Hi,
I made a lot of cases to trigger them with the keyboard. Now, I wish I could sequence the cases in a special order and manage their duration.
For example with the Arduino IDE, I made case ‘0’ and case ‘4’’
In void loop, i manage the sequence and the duration like this :
void loop() {
static uint8_t ETAT = 0; // begin with the case '0'
static float reftempsGENERAL = millis(); // time in the loop is in milliseconds
switch (ETAT) {
case 0:
yoyo45to75 (45, 16); // do yoyo45to75--> speed 45 to 75 for 16s
yoyo75to60 (75, 16*2); // do yoyo75to60 --> speed 75 to 60 for 32s
yoyo60to45 (45, 16*2); //
if(millis() - reftempsGENERAL > 16000*5) { // if time is upper than 16000 millisecond*5 --> switch on CASE 4
reftempsGENERAL = millis();
ETAT=4;
/* TEST IF MOTOR STOP AT THE GOOD POSITION
for(uint8_t i = 0; i < 5; i++) {
setMoteur(i, 0);
}
while(1);
*/
}
break;
case 4:
recallage2to60 (60,8); // MOVE MOTOR TO THE SECOND ONE
if(millis() - reftempsGENERAL > 8000) { // IF time > 8 sec go back to case 0
reftempsGENERAL = millis();
ETAT=0;
/*
for(uint8_t i = 0; i < 5; i++) {
setMoteur(i, 0);
}
while(1);
*/
}
break;
}
And later, would it be possible to directly select my cases with the keyboard and have a program record the keys and the duration between them. So that this program will sequence the cases as it recorded it?
This second question is less important than the first for now but maybe it’s simpler to program.
So I’ll every option you propose to me!!
Thank you for your help and your kind lights.
You can see below the way I coded my case.
void keyPressed() {//**** faire position de base à l'arret avec ecrart equidistant qui s'incrementent entre G et le chiffre
// SET POSITION
if (keyCode == CONTROL) { println(" GO to NEXT POSITION "); // Faire control -
for (int i = 0; i < net.networkSize; i++) {
// net.phase[i] += net.phase[i]+2*PI/net.networkSize;// (incremente ecrat des dernieres phases --> si nul elles n'evoluent pas
net.phase[i] = net.phase[i]+2*PI/net.networkSize; // (faire un nouvel ecart à corrélé selon l'ecart precedent )
// net.phase[i] += 2*i*PI/net.networkSize; // positionne avec un ecart qui s'increment et se supperposent les uns sur les autres
print ("phase "); print (i); print (" ");
print (net.phase[i]); print (" ");
print ("frequency "); print (i); print (" ");
println (net.naturalFrequency[i]);
}
}
// SET POSITION
if (keyCode == ALT) { println(" SHIFT POSITION "); // Faire ALT -
for (int i = 0; i < net.networkSize; i++) {
net.phase[i] += net.phase[i]+2*PI/net.networkSize;// (incremente ecrat des dernieres phases --> si nul elles n'evoluent pas
// net.phase[i] = net.phase[i]+2*PI/net.networkSize; // (faire un nouvel ecart à corrélé selon l'ecart precedent )
// net.phase[i] += 2*i*PI/net.networkSize; // positionne avec un ecart qui s'increment et se supperposent les uns sur les autres
print ("phase "); print (i); print (" ");
print (net.phase[i]); print (" ");
print ("frequency "); print (i); print (" ");
println (net.naturalFrequency[i]);
}
}
//*********************** ADDING "LIVE" in the hole movement
if (key == 'Q') {println ("Noise in Phases");
background (0);
for (int i = 0; i < net.networkSize; i++) {
// net.phase[i] = TWO_PI * noise(i*0.1);
net.phase[i] = net.phase[i] + noise(i*0.1); // Add noise in former
print ("phase "); print (i); print (" ");
print (net.phase[i]); print (" ");
print ("frequency "); print (i); print (" ");
println (net.naturalFrequency[i]);
}
}
if (key == 'q') {println ("Noise in Frequencies");
background (0);
for (int i = 0; i < net.networkSize; i++) {
net.naturalFrequency[i] = TWO_PI * noise(i*0.1); //p0.01 to begin slower
print ("phase "); print (i); print (" ");
print (net.phase[i]); print (" ");
print ("frequency "); print (i); print (" ");
println (net.naturalFrequency[i]);
}
}
record times based on millis() instead of frameCount. But that requires more logic, you can’t compare times using == as a specific time in milliseconds may happen between two animation frames.
Allow recording any keys. Then you can’t store the variables as int.
/*
expects a csv file named "planer1.csv" like (without spaces before each line). The millis is the absolute time since the sketch has started; this is when the line starts
millis,command,param1,param2
0,11,45,16
1222,20,75,32
2444,30,45,32
4566,40,12,
7000,50,12,
*/
// data for show
Table planer;
// example
EllipseMy[] ellipseMy = new EllipseMy[6];
// ------------------------------------------------------------------------------
void setup() {
size(900, 400);
// load
planer = loadTable("planer1.csv", "header");
//prepare example
for (int i=0; i < ellipseMy.length; i++) {
ellipseMy[i]=new EllipseMy(66+i*100);
}//for
}//func
void draw() {
background(0);
// show row number
int rowNumber = findRowNumberToExecute();
text(rowNumber, 100, 100);
//run commands
if (rowNumber>-1) {
doCommand(rowNumber);
}//if
//example
fill (255, 1, 1); // RED
for (int i=0; i < ellipseMy.length; i++) {
ellipseMy[i].display();
}//for
}//func
// ------------------------------------------------------------------------------
void doCommand(int rowNumber) {
TableRow row = planer.getRow(rowNumber);
int commandFromTable = int(row.getString("command"));
int param1FromTable = int(row.getString("param1"));
int param2FromTable = int(row.getString("param2"));
text(str(commandFromTable) + " -> with "
+ param1FromTable
+ " and "
+ param2FromTable,
width/2, 111);
switch(commandFromTable) {
case 11:
ellipseMy[0].y+=-1;
break;
case 20:
ellipseMy[1].y+=-1;
break;
case 30:
ellipseMy[2].y+=-1;
break;
case 40:
ellipseMy[3].y+=-1;
break;
case 50:
ellipseMy[4].y+=-1;
break;
default:
// ignore
break;
}//switch
}//func
int findRowNumberToExecute() {
boolean prevRow=false;
int result = -1;
for (int i = 0; i < planer.getRowCount(); i++) {
TableRow row = planer.getRow(i);
int millisFromTable = int(row.getString("millis"));
if (millisFromTable>millis()) {
// found
prevRow=true;
result=i-1;
break;
}//if
}// for
// found
if (prevRow) {
return result;
}//if
// no found
return -1;
}//func
// ============================================================================
class EllipseMy {
int x, y=height-66;
EllipseMy(int x_) {
x=x_;
}//constr
void display() {
ellipse(x, y, 17, 17);
}//method
//
}//class
//
It relies on the order of millis. Each Line has a milliseconds value that tells the line when to start (or the previous line to end).
There is only one active line at any given moment.
Improvement could be to have a start and a stop time (in millis) and use this. Then you could have multiple tasks at once.
Each line has a command number that can be evaluated and executed in function doCommand(). It has also 2 parameters you could pass to your function yoyo75to60().
There are things to discuss though. For example when you load a lot of images in setup() the assumption that the millis() are 0 at start of draw() is wrong. Therefore we could set a timer at the end of setup() and define it as 0.
Also when we have processes we don’t know how long they take (ball flies to target) the program could wait until the event happens. Only then the next task would be started.
But then the following millis values would have to be relative to this event and not absolute (from the start of the sketch) anymore.
I have tested yours programs. But the second one have a bug here
theKey = int(split(lines[index], ‘:’)[1]);
Processing says:
ArrayIndexOutOfBoundsException: 0
May be I have to mix your 2 program to record a sequence ( with the good time between case) but I m not be able to do that.
Actually I would like to trig event one after one. I have several motors turning at different speed with only one case.
I would like the simulation of speeds to be close to reality. Maybe recorded time with FrameCount will be the same as millis()
Here you can see a simulation (in French sorry).
When motors change speed or way of rotation that’s mean I have changed cases.
So now I have to test your programs.
Could you mix them for me?
You either copy the file produced by program 1 into program 2, or you use an absolute path in both cases like /tmp/data.txt or C:/some/folder/data.txt. I’m not on Windows so not sure how you make absolute paths in Processing on Windows.
I think you can also drag and drop the data.txt file into the second sketch.
You are absolutely right.
But, for the moment, I will try to motorize the above simulation hoping that the motors react in “real time”. I will get back to you after a few tests. Thank you.
Sincerly
Hello !
Yours programs to record and play the key pressed work perfectly.
But I would like to be able to use letter and the others keys like , ; / *.
Is it possible to you?
Please.
In the saving program (the first), you only need to change the line that saves the pressed key:
void keyPressed() {
if (key == ESC) {
output.flush();
output.close();
exit();
} else {
if(key != CODED) { // this `if` to ignore keys like shift, ctrl, alt
output.println(frameCount + ":" + (int)key);
}
}
}
This will make it save the ascii code that represents the pressed key.
In the second program you need to change the variable called theKey so it is char instead of int. At the top:
int index = 0, nextFrame = 0; // these stay the same
char theKey; // this becomes a char
and when setting the value we cast to char:
theKey = (char)int(split(lines[index], ':')[1]);
With these changes it will no longer save the pressed character, but a number that represents that key. When loading, it will convert that number to a character.
Waaa! Thank you so much. As the solution looks simple for you.
And to finish ( I have forgotten what I need), could you adapt yours programs in the manner it could record and play CONTRL, ALT and the ARROW?
Please.
I have just tried to use the last saver program but it doesn’t seem to work. There is no data recorded in the sketch folder, whereas I worked very well in the program recording key and letter.
Hi! Please change the path to suit your needs. In my latest example I was using /tmp/data.txt because that’s what works best for me for a temporary file. That’s a path in the root of my drive, not in the sketch folder.
Thanks again.
I can see all ascii code now .
But I can’t manage to play event (here it’s just printing something) from the key and/or from the key code recorded, in order the playback program play them as a real keys pressed() .
I have tried to split my void keyPressed() in two part but it doesn’t work because this function is waiting a KeyEvent.
It’s the last part of my program, i really need you.
Special thank
I show you what I have tried in the playback program
Hi! Sorry for replying so slow, I’ve been offline a bit…
Issues I see in the last program:
there is void keyPressed(theKeyCode) but then you check if(keyCode == DOWN) instead of using if(theKeyCode == DOWN). I guess it’s also missing int before theKeyCode right? Otherwise it would not compile…
As it stands, keyPressed would be called for every animation frame. Maybe you should move keyPressed(theKeyCode) inside the previous if statement, right after readOneLine() so it is only called at the right time when the key was pressed?