Speeding up Serial Print

Hi, I need help to increase speed up send Serial Data using Serial.print

for(int i = 1; i<=200; i++){
    
  //timer = micros();
  val1 = (float)analogRead(analogPin1)* (3.3/4095);
  val2 = (float)analogRead(analogPin2)* (3.3/4095);
  val3 = (float)analogRead(analogPin3)* (3.3/4095);
  val4 = (float)analogRead(analogPin4)* (3.3/4095);

   
  //timerb = micros();

  

  Serial.print(i);
  //timerb = micros();
  Serial.print(",");

  Serial.print(val1,4);
  Serial.print(",");
  Serial.print(val2,4);
  Serial.print(",");
  Serial.print(val3,4);
  Serial.print(",");
  Serial.print(val4,4);
  Serial.print(",");
 
}

thats the loop Im working with right now,
Im using a baudrate of 614400 successfully as processing is getting correct data (no higher baud rate i tested works), I just need the Serial.prints to be faster because right now that block of code takes about 580us.

I've seen solutions like this

char asdf[32];
  snprintf(asdf,32,"%d, %d, %f, %f, %f, %f,",timer-timerb,i,val1,val2,val3,val4);
  Serial.print(asdf);

but this actually takes longer.. Ive seen a modified HarwareSerial.cpp that I tried using on another post, didnt work.

Ive seen some stuff on using the native programmer port? I dont know whats the difference

Anybody got some clever solution??

Thanks in advance

Which Arduino?

The Arduino Due native USB port is very fast. The Teensy is also fast.

But what are you really doing? Why not send the raw anlogRead() data which is 2 bytes per reading instead of 6 bytes worth of floating-point? Do the complex calculations on the receiving end.

thanks for the quick reply and great advice! I will definitely change that on the processing side but I just tested on the arduino side and the Serial prints perfom faster but only sped up from 580 us to 360us.

I was hoping for something sub 100us.. is this possible?

And I am using the arduino due. You say the native port is fast what does this mean? Serial prints will perform faster? I can use a higher baud rate?

Thank you!!

philipjfry:
Hi, I need help to increase speed up send Serial Data using Serial.print

Use a higher baudrate for Serial, like:

Serial.begin(250000);

or

Serial.begin(500000);

If the serial monitor of the Arduino IDE does not support the baudrate you want, use a different "serial terminal software" on your PC instead of the serial monitor!

Which Arduino? A 16MHz 8 bit Arduino will have trouble doing the floating point calculations that fast.

On the 'native' USB ports, the baud rate set in the serial monitor and in the sketch code is ignored. It simply works at the speed of USB.

jurs:
Use a higher baudrate for Serial, like:

Serial.begin(250000);

or

Serial.begin(500000);

If the serial monitor of the Arduino IDE does not support the baudrate you want, use a different "serial terminal software" on your PC instead of the serial monitor!

Thanks Jurs, Ive tried both those and every baud rate I can find higher than 614400 and none other seem to work with processing. And yes Ive checked with program called tera term thank you!

MorganS:
Which Arduino? A 16MHz 8 bit Arduino will have trouble doing the floating point calculations that fast.

On the 'native' USB ports, the baud rate set in the serial monitor and in the sketch code is ignored. It simply works at the speed of USB.

When I changed to the native port, the time for the prints increased from 360us to 490us....

You have not posted enough of your program so we can see how the Serial.print() stuff is used or what is being affected by the long time taken to send the data. Always post a complete program.

Perhaps you are just trying to send the data too often?

I am a great believer in doing the hard work on the PC rather than the Arduino.

...R

Robin2:
You have not posted enough of your program so we can see how the Serial.print() stuff is used or what is being affected by the long time taken to send the data. Always post a complete program.

Perhaps you are just trying to send the data too often?

I am a great believer in doing the hard work on the PC rather than the Arduino.

...R

Hi robin, Ive posted the only relevant part of my code, here is my setup portion in case that will help

void setup() {
  
  delay(1000); //let processing get ready
  
  Serial.begin(614400);//614400 highest baud rate that works right now
  SerialUSB.begin(9600);
  while (!SerialUSB) {} // wait for serial port to connect
  
  pinMode(latchPin, OUTPUT);
  analogReadResolution(12); //increase accuracy of analog

  SPI.setDataMode(SPI_MODE1);//Set when to collect data (MODE 0 rising edge MODE 1 falling edge)

  delayMicroseconds(100);//delay 100us before measuring analog 

 

}

But again the only part I am interested in is speeding up the Serialprint OR SerialprintUSB (have tried both the programming port and native port) And measured the time it takes for the SerialPrints using timers and I am sure that this is the slow part of the code,

I saw an optimized version of HardwareSerial.h from How can i speed up serial.print and serial read processing time? - Programming Questions - Arduino Forum

that was supposed to speed up Serialprint but when I replaced it, it didnt work.

Any way to speed up Serial Print????????

Delta_G:
The slow part of the code you'be shown is the floating point math. That's the part that is taking hundreds of microseconds.

Hi delta thanks for response, As Ive said in previous response, when I moved the math over to the processing side and timed the serialprints sending two bytes instead of the calculated float value, it sped up but only from 580us to 360 us and I was hoping for something significantly faster. Its still the SerialPrints that are being a problem for me. Are you saying that its as fast as its going to be and no way of optimizing??

Thank you!

philipjfry:
here is my setup portion in case that will help

Please post the complete program.

...R

Ive posted the only relevant part of my code,

The problem is not in the code you posted. If it was, you would have already noticed the relevance and fixed it.

Newbies usually don't post variable declarations because they "don't look important" but they are the root of the problem in a large proportion of these types of questions.

Search around some more. There's lots written on the speed of native USB and how the actual USB connection really works. There's some FIFO buffer settings you can make on the PC that will make a difference. For maximum speed, you want to fill all your USB packets as much as possible.

614400 baud gives 61440 bytes per second.

One of your printed lines has 4+4*7+2 = 34 bytes (with cr/lf).

One loop takes 580µs, 1724,14 times a second, streaming 58620 bytes per second.
That is very close to the theoretical maximum, isn't it?

Robin2:
Please post the complete program.

ok R

//#include <SoftwareSerial.h>
#include <SPI.h>

//latch, analogIn pin declarations
const int latchPin = 12;
const int analogPin1 = A0;
const int analogPin2 = A1;
const int analogPin3 = A2;
const int analogPin4 = A3;

//float variables to store analog values
//float val1;
//float val2;
//float val3;
//float val4;

int val1;
int val2;
int val3;
int val4;


unsigned long timer;
unsigned long timerb = 0;



void setup() {
  
  delay(1000); //let processing get ready
  //speeding up analogread  commented line (dont disable channel) in c file per http://forum.arduino.cc/index.php?topic=144484.0
  REG_ADC_MR = (REG_ADC_MR & 0xFFF0FFFF) | 0x00020000; // speeds up analog read from   http://www.djerickson.com/arduino/
  //now 4 analog reads down to about 20us
  Serial.begin(614400);//614400 highest baud rate that works right now
  SerialUSB.begin(2000000);
  while (!SerialUSB) {} // wait for serial port to connect
  
  pinMode(latchPin, OUTPUT);
  SPI.begin();
  //SPI.setClockDivider(255);//(255)333KHz slowest
  analogReadResolution(12); //increase accuracy of analog

  SPI.setDataMode(SPI_MODE1);//Set when to collect data (MODE 0 rising edge MODE 1 falling edge)

  delayMicroseconds(100);//delay 100us before measuring analog 

 

}
void loop() {

   for(int i = 1; i<=200; i++){
    
  //timer = micros();
//  val1 = (float)analogRead(analogPin1)* (3.3/4095);
//  val2 = (float)analogRead(analogPin2)* (3.3/4095);
//  val3 = (float)analogRead(analogPin3)* (3.3/4095);
//  val4 = (float)analogRead(analogPin4)* (3.3/4095);
  val1 = analogRead(analogPin1);
  val2 = analogRead(analogPin2);
  val3 = analogRead(analogPin3);
  val4 = analogRead(analogPin4);
   
  //timerb = micros();
  /*
  timer = micros();
  char asdf[32];
  snprintf(asdf,32,"%d, %d, %f, %f, %f, %f,",timer-timerb,i,val1,val2,val3,val4);
  
  SerialUSB.print(asdf);
  timerb = micros();
  
  SerialUSB.print(",");
  SerialUSB.println(timerb-timer);
  */
//  SerialUSB.print(i);
//  //timerb = micros();
//  SerialUSB.print(",");

/*
  Serial.print(val1,4);
  Serial.print(",");
  Serial.print(val2,4);
  Serial.print(",");
  Serial.print(val3,4);
  Serial.print(",");
  Serial.print(val4,4);
  Serial.print(",");
  */
  timer = micros();
  SerialUSB.print(val1);
  SerialUSB.write(",");
  SerialUSB.print(val2);
  SerialUSB.write(",");
  SerialUSB.print(val3);
  SerialUSB.write(",");
  SerialUSB.print(val4);
  SerialUSB.write(",");
  
  timerb = micros();
  SerialUSB.println(timerb-timer);
  
  
  
  //timerb = timer;
  
}
  
}

And delta no, i just put timers around the SerialPrint block of code i had to approximate the time it took

You seem to be trying to send serial data in every iteration of loop() - why? I would expect loop() to repeat hundreds or thousands of times per second. No matter how fast Serial.print() is it will overwhelm the Serial system. In fact, the faster the worse the problem will be.

From that code I can't see why the speed of Serial.print() would be a problem.

Is there any reason not to restrict Serial.print() to (say) once every 100 millisecs?

...R

As already noted, sending the raw analog values as 3 hex digits each brings the record down to 14 bytes and drops all the floatingpoint stuff. No rounding errors, just the raw data.

Robin2:
You seem to be trying to send serial data in every iteration of loop() - why? I would expect loop() to repeat hundreds or thousands of times per second. No matter how fast Serial.print() is it will overwhelm the Serial system. In fact, the faster the worse the problem will be.

From that code I can't see why the speed of Serial.print() would be a problem.

Is there any reason not to restrict Serial.print() to (say) once every 100 millisecs?

...R

yes I need a 10k frequency for the loop

and

Whandall:
As already noted, sending the raw analog values as 3 hex digits each brings the record down to 14 bytes and drops all the floatingpoint stuff. No rounding errors, just the raw data.

Yeah Im sending raw data and its still too slow
thank you

So you can transfer at max 61440 and you want to have 10k samples.
That gives 6 bytes transfer bandwidth per 4 values of 12 bit binary data.

So you have to send binary data to get close to your target speed.

Whandall:
So you can transfer at max 61440 and you want to have 10k samples.
That gives 6 bytes transfer bandwidth per 4 values of 12 bit binary data.

So you have to send binary data to get close to your target speed.

ok any hints whandall?

Delimiters are problematic, there is no bandwidth for them and there are no special characters when using binary.
Maybe you can use a synch preamble.

You will have to pack the 12 bit values somehow to fit them into the 6 bytes you can transmit.

If you have to convert to ascii or use delimiters, you will never come close to 10k samples.

Do you really need all 4 values? Do you really need that speed?

You could send only two samples each loop alternating between the two pairs.