We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Hello there,
I've been dealing with a RFID reader:
http://forum.processing.org/two/discussion/12920/problem-reading-a-rfid-reader http://forum.processing.org/two/discussion/13077/how-to-load-save-data-from-serial-port-to-a-txt-file
What I want is that a card that hasn't been read previously is read, it displays an image for a certain amount of time. The thing is that this times varies randomly and I don't know why.
For example: now is set to 25 seconds (25000 milliseconds), I tried with one card and the image was displayed for 17 seconds, I tried another card and it was displayed for 22 seconds, and 19 seconds with a third card.
GoToLoop pointed (here) something about synchronized
, and I've been reading about it but I still don't get it (in case this might be the solution).
Any ideas? Thanks!
This is the code:
import processing.serial.Serial;
String mensaje = "Texto inicial";
int tiempo; // this line and the next is for the delay time of the image
int espera = 25000;
PImage imagen;
int contador = 1;
Table table;
void setup() {
size(900, 600);
frame.setBackground(new java.awt.Color(0, 0, 0)); // fullscreen moder with black background
imagen = loadImage("1.jpg");
String[] portas = Serial.list(); // load serial port
printArray(portas);
new Serial(this, portas[0], 9600).bufferUntil(ENTER);
tiempo = millis();
table = loadTable("data.csv", "header"); // load the table with "id" and "state"
table.setColumnType("state", Table.INT);
println(table.getColumnTitles());
println();
println(table.getColumnTypes());
println();
}
void draw () {
TableRow result = table.findRow(mensaje, "id"); //here i find the row with the ID i get from the serial port
int state = result.getInt("state"); //here i get the value of the state of the id read by the serial
if (state == 1) { // if state is 1, wich means false, which means that is the first time the card is read, then show the image
imageMode(CENTER);
image(imagen, width/2, height/2); // show the image
if (millis() - tiempo >= espera) { //wait 25 seconds
tiempo = millis();
contador++;
result.setInt("state", 2); // here i change the value of state
// saveTable(table, "data/data.csv"); // i save the table for any future run of the program - IS NOT WORKING
}
} else { // if state is 2, it means that the card was used, so don't display anything
background(0);
}
}
void serialEvent(Serial s) {
mensaje = s.readString().trim();
}
This is the data I'm loading. 1 is for "haven't been read", 2 is for "has been read"
Answers
Hi GoToLoop, I've been really busy @ university and haven't had time to give attention to your answer.
My proble. Is that I don't know how to implement your suggestion into my code. I see that your timers work perfectly but I don't know how to apply this into my sketch. Any tips?
Thanks!
In order to adapt my example to yours you need to comprehend what I did.
You need to be more specific about which part(s) you don't get.
Main difference is that your sketch got 1 String mensaje & 1
int
tiempo.And in case another matching readString() arrives in serialEvent() mensaje is overridden, even though the tiempo for current 1 hasn't finished yet!
In order to keep track for each readString() mine relies on an IntDict container called idTimers:
https://Processing.org/reference/IntDict.html
Therefore each approved id is paired up w/ an
int
value representing how much time it is displayed till it's remove().The first time I read a card the time is displayed is worng, how could this be if mensaje hasn't been override yet? (though I get your point here)
I'll try your code tomorrow with the serial reader as i dont have it here. thanks
I haven't created my own "data.csv". Instead I've made a mini sample String[] array called CSV[].
Unfortunately loadTable() doesn't work w/ arrays. So I had to turn CSV[] into some ByteArrayInputStream in order to instantiate a Table w/ that.
In other words, you can get rid of both since you've already got your own ".csv" file. :ar!
It's roughly the same as
HashMap<String, Integer>
. But its keys are ordered like a List. And its values useint
rather than Integer.An Iterator is like the old Enumeration:
http://docs.Oracle.com/javase/8/docs/api/java/util/Enumeration.html
It's what an enhanced
for ( : )
loop relies on behind the scenes.The reason why I couldn't use
for ( : )
and had to depend on an Iterator +while ()
loop is b/c I'm using remove():http://docs.Oracle.com/javase/8/docs/api/java/util/Iterator.html#remove--
And we can't use remove() inside enhanced
for ( : )
loops.And neither we can traverse an IntDict w/ some regular
for ( ;; )
b/c its keys are String and not numerical. :(I'm caching current millis() & IntDict's size() as local variables till the end of draw().
Local variables ids[] & expires[] are just to store respectively IntDict's keyArray() & valueArray().
So they can be displayed later @ here:
Again, thanks for the detailed explanation. But I lack the knowledge to fully understand your code, I mean, I get your point but there are several "java codes" that I still don't get (and I'm in a rush now :( ), so I'll try to figure a way to display images without using millis, i.e. you swipe one card and one image is displayed until you swipe another card. Or something similar.
Thanks!