Serial USB communicating with increasing time gaps

Hi,

I’m working with two Arduino DUEs, one receives commands from the computer over the programming port and then turns on and off pumps based on sensor data, the other is set up just to check the value of a phototransistor and transmit the values over Serial USB to the computer. From there, I’m using Processing to put all the values in an Excel sheet I can do stuff with after. Ideally, I’d get a continuous stream of sensor readings but that’s impossible so I’m trying to get as fast a rate as possible.

The code seems to work fine initially with the DUE that is just recording the sensor values getting about 4 values per millisecond, which is fast enough for what I need. Over time, gaps seem to appear in the data. At first these gaps are about 2000 milliseconds long and then grow to about 5000 milliseconds long. I’ve looked through the forums and google and haven’t found any solutions or other people with a similar problem (that I could see).

Here’s the code for the DUE that is reading the sensors:

void setup()
{
    SerialUSB.begin(115200);
    delay(5000);
}

void loop() 
{
    SerialUSB.print(millis());
    SerialUSB.write(',');
    SerialUSB.println(analogRead(A0), DEC);
}

And here is the Processing Code I’m using:

import processing.serial.*;

Serial myPort;
Table dataTable;
Table table;
String fileName;

void setup()
{
    fileName = "Data/20Amps/Test1.csv";
  
    println(Serial.list()[0]);
    
    myPort = new Serial(this, Serial.list()[0], 115200);
    dataTable = new Table();
     
    dataTable.addColumn("id");
    dataTable.addColumn("Time");
    dataTable.addColumn("Sensor Reading");
    
    saveTable(dataTable, fileName);
}

void serialEvent(Serial myPort)
{
    try {
String val = myPort.readStringUntil('\n');
   
   if(val != null)
   {
       val = trim(val);
       
       int values[] = int(split(val, ','));
       
       TableRow newRow = dataTable.addRow();
       
       newRow.setInt("id", dataTable.lastRowIndex());
       newRow.setInt("Time", values[0]);
       newRow.setInt("Sensor Reading" , values[1]);
              
       saveTable(dataTable, fileName);
   }
  }
  catch(RuntimeException e) {
    println("Error");
  }
}

void draw()
{
  
}

I’ve attached a chart of the ‘Time’ values the DUE is providing just as an example. It should be a nice straight line but there are bigger and bigger steps/jumps in it as time goes on.

Any advice or links to something that would solve this would be greatly appreciated. Thanks!

Example Error Graph.png

It is most likely the PC side of the USB not reading it fast enough. I can't offer much advice there.

But your sender is just sending as fast as it possibly can. Remember the SerialUSB ignores the baud rate. (It is actually much faster than 115200.) So the baud rate doesn't hold down the sample rate to a consistent speed. Use a blink-without-delay timer (using micros()) to set your sample rate at a specific speed which is within the PC's capabilities.

Thanks for your help!

I actually switched from using just Serial to SerialUSB because of the faster transmission rate but maybe that isn't being handled well by my computer. Would it be better to use the timer as you've suggested to make the transmission rate more manageable or to switch back to using Serial instead of SerialUSB and increase the baud rate/decrease the data transmitted?

I read about making Serial faster and ideally I would like to keep a sampling rate somewhere near or above 4 samples/millisecond to get a nice plot (I'm observing something that occurs in about 6-8 milliseconds), but that might not be possible... Are there any other solutions out there that might help keep a sampling rate that high? Or should I look into the computer side of things since it seems to manage it at some times and not at others?

Thanks again!

Edit: I was also looking at other ways of storing the data on my computer if that might speed it up (i.e. if the hold up was Processing), and I was wondering what might be the fastest way to store all of the values I'm getting in a way I could use with Excel?

So set up a timer like Blink-Without-Delay that takes a sample every 250us. A stream of analog readings is much more useful if it has a specific period that doesn't change. Remember that micros() works in steps of 4us, so you won't ever get exactly 250us between samples and it's more likely to be much greater than this because your main loop will take 10-100us to execute.

If you find that the jitter is unacceptable, then you must use a timer interrupt to trigger the analog conversion.

analogRead() is deliberately rather slow on the Arduino. There are a number of ways of speeding it up. Some of them involve register manipulation to reduce the precision of the ADC converter but increase its speed of conversion. But the last time I tested it, the standard analogRead() was good for 10 reads per millisecond if you did nothing else.

The communication to the computer can be accelerated significantly by sending binary values instead of text. Send a start byte, four bytes of the millis() reading, two bytes of the analog reading and (optionally) an end byte. This should make your system at least twice as fast. It also saves some computation time in the numeric-to-text conversion.

Excel loves tab-seperated files. If you have a file with tabs in it and you name it ".xls" then Excel will open it as if it is a normal spreadsheet.

Thanks for your help, I tried a rather crude solution and it seemed to work so I've just been using that. I just opened the Arduino Serial Monitor and that never had any gaps, so I just copy and pasted the output into a text file and saved it to a ".csv" format file. It's not elegant but it worked for me, but I'm not sure why the Serial Monitor works and Processing doesn't. :relaxed: