Go Down

Topic: Faster than 128000 Baud? (Read 1 time) previous topic - next topic

SarahC

Hi!

The baud rate on the Arduino, and Processing can be set via their programs.

Similar to:
baud.begin(128000);

That appears to mean I can set it to a value greater than that shown in Device-manager, say 200000 baud, and some people online suggest up to 3 megabaud is possible.
One such project is the ChibiMo, that expands the Windows display using LCD Matrix panels! : http://www.youtube.com/watch?v=B0uevXj1ARM&feature=related

But the serial read of the Arduino IDE, only goes to 128000, so at faster speeds I can't read the data.

Is there anything online that give a good intro to faster baud rates for the Arduino, and shows how the Device Manager settings can be over-ridden?

SarahC

In arduino-1.0\hardware\arduino\cores\arduino\HardwareSerial.cpp is the following code:

It looks tied in to the bootloader for some reason!?

I'm going to look through it and see what I can make of it.


void HardwareSerial::begin(unsigned long baud)
{
  uint16_t baud_setting;
  bool use_u2x = true;

#if F_CPU == 16000000UL
  // hardcoded exception for compatibility with the bootloader shipped
  // with the Duemilanove and previous boards and the firmware on the 8U2
  // on the Uno and Mega 2560.
  if (baud == 57600) {
    use_u2x = false;
  }
#endif

try_again:
 
  if (use_u2x) {
    *_ucsra = 1 << _u2x;
    baud_setting = (F_CPU / 4 / baud - 1) / 2;
  } else {
    *_ucsra = 0;
    baud_setting = (F_CPU / 8 / baud - 1) / 2;
  }
 
  if ((baud_setting > 4095) && use_u2x)
  {
    use_u2x = false;
    goto try_again;
  }

  // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)
  *_ubrrh = baud_setting >> 8;
  *_ubrrl = baud_setting;

  sbi(*_ucsrb, _rxen);
  sbi(*_ucsrb, _txen);
  sbi(*_ucsrb, _rxcie);
  cbi(*_ucsrb, _udrie);
}

Coding Badly


For a processor running at 16 MHz (like the one on your Arduino), 125K, 250K, 500K, 1M are "zero error" baud rates.  That means using them is less likely to cause communications problems.  I suggest using one from that list rather than 200K or 128K.

Quote
and shows how the Device Manager settings can be over-ridden?


I have yet to cross paths with an application that uses the Device Manager line settings.  In other words, everything overrides the Device Manager settings. 

SarahC

#3
May 20, 2012, 11:38 am Last Edit: May 20, 2012, 08:10 pm by Coding Badly Reason: 1
Hi Coding!

I need to keep it in multiples of the clock frequency... that's good to know, thanks!
I've just run some benchmarks to see what happens if numbers greater than 115,200 are used.

There IS an increase in throughput.  :)
But it's only 4.75Kb/s.  =(

Something is creating that ceiling - do you think it's the ATTiny that acts as the USB to Serial interface?

Code: [Select]
/*

Arduino code

This is a simple Arduino program that outputs a byte to the Serial port as fast as it can, the byte cycles from 0 to 255, and back around.

Looking at the following benchmark, we can see that we can throughput 19,200 bytes a second.
That is faster than the "Serial Monitor" in the Arduino IDE can support.

It's a total of 18.75 Kb/s, just by using the standard Serial output on the Arduino, and standard Serial input on Processing.
That's a bit better than the 115,200 baud (14 Kb/s) the Serial Monitor supports.
But a long way from the 122Kb/s 1 Megabaud would provide. (6 times slower in fact!)



Baud rate = Bytes received per second
50,000    = 5,080
100,000   = 10,100
150,000   = 15,600
200,000   = 19,200
250,000   = 19,200
300,000   = 19,200
350,000   = 19,200
400,000   = 19,200
*/

unsigned short int counter=0;


void setup() {
 // initialize the serial communication:
 Serial.begin(150000);
}

void loop() {

   Serial.write(++counter);
   
}





Code: [Select]
/*

Processing code

Processing program to count Serial byte reads per second, using the Serial interrupt mechanism.

*/


import processing.serial.*;

Serial myPort;
int oldTime=0,oldCount=0,count=0;

void setup()
 {
 println("begin");
 myPort = new Serial(this, "COM4", 150000);
 }

void serialEvent(Serial myPort)
 {
   count++;
/*   print("("+count+")");
   print(" : ");
   println(myPort.read());  */
 }


void draw()
{
if(millis()-oldTime>1000)
  {
  oldTime=millis();
  println("Reads per second: " + (count-oldCount));
  oldCount=count;
  }
 
}



Moderator edit: [code] [/code] tags added.

robtillaart

#4
May 20, 2012, 01:07 pm Last Edit: May 20, 2012, 01:09 pm by robtillaart Reason: 1
writing byte per byte is relative slow, check the overhead of loop() itself and the call to write.

did also some testing with higher baud rates and used a bit longer strings, see - http://arduino.cc/forum/index.php/topic,61381.msg444421.html#msg444421 -
The longer strings reduces the overhead substantially.

Also at the receiving end I used an terminal program called putty.exe. These terminals (there are others too) are quite optimized for communication, where Processing uses probably a layer of libraries (assumption)
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

arcachofo

#5
May 20, 2012, 02:18 pm Last Edit: May 20, 2012, 02:27 pm by arcachofo Reason: 1
You could configure the atmega328 usart yourself, have a look to datasheet or google it, there is lot of info in the web.

In theory you could configure usart up to 2 Megabauds with 16 MHz clock, using asinchonous double speed:

BAUD = Fosc/(8*(UBRRn+1))

with UBRRn=0 : BAUD = 16/8 = 2 (0% error)

To calculate UBRRn (double speed):

UBRRn = (Fosc/(8*BAUD))-1

Example C code to configure Usart0 in atmega328, not tested and perharps errors, but can show you how it's done :

Code: [Select]

#define USART0_BAUD 115200 // Define desired baud rate

#define USART0_UBBR_VALUE ((F_CPU/(USART0_BAUD<<4))-1)

void USART0_Init(void)
{
   // Set baud rate
   UBRR0H = (uint8_t)(USART0_UBBR_VALUE>>8);
   UBRR0L = (uint8_t)USART0_UBBR_VALUE;
   
   // Set frame format to 8 data bits, no parity, 1 stop bit
   UCSR0C = (0<<USBS0)|(1<<UCSZ01)|(1<<UCSZ00);
   
   // Uncomment for double speed
   //UCSR0A |= (1<<U2X0);

   // Enable receiver and transmitter
   UCSR0B = (1<<RXEN0)|(1<<TXEN0);
}



One important thing is line isolation, at high speeds electric noise can produce lot of errors.

Best regards.

Go Up