We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Here is the thing, I'm trying to comunicate with arduino to create a robot, right now processing will send information for how the robot will move and when I press the key 'g' it will work like a switch to activate the sensors in the arduino and get the values, here is the code
import processing.serial.*; //use the Serial library
Serial myPort;
boolean keyup = false;
boolean keyright = false; // Booleanos de las teclas que se presionan
boolean keyleft = false;
boolean keydown = false;
boolean sensor = false;
float x,y;
boolean loop = false;
int inByte;
void setup() {
size(200, 200); //set window size to 200 by 200 pixels
String portName = Serial.list()[0]; //list serial ports, save the first one as portName
myPort = new Serial(this, portName, 9600);
}
void draw() {
background(255);
loop = sensor;
while(loop == false){
if (keyup && !keydown && !keyleft && !keyright) { myPort.write('w'); println('w'); }
if (keyup && !keydown && keyleft && keyright) { myPort.write('w'); println('w'); }
if (keyup && !keydown && keyleft && !keyright) { myPort.write('q'); println('q'); } // Dependiendo de la combinacion de letras que lee es la letra que manda
if (keyup && !keydown && !keyleft && keyright) { myPort.write('e'); println('e'); } // Para hacer de el teclado "asdw" un teclado de 9 botones
if (!keyup && !keydown && keyleft && !keyright) { myPort.write('a'); println('a'); }
if (!keyup && !keydown && !keyleft && keyright) { myPort.write('d'); println('d'); }
if (!keyup && keydown && !keyleft && !keyright) { myPort.write('x'); println('x'); }
if (!keyup && keydown && keyleft && keyright) { myPort.write('x'); println('x'); }
if (!keyup && keydown && keyleft && !keyright) { myPort.write('z'); println('z'); }
if (!keyup && keydown && !keyleft && keyright) { myPort.write('c'); println('c'); }
if (!keyup && !keydown && !keyleft && !keyright) { myPort.write('s'); println('s'); }
loop = sensor;
}
while(loop == true){loop = sensor;} // Si se presiono sensor sigue hasta que la condicion de presionado cambie
while(loop == false){ // Se asume que el boton de sensor se solto
myPort.write('g'); // pide informacion al arduino
inByte = myPort.read(); // lee la informacion
println(inByte); // la escribe en processing
if (keyup && !keydown && !keyleft && !keyright) { myPort.write('w'); println('w'); }
if (keyup && !keydown && keyleft && keyright) { myPort.write('w'); println('w'); }
if (keyup && !keydown && keyleft && !keyright) { myPort.write('q'); println('q'); }
if (keyup && !keydown && !keyleft && keyright) { myPort.write('e'); println('e'); }
if (!keyup && !keydown && keyleft && !keyright) { myPort.write('a'); println('a'); }
if (!keyup && !keydown && !keyleft && keyright) { myPort.write('d'); println('d'); } // manda informacion de movimiento al arduino
if (!keyup && keydown && !keyleft && !keyright) { myPort.write('x'); println('x'); }
if (!keyup && keydown && keyleft && keyright) { myPort.write('x'); println('x'); }
if (!keyup && keydown && keyleft && !keyright) { myPort.write('z'); println('z'); }
if (!keyup && keydown && !keyleft && keyright) { myPort.write('c'); println('c'); }
if (!keyup && !keydown && !keyleft && !keyright) { myPort.write('s'); println('s'); }
loop = sensor;
}
while(loop == true){loop = sensor;} // mantiene el ciclo hasta que se suelta el sensor para salir de ese modo
}
void keyPressed() {
if (key == 'w' || key == 'W') keyup = true;
if (key == 's' || key == 'S') keydown = true;
if (key == 'a' || key == 'A') keyleft = true; // Si alguna de las teclas esta presionada hace true el booleano
if (key == 'd' || key == 'D') keyright = true;
if (key == 'g' || key == 'G') sensor = true;
}
void keyReleased() {
if (key == 'w' || key == 'W') keyup = false;
if (key == 's' || key == 'S') keydown = false;
if (key == 'a' || key == 'A') keyleft = false; // Si la tecla no esta presionada hace false el booleano
if (key == 'd' || key == 'D') keyright = false;
if (key == 'g' || key == 'G') sensor = false;
}
Excuse the anotations in spanish, the code should be self explanatory for slightly more advanced programmers, my mates and I are kind of noobs (if you want english anotations please ask)
Anyway, in the void draw the keyPressed and keyReleased functions should be called automatically, and they do, when I do
loop = sensor;
the action is done, but after entering the first while all my code does is read the values before the while and wont let me press any keys to change how the robot will move or to get out of the while. Please help How do I explicitly call the void keyreleased within my whiles, or how do I fix the problem?
Answers
The problem is the while loops in the draw method. The draw method is called (~60 times per second) is part of the main event loop. So if you consider line 49 you have
while(loop == true){loop = sensor;}
If
loop
is true then the code loops untilsensor
is false but that only happens when theg
key is released but that can't happen because the keyPressed method is also on the main event thread but the program is stuck on the draw method.You need to revisit the program logic to get rid of the loops in draw. I suggest that you start by simply changing the
while
(s) withif
(s) and see what happens.To add to what quark said above:
You're in the false assumption that Processing's event functions like keyPressed() and such would be asynchronous.
That is, erroneously thinking they'd run in parallel to draw() as separate threads! :O
If you were programming in a .Net Framework language like C#, that'd much probably be so.
Thus, such blocks like:
won't ever break free, b/c keyPressed() wouldn't be reached in order to toggle sensor variable, while draw() is running! b-(
You gotta change your approach then. A good 1 is to turn off auto draw() calls w/ noLoop().
And then use redraw() within keyPressed() & keyReleased() to control whether to run draw() or not. :-B
A more advanced 1 is to turn your code inside draw() into another Thread function.
That way, your strategy of awaiting for sensor would work alright,
b/c your threaded function and Processing's event functions would run at the same time! $-)
To go along w/ this 1, just transfer your main code into some function;
and use thread("function name") inside setup() to ignite it! :bz
And a template using noLoop() & redraw(): <):)
Just to add a bit more of clarification for everybody's education:
Events are collected asynchronously meaning that there's a separate thread which is collecting all mouse and keyboard events. However this thread only saves events in the internam memory buffer.
Processing sketch, meanwhile will be notified about those evens via keyPressed() mouseMoved() and other event methods, but only on MAIN DRAWING THREAD.
Because these methods will be called on the main event thread, when you stall the thread with your
you will not be notified of them. (All the events are collected, but they are in memory buffer somewhere in the memory of your computer, but your sketch is not notified of them).
Your app is stalling main app thead similarly to this example:
If you run this sketch, you can see that all events are actually collected (and saved/queued in internal memory somewhere) but only once per 10 seconds, after the draw() has finished executing they will become known to your sketch.
First of all you guys are fantastic. Second, as I thought about it I figured that a way to go would be the second one that GoToLoop mentioned, a problem with the first solution is that (to my understanding) this method involves having the sensor key pressed all the time to collect sensor values, where what I'm looking for is to use it as a latching state switch (not sure how to say this in english, and it's more of an electrical term). I will try to do the separate thread kind of solution, but' I'll also run the other one to compare results... anyways thanks guys, I have only used processing very few times and I mostly use C languages instead of JAVA so I feel lost. I'll post what happens ASAP.
So you wanna toggle the key states, like a light switch? If so, only keyPressed() is needed! ;)
The pair keyPressed() + keyReleased() is used for games! (*)
I'm actually looking for the videogame approach, since it will later go to a robot (I think that a robot or a videogame car might work the same in terms of direction), with sensor the idea is that if you press 'G' the sensor is on and even if you release said key it's still on, if you press it again it'll change to off, and so on... tried the thread solution really quickly and it didn't load keypressed at all, do I have to call it in thread or do you think it's a synchrony issue?
Well, you can mix both approaches for keys. Since only 'G' needs to be toggled for each keyPressed(), we set that apart.
The other keys are active as long as they're being pressed down. *-:)
Also, I've got an online example which uses the mixed approach. Space or Enter keys toggle rect/ellipse shapes! :-h
Take a look at it here: http://studio.processingtogether.com/sp/pad/export/ro.9bY07S95k2C2a/latest