Cannot plot realtime (slow,delay)

Hi

Intention:
Realtime plot an ECG Signal from Arduino’s ADC (sent from Arduino–>RaspberryPi–>LAN–>ClientPC–>Processing).

Problem:
The plotting in processing somehow lags/delays behind realtime.

In depth:
I use a EGC signal generator to feed an Arduino ADC. The data is sent
to the serial output every 2 milliseconds, thats the arduino code for that:

void setup() {
  Serial.begin(38400);
}
void loop() {
  Serial.println(analogRead(0));
  delay(2);
}

That should give about ~500 sps/s. I am not sure if my serial speed of 38400baud is enough for that but on the RaspberryPi I am receiving
7046 values per second, that is roughly 2 milliseconds and I think this is not the cause of the lag.

Then, on the raspberryPi I relay the pakets from /dev/ttyUSB0 to the ClientPc over LAN

raspberryPi;

socat /dev/ttyUSB0,raw,echo=0 tcp:ClientPcIP:8888

Arriving at the ClientPc I still get about 7040 lines of data per second which is again ~2ms.
So I rule out any bottlenecks over the LAN…

But then when I plot the data with this code:
import processing.net.*;

int SERVERPORT = 8888;
Server myServer;
String myString;
float inByte = 0;
float yPos = 1;
int xPos = 1;
float yPos2 = 1;
int xPos2 = 1;

void setup() {
  size(800, 300);
  myServer = new Server(this, SERVERPORT);
  background(255);
}

void draw() {
  Client thisClient = myServer.available();
  if (thisClient != null) {
    if (thisClient.available() > 0) {
      myString = thisClient.readStringUntil('\n');
      if (myString != null) {
        myString = trim(myString);
        inByte = float(myString);
        yPos = map(inByte, 0, 1024, 0, height);
        //point(xPos,yPos);
        xPos++;
        line(xPos2, yPos2, xPos, yPos);
        if(xPos >= width){
         xPos = 0;
         background(255);
        }
        xPos2 = xPos;
        yPos2 = yPos;
      }
    }
  }
}

the plot runs from left to right very slow.
I recorded a video to show what I mean. I first show how ArduinoIDE Serial Plotter plots in realtime, then I start sending the data over lan to processing and you can see how slow it runs there:

I then wrote a simple code to count the time that it needs to receive 1000 pakets (data lines) in processing:

import processing.net.*;

int SERVERPORT = 8888;
Server myServer;
String myString;
float inByte = 0;
float yPos = 1;
int xPos = 1;
float yPos2 = 1;
int xPos2 = 1;
int counter = 0;
int startTime = 0;
int endTime = 0;
void setup() {
  size(800, 300);
  myServer = new Server(this, SERVERPORT);
  background(255);
}

void draw() {
  if(counter == 0){
    startTime = millis();
  }
  Client thisClient = myServer.available();
  if (thisClient != null) {
    if (thisClient.available() > 0) {
      myString = thisClient.readStringUntil('\n');
      println(counter + "-->" + myString);
      counter++;
      if(counter == 1000){
        endTime = millis();
        println((endTime-startTime)/1000);
        println("EXIT OK");
       exit(); 
      }
    }
  }
}

It takes 16 seconds for 1000 data lines which gives about 16ms per sample. This is 8 times more than expected of 2ms.

Does someone have an idea what I am doing wrong? Is this maybe something buffering related in processing? I never had anything to do with buffering…

1 Like

I possibly found the problem…
the 16ms might correspondent to 60Hz refreshRate which seems
to be default…

So I guess I need to set the refreshRate to at least 500Hz to draw every data line with 500sps/s.

possibly the main problem is you try to print best case 500 lines per second
with println from inside draw.
pls give that line a diagnostic en/disable

boolean diagp = false;
//..
void draw() {
  if ( diagp ) println(...);
//..
}

void keyPressed() {
  if ( key == 'p' ) diagp = ! diagp;
}

other thing i see is

  Client thisClient = myServer.available();

60 times per second too?

-a- better have a readStringUntil in a external function
and feed its result ( int ) to an int array ( long as pixel you later use in your line plot )
-b- the draw should just plot the current array content of the array.

1 Like

Thanks, with refreshRate(600) everything seems to run smooth and real time now.
But as you wrote, I think there is a lot of optimisation possible in my code even that the java process is just using 8% Cpu load…

I did a personal exploration of this and sharing.

Arduino (Serial) to Processing (Serial Rx and Server Tx) to Processing (Client Rx) :

  1. Send (delimit) a larger “packet” of data; I sent a “space” (" ") after 16 values.
    I used println() for each value which delimits each value with a “\r\n”.
    I sent some modulated data (int) from the Arduino with a range of 0 to 1023.
  2. Processing receives “serial data” and “network server” relays data to “network client”.
    I used:
    https://processing.org/reference/libraries/serial/serialEvent_.html
    and buffered until the “space” (" ")
    This does not rely on reading during each frame.
  3. “Network client” received data and plotted.
    I read the string until “space” (" ") and then processed that data (trim, spit, parse) and then plotted it.
    This kept up with incoming data at 60 fps and 19200 baud.

You have a 2ms delay for A2D conversion.
Consider:

I did this rather quickly and juggled some math and everything seemed to sync; there is a lot of finessing that can be done I am confident.

:slight_smile:

2 Likes

Thanks @glv,
are you willing to share your processing code? I ask because I still dont get it.
You used “network server”and “network client” in your code together with serialEvent even if you dont have a Serial port defined?
My throught on this was rather using a serverEvent or clientEvent… but I still did not understand its concept…

Well I dont care for the first readings nor do I have a high impedance signal (its an Opamp output) nor do I read from multiple pins :slight_smile: