How do I speed up serial communication?

Hey all!

Other than increase baudrate, what can I do? Do you think the arduino's output buffer may affect the process?
I also tried to package more data in a single Serial.println(), but the packaging process decrease the performance.

Thank you

I'm using arduino uno rev3

EDIT: SOLVED! see this post How do I speed up serial communication? - #9 by DidntKnowThisBefore - Networking, Protocols, and Devices - Arduino Forum

What are your needs, exactly ?
Saying you want to speed up serial communication doesn't inform us very much.

What are you trying to do with the serial port ?
In fact, why not present your code, as we may see where improvements might be may in other areas that effect your code that deals with serial communications.

In essence, provide a lot more detail or all we can offer you is a crude guess.


Paul

Sure, my bad!

Here's the code:

unsigned long const baudrate = 115200;
int const phr = A0; //photoresistor
int const btn = 2; //just a button to start the reading

void setup()
{
  Serial.begin(baudrate);
  pinMode( btn , INPUT );
  // following three lines to speed up ADC (that is analogRead() )
  bitClear(ADCSRA,ADPS0);
  bitSet(ADCSRA,ADPS1);
  bitClear(ADCSRA,ADPS2);
}

void loop()
{
  if( digitalRead( btn ) == HIGH )
  {
    delay(1000)
    
    while( digitalRead( btn ) != HIGH )
    {
      //I need to speed up this part. analogRead, thanks to the trick above, only takes 6micros
      //but Serial.println takes 411us after the first 22 call to Serial.println() function
      Serial.println(analogRead(phr));
    }
    
    Serial.println(9999);
    delay(3000);
  }
}

What I want to do is to sample a light, and of course I want the highest frequency as possible because I want to write those data in a graph (made with python).
I'm fairly sure that the buffer gets full after those 22 samples. In fact, increasing its dimension (with this trick http://www.hobbytronics.co.uk/arduino-serial-buffer-size ) the number of samples increase proportionally to the increase of the buffer dimension.

So maybe I just should read faster? I'm going to see and report what I discover.

You want to get the data down the serial port faster, so you can spend a higher percentage of your time in the stupid delay() function? Why?

There are only two ways to make that happen. Send the data faster or send less data. Neither seems likely, since you may be using the highest supported baud rate already, and sending binary data may actually result in more data.

PaulS:
You want to get the data down the serial port faster, so you can spend a higher percentage of your time in the stupid delay() function? Why?

what? did you see that the Serial.println(analogRead() ) is inside a continuous while? it doesn't stop until I press the button again. I used the first delay to avoid getting immediately inside the while and repress is. The second one has the same function: I use it to not get inside the loop immediately after I told it stop.

btw: I was able to use baudrate 230400. higher values didn't produce better resault

Instead of printing the analogue value as ASCII over the serial connection you could write it as binary and only send 2x 8 bit characters (or maybe 2x 5 bit using SERIAL_5N1). This will save between 1-4 characters per sample.

If your only sampling a short burst of data then buffer it to RAM before sending it over serial. If you use a Mega-2560 then you should be able to buffer 3500+ samples

Riva:
Instead of printing the analogue value as ASCII over the serial connection you could write it as binary and only send 2x 8 bit characters (or maybe 2x 5 bit using SERIAL_5N1). This will save between 1-4 characters per sample.

I can't get this done... i set Serial.begin(9600, SERIAL_5N1) and then I use Serial.println(value). In my program (I use python 'serial' library) and I just set bytesyze=fivebits, but when I read I see many strange symbols.

Riva:
If your only sampling a short burst of data then buffer it to RAM before sending it over serial. If you use a Mega-2560 then you should be able to buffer 3500+ samples

No, I have to sample as continuous as possible. Also I've got Uno r3

I was talking about sending the raw binary data instead of converting it to ASCII first, like this...

      int temp = analogRead(phr);
      Serial.flush();
      Serial.write(temp >> 8);
      Serial.write(temp & 0xFF);

You will need to alter the Python code to read raw values instead of ASCII numbers and re-construct the int's from 2 consecutive bytes. To synchronise the readings so you assemble the bytes in the correct order you should make the Python code use the long delay at the end to sync.

Thanks to Riva I'm now able to output a value (ranged between 0 and 1023, that is 10bit) in 32micros.

Here's my final code:

//higher baud doesn't help. maybe it depends by my pc or arduino
unsigned long const baudrate = 230400;
int const phr = A0;
int const btn = 2;

void setup()
{
  Serial.begin(baudrate,SERIAL_5N1);
  pinMode( btn , INPUT );
  
  //these lines speed up the ADC. no loss of quality
  bitClear(ADCSRA,ADPS0);
  bitSet(ADCSRA,ADPS1);
  bitClear(ADCSRA,ADPS2);
}

void loop()
{
  if( digitalRead( btn ) == HIGH )
  {
    
    delay(1000);
    
    unsigned int val = 0;
    while( digitalRead( btn ) != HIGH )
    {
      //1 single line would take 36-44us
      //this way it falls to 32us (on average) 

      val = analogRead(phr);
      Serial.write( val>>5 ); //write first the highest 5bits
      Serial.write( val & 0x1F ); //and then the lowest 5

      val = analogRead(phr);Serial.write( val>>5 );Serial.write( val & 0x1F );
      val = analogRead(phr);Serial.write( val>>5 );Serial.write( val & 0x1F );
      val = analogRead(phr);Serial.write( val>>5 );Serial.write( val & 0x1F );
      val = analogRead(phr);Serial.write( val>>5 );Serial.write( val & 0x1F );
      val = analogRead(phr);Serial.write( val>>5 );Serial.write( val & 0x1F );
      val = analogRead(phr);Serial.write( val>>5 );Serial.write( val & 0x1F );
      val = analogRead(phr);Serial.write( val>>5 );Serial.write( val & 0x1F );
      val = analogRead(phr);Serial.write( val>>5 );Serial.write( val & 0x1F );
      val = analogRead(phr);Serial.write( val>>5 );Serial.write( val & 0x1F );
    }
    
    //I need these for my program
    Serial.write(0);
    Serial.write(0);
    Serial.write(0);
    Serial.write(0);
    Serial.write(0);
    Serial.write(0);
    
    delay(3000);
  }
}

I didn't need to use the Serial.flush(), maybe cause I'm reading them fast enough?

If you're interested about the python program, that takes this data and draw them in a graph in real time (at 63us per sample), just drop me a message

Why do you need to repeat the analogue read and serial send several times in the while loop?

     val = analogRead(phr);Serial.write( val>>5 );Serial.write( val & 0x1F );
      val = analogRead(phr);Serial.write( val>>5 );Serial.write( val & 0x1F );
      val = analogRead(phr);Serial.write( val>>5 );Serial.write( val & 0x1F );
      val = analogRead(phr);Serial.write( val>>5 );Serial.write( val & 0x1F );
      val = analogRead(phr);Serial.write( val>>5 );Serial.write( val & 0x1F );
      val = analogRead(phr);Serial.write( val>>5 );Serial.write( val & 0x1F );
      val = analogRead(phr);Serial.write( val>>5 );Serial.write( val & 0x1F );
      val = analogRead(phr);Serial.write( val>>5 );Serial.write( val & 0x1F );
      val = analogRead(phr);Serial.write( val>>5 );Serial.write( val & 0x1F );

I didn't need to use the Serial.flush(), maybe cause I'm reading them fast enough?

The flush was there so the serial buffer emptied before the next reading was added, preventing full buffer blocking at the possible expense of slightly slower but consistent sampling. If your code is sending fast enough then that's great.

Riva:
Why do you need to repeat the analogue read and serial send several times in the while loop?

     val = analogRead(phr);Serial.write( val>>5 );Serial.write( val & 0x1F );

val = analogRead(phr);Serial.write( val>>5 );Serial.write( val & 0x1F );
      val = analogRead(phr);Serial.write( val>>5 );Serial.write( val & 0x1F );
      val = analogRead(phr);Serial.write( val>>5 );Serial.write( val & 0x1F );
      val = analogRead(phr);Serial.write( val>>5 );Serial.write( val & 0x1F );
      val = analogRead(phr);Serial.write( val>>5 );Serial.write( val & 0x1F );
      val = analogRead(phr);Serial.write( val>>5 );Serial.write( val & 0x1F );
      val = analogRead(phr);Serial.write( val>>5 );Serial.write( val & 0x1F );
      val = analogRead(phr);Serial.write( val>>5 );Serial.write( val & 0x1F );

It makes it a little faster, saving 6-10us (on average). I just verified it empirically, nothing much.

Riva:
The flush was there so the serial buffer emptied before the next reading was added, preventing full buffer blocking at the possible expense of slightly slower but consistent sampling. If your code is sending fast enough then that's great.

Yeh, speed doesn't fall