Hi,
I am creating a graphic user interface for a machine controled by an arduino
The arduino sends serial data to processing at 120 SPS and my monitor displays 60 images per second. the only way to draw those values on a graph in real time is to draw two points at the same time.
My problem is that the draw loop does not repeat more than 60 times per second to receive the serial data in real time.
I know the best solution would be a thread but it’s too complex for a noob like me.
What is the easiest solution to make processing work faster ?
Hi quark,
I saw on a forum that even if you write frameRate(120); ,the draw() function will still not be faster than the framerate of the monitor.
I also saw that the serialEvent() works as a thread on processing but on another forum, someone said the opposite.
In Processing the frameRate(float) statement determines how often the draw() method is executed. At 120fps the rendered frame is made available to the graphics card every ~8ms
With modern displays the term is ‘refresh rate’ i.e. how often the display is updated, a 60Hz monitor will refresh the display 60 time a seconds, a 120Hz will refresh at 120 times a second so have a look at a faster monitor.
To be honest I do not believe the viewer can differentiate between
2 points being added every 1/60 of a second and
1 point being added every 1/120 of a second.
The human eye cannot detect changes that quickly, if you go to a movie the standard projection is 24fps and no one notices.
Thank you for your answer but that was not really my question.
My goal is to make my program work on any 60hz monitor so the only option is 2 points being added every 1/60 of a second, but that is not a problem.
My problem is that I have to work with serial data in real time so there is no lag and this data arrives 120 times per second.
If the serialEvent() works as a thread, that would be the best solution. But if I understood correctly, it is triggerd each time after the draw function.
With the frameRate(120) method, I wrote the code below but there is no difference with 60 SPS from the arduino.
boolean draw_state = true ;
public void setup(){
frameRate(120);
}
public void draw(){
Serial operations
if (draw_state == true) {
Drawing operations
draw_state = false ;
}
else {
draw_state = true ;
}
}
I know but on the arduino reference of serialEvent(), it is also writen “Called when data is available”, yet it does not work as a thread. On the arduino, the availabilty of data is checked after each execution of the loop() and then serialEvent() can be triggered.
So I don’t know it is the same method on processing or not.
AFAIK the serialEvent() is executed every time data is received by Processing so maybe executed several times every frame. Also AFAIK this occurs on a separate thread so Processing might execute serialEvent() while it is in the middle of the draw() method. This is a problem because the two threads are trying to share the same data store.
The solution is to use a thread safe collection e.g. java.util.concurrent.LinkedBlockingQueue
Since I don’t have an Arduino device I am using a separate thread to simulate data being generated and stored in a queue. This video shows it in action.
Sketch Code:
import java.util.concurrent.*;
int[] c = new int[100];
BlockingQueue<Integer> bq = new LinkedBlockingQueue<Integer>();
int dataSent = 0;
int dataReceived = 0;
boolean createData = true;
public void setup() {
size(600, 200);
frameRate(60);
strokeWeight(1);
stroke(0, 0, 128);
fill(0);
textSize(16);
thread("generateData");
}
void draw() {
background(255, 255, 200);
// Take any data off the queue and add it to the array
Integer data;
while (null != (data = bq.poll()) ) {
c[data]++;
dataReceived++;
}
// Display the array of data received
for (int i = 0; i < c.length; i++) {
line(0, i, c[i], i);
}
// Display stats - note we do not loose any data and the amount of data
// processed every frame depends on how fast it is generated.
text("Data sent " + dataSent, 20, 120, width - 40, 20);
text("Data received " + dataReceived, 20, 140, width - 40, 20);
float datarate = ((float) dataReceived ) / frameCount;
text("Data processed per frame " + datarate, 20, 160, width - 40, 20);
}
/**
This is to simulate the serialEvent method where the data
received will be placed on the queue.
*/
void generateData() {
while (createData) {
int d = (int)random(0, c.length);
try {
bq.put(d);
dataSent++;
delay(2); // 2 ms so we are creating 500 data elements per second
}
catch(InterruptedException e) {
println("Interrupted");
};
}
}