56

The standard is 9600 baud. That's just the standard. Using a Arduino Uno SMD R2, what is the highest practical baud rate I can achieve?

Bonus points for the audacious: How would you go about creating an error checking mechanism and then increasing the baud rate ridiculous high to get high transfer rates?

Anonymous Penguin
  • 6,155
  • 9
  • 31
  • 62
  • 2
    It's worth noting that Arduino boards that use FTDI USB-serial ICs can go REALLY fast. The common FT232 can go 3 Megabaud (that's 3,000,000 baud) without issues. The use of a ATmega16U2 is the limiting factor. – Connor Wolf Feb 19 '14 at 05:52
  • 1
    My clone Arduino Nano that I got from eBay maxed out at 1,099,999. Seriously. It did. Once it reached 1,100,000, the output was garbled. ``laqq`na`fca`fga`fga`bcngaah````iin`ha`a`a`bga`fga`bcqpahhqfq```fh`oopa`bca`fca``. It uses a CH340 chip for USB comms. – Aloha Sep 27 '15 at 12:23

4 Answers4

75

There are several factors here:

  • How high of a baud-rate can the ATmega328P MCU achieve?
  • How high of a baud-rate can the USB-Serial interface achieve?
  • What is the oscillator frequency on the ATmega328P?
  • What is the oscillator frequency on the USB-serial interface (if it has one)?
  • How tolerant is the USB-serial interface of baud-rate mismatch?

All of these factors are relevant to determining the maximum achieveable baud rate. The ATmega328P uses a hardware divisor from it's clock-rate to generate the base-clock for the serial interface. If there is no integer ratio from the main clock to the bit-time of the desired baud rate, the MCU will not be able to exactly produce the desired rate. This can lead to potential issues, as some devices are much more sensitive to baud-rate mismatch then others.

FTDI-based interfaces are quite tolerant of baud-rate mismatch, up to several percent error. However, I have worked with specialized embedded GPS modules that were unable to handle even a 0.5% baud rate error.

General serial interfaces are tolerant of ~5% baud-rate error. However, since each end can be off, a more common spec is +-2.5%. This way, if one end is 2.5% fast, and the other is 2.5% slow, your overall error is still only 5%.


Anyways. The Uno uses a ATmega328P as the primary MCU, and a ATmega16U2 as the USB-serial interface. We're also fortunate here in that both these MCUs use similar harware USARTs, as well as 16 Mhz clocks.

Since both MCUs have the same harware and clock-rate, they'll both have the same baud-rate error in the same direction, so we can functionally ignore the baud error issue.

Anyways, the "proper" answer to this question would involve digging up the source for the ATmega16U2, and working out the possible baud-rates from there, but since I'm lazy, I figure simple, empirical testing will work.

A quick glance at the ATmega328P datasheet produces the following table:
enter image description here

So given the max stated baud-rate of 2 Mbps, I wrote a quick test program:

void setup(){};

void loop()
{

  delay(1000);
  Serial.begin(57600);
  Serial.println("\r\rBaud-rate = 57600");
  delay(1000);
  Serial.begin(76800);
  Serial.println("\r\rBaud-rate = 76800");
  delay(1000);
  Serial.begin(115200);
  Serial.println("\r\rBaud-rate = 115200");
  delay(1000);
  Serial.begin(230400);
  Serial.println("\r\rBaud-rate = 230400");
  delay(1000);
  Serial.begin(250000);
  Serial.println("\r\rBaud-rate = 250000");
  delay(1000);
  Serial.begin(500000);
  Serial.println("\r\rBaud-rate = 500000");
  delay(1000);
  Serial.begin(1000000);
  Serial.println("\r\rBaud-rate = 1000000");
  delay(1000);
  Serial.begin(2000000);
  Serial.println("\r\rBaud-rate = 2000000");
};

And then looking at the relevant serial port with a serial terminal:

enter image description here

So it appears the hardware can run at 2,000,000 baud without problems.

Note that this baud rate only gives the MCU 64 80 clock-cycles per byte, so it would be very challenging to keep the serial interface busy. While the individual bytes may be transferred very rapidly, there is likely to be lots of time when the interface is simply idle.


Edit: Actual Testing!

The 2 Mbps is real:
enter image description here
each bit-time is 500 ns, which matches exactly with what is expected.

Performance issues! Overall packet length:
500 Kbaud: enter image description here

1 Mbaud: enter image description here

2 Mbaud: enter image description here
Note: The noticeable overshoot is due to poor scope probe grounding practices, and is probably not real. I'm using the ground-clip-lead that's part of my scope probe, and the lead-inductance is likely the cause of the majority of the overshoot.

As you can see, the overall transmission length is the same for 0.5, 1 and 2 Mbaud. This is because the code that is placing the bytes in the serial buffer is poorly optimized. As such, you will never achieve anything better then an effective 500 Kbaud, unless you write your own serial libraries. The Arduino libraries are very poorly optimized, so it probably wouldn't be too hard to get a proper 2 Mbaud, at least for burst transmissions, if you spent a bit of time on it.

Connor Wolf
  • 2,594
  • 11
  • 16
  • 4
    Nice illustration of the throughput limitation! – jippie Feb 19 '14 at 07:03
  • @jippie - I had the scope up, and was running the program in my answer that cycles through baud rates. It was very little additional work, and does illustrate the issue quite nicely. Also, the segmented memory on my scope is awesome. – Connor Wolf Feb 19 '14 at 07:05
  • DS2000 series? Does lowering the bitrate to 250kb actually double the time of the transmission? I think I can still easily spot the start/stop bits in the 500kb image. – jippie Feb 19 '14 at 07:07
  • @jippie - 4000 series. I loves me some 4 channels. – Connor Wolf Feb 19 '14 at 07:25
  • If you skip the Serial library, you can get much faster. – Cybergibbons Feb 19 '14 at 08:36
  • @Cybergibbons - Yep. See the note at the end about optimization. – Connor Wolf Feb 19 '14 at 08:42
  • Wow I thought that the 9600 baud was pretty good for an AVR device but I never expected 2 MBPS! – Anonymous Penguin Feb 19 '14 at 21:55
  • 1
    @AnnonomusPerson - If you switch to a 20 Mhz clock, you can do 2.5 Mbps. – Connor Wolf Feb 20 '14 at 01:03
  • @FakeName 20 Mhz main crystal or on the USB chip? – Anonymous Penguin Feb 20 '14 at 01:39
  • 1
    @AnnonomusPerson - You'd need to swap both, or use a FTDI usb-serial interface with a 20 Mhz ATmega328P oscillator. The ATmega328P can't do 2.5 Mbps without a 20 Mhz crystal/resonator. The same is true for any ATmega16U2 interfaces. – Connor Wolf Feb 20 '14 at 02:35
  • 1
    Great answer! Just one small correction: at 2 Mb/s, each byte transmission takes 80 CPU cycles, not 64. This is because, time-wise, each byte is worth 10 bits (1 start, 8 data, 1 stop). – Edgar Bonet May 29 '15 at 13:03
  • @EdgarBonet - You are quite correct (and whoops). Fixed. – Connor Wolf May 29 '15 at 16:31
  • This is a great answer with one exception in that it doesn't account for the affects of the physical media (wire/cable used to connect to the other device). This will also be a major limiting factor in useful baud rates. Serial communication is pretty boring with just one device (loopback included). ::grin:: – linhartr22 Jul 09 '15 at 19:57
  • 1
    @linhartr22 - Wires only really come into play if they're *long*, as in 12"+. I think it's probably unlikely that too many people are using 100 foot long cables too much. Besides, the question was how high the **arduino/ATmega** baud rate can go, not how high an arbitrary cable assembly can go. – Connor Wolf Jul 09 '15 at 20:04
  • @ConnorWolf, I don't know if I agree 100% with this statement, "Since both MCUs have the same harware and clock-rate, they'll both have the same baud-rate error in the same direction, so we can functionally ignore the baud error issue." I don't see how being the same UART would guarantee error in the same direction, as individual chips can still vary randomly right?--and although the chips both are the same freq, which means serial freq calculation error is in the same direction, I know the chips don't use the same clock source (16U2 uses crystal, 328 uses separate ceramic oscillator). – Gabriel Staples Sep 11 '15 at 17:43
  • 1
    @GabrielStaples - You're missing the error I'm talking about. Basically, the way the ATmega UARTs work is they use an integer divider from the MCU clock to generate the serial timing. As such, some baud rates cannot be directly achieved, as the ratio between the baud rate and the system clock is not an integer. Generally, in this situation, the *closest option* is chosen, which results in the error I'm talking about here (`abs(closest option - target baud) = err`). **This** error will be matched between the two different parts. – Connor Wolf Sep 11 '15 at 18:56
  • While chips can vary, the operation of the UART is deterministic, so if you drive two parts with the same clock source, you'll get the same outputs (minus some small potential jitter). – Connor Wolf Sep 11 '15 at 18:59
  • @ConnorWolf, I see, so what this implies is that if you want to maximize the possibility of two devices to talk at a very high baud-rate, since this is asynchronous communication, you should have them both use the same frequency clock so that their actual baud-rates are skewed in the same direction, thereby aligning their bit-timing better? Is that right? ie: a 16MHz Arduino with a 16MHz USB to UART device is better than a 16Mhz Arduino with a 20MHz USB to UART device? – Gabriel Staples Sep 11 '15 at 19:02
  • Basically, the issue is that you have a MCU with a 20 MHz clock, you might get a -1.5% error from the baud-rate divisor *and* the oscillator variance could be -1%. Then, if talking to a MCU with a 16 MHz osc which produces a +2% divisor error, and a +1.5% oscillator error, all your errors sum up to 5% in total. However, if you share the same reference oscillator frequency, the baud rate divisor errors match, so they cancel out, and the only relevant factor becomes the oscillator error. – Connor Wolf Sep 11 '15 at 19:03
  • Edit: Yeah, you've got it. However, the baud-rate generation logic is specific to a device/line-of-devices,so comparing between different manufacturers can be complicated. – Connor Wolf Sep 11 '15 at 19:05
  • I see now. I just checked the ATmega328 datasheet. Here's [another table](http://i.stack.imgur.com/muABX.png) (from pg. 175) you might want to throw in your answer under the first one. It helps calculate the baud-rates to verify their errors in the table, and it makes it clear to me how they got their errors. For example, 115.2k shows -3.5% error for asynchronous normal mode (U2Xn=0). The formula goes: `16e6/(16*(8+1)) = 111111.11bps`. That's the closest option. So, the error is 111111.11/115200 = 0.9645 = -3.5%. – Gabriel Staples Sep 11 '15 at 19:49
  • Funny that the 1MBPS baud and 2MBPS baud will take the same time to transmit. It's because of the bytes not being copied fast enough? This might also mean that you won't be able to receive the bytes at this speed. Ofcourse you can receive 1 byte at 2Mbaud, but for receiving multiple bytes, it depends on how fast the Arduino clears the serial buffer (and thus another byte can be received). – Paul Apr 13 '16 at 09:19
  • @Paul - The arduino doesn't do anything. The **ATMega328p**, on the other hand, does lots of stuff. Anyways, The throughput issues are a function of the efficiency of the transmit interrupt handler speed. As a rule, the code in the default arduino libraries is, well, really poor quality. It should be entirely possible to saturate the serial link for at least short bursts. – Connor Wolf Apr 13 '16 at 17:22
  • Do you think that adding de-bouncing caps (~10-2pf) to ground may increase the stability? – tuskiomi Aug 09 '17 at 19:01
  • 1
    @tuskiomi - What? No, the issue is the inductance of the ground clip wire that's part of my scope probe. The proper solution is to use a [probe tip ground](https://electronics.stackexchange.com/a/40421/1374), but unless you're specifically trying to measure things like risetime, as long as you know the ringing isn't real, it's not a significant issue. – Connor Wolf Aug 09 '17 at 20:05
  • @ConnorWolf I'm not sure. for example, over on [my question](https://arduino.stackexchange.com/questions/41661/arduino-due-not-properly-detecting-sd-card), The capacitors negated most of the spiking, which would not happen if it was a probe thing. – tuskiomi Aug 10 '17 at 13:18
  • @tuskiomi - That's to be expected, since the capacitors slow down the edge-rate, which means the inductance of the ground clip has a smaller effect. The point is, the spiking is 1. not harmful, 2. in the great majority of the cases, not actually real, but rather a measurement artifact. Additionally, if anything, the capacitors are *worse* for the circuit, since they're a load directly on the output drivers of the IC driving the bus. In general, there are **very** few cases where you ever want to *add* capacitance to a data bus. – Connor Wolf Aug 10 '17 at 22:03
  • Basically, before starting to stick capacitors everywhere, [learn to use your tip ground](https://electronics.stackexchange.com/questions/40420/what-is-the-name-of-this-springy-type-oscilloscope-probe-accessory/40421#40421), and check with that. [Here](http://teledynelecroy.com/doc/passive-probe-ground-lead-effects) is a white-paper by Teledyne LeCroy on the topic. [Here](http://web.mit.edu/6.101/www/reference/ABCprobes_s.pdf) is another from Tektronix. – Connor Wolf Aug 10 '17 at 22:09
  • Remember, even if your data rate is relatively slow, it's the *edge rate* that determines the effect the ground lead inductance has, rather then the edge frequency. Even slow little devices like ATMega ICs can produce quite fast edges. – Connor Wolf Aug 10 '17 at 22:12
  • There is also the issue of the [ceramic resonator](https://en.wikipedia.org/wiki/Ceramic_resonator) used for the MCU clock on some Arduinos, e.g. [Arduino Uno](http://arduino.cc/en/Main/ArduinoBoardUno) (they don't technically lie on the product page, but the [quartz oscillator](https://en.wikipedia.org/wiki/Crystal_oscillator) is used ***only*** for the USB helper MCU, not the main microcontroller). It introduces an up to 0.5% error. This may or may not be significant, depending on the circumstances (for instance, using the second serial port). Perhaps cover this as well in the answer? – Peter Mortensen Aug 22 '22 at 17:12
  • The error accumulates, so the last bit's time may already be off by close to 5% due to the ceramic resonator. How much can be tolerated as the accumulated error? 8%? – Peter Mortensen Aug 22 '22 at 17:17
9

The Arduino Serial Monitor window limits you to 115200, but that's not the highest baud rate capable. You can read the Atmel and the FT232 (or whatever you're using) datasheets to find out the maximum but I am able to successfully use 230400 (twice as fast as the largest the Arduino Serial Monitor supports) with no issues.

If you want to see the results in your computer, you will need another serial monitor that supports other baud rate options. I like CoolTerm and Termite.

Do note that this heavily depends on your clock speed as well.

Here's a calculator to help you with calculating what's possible.

sachleen
  • 7,365
  • 4
  • 37
  • 55
3

This is probably one of the few aspects where el-Cheapo boards differ from original boards. The maximum serial transfer rate is pretty much only limited by the quality of the board and its layout. Once the serial data enters either AVR or USB interface chip, the data will be processed differently from the serial UART protocol.

Keep in mind though that the microcontroller has some basic hardware to shift in/out serial data to/from the IO pins, but the absolute maximum rate is limited to the 16MHz clock (for AVRs). Once a byte is moved to the serial buffer, the UART hardware will take over and push out / pull in the bits on its own. An AVR at best reaches 16M instructions per second and the interrupts used to fill the serial buffer have some overhead (at least 8 clock ticks for the interrupt handling + instructions to save current state + several instructions for actually filling the buffer). At a given bitrate, the protocol will run at a whopping n bits per second, but your controller needs more time to fill the serial buffer than it needs to actually output the data, resulting in a lower average throughput than you expect and the UART idling for a relatively long time. Disadvantage is the increased probability for bit errors.

Another effect to remember is that all the overhead required to push data out onto UART (or pull it in) cannot be spent in your actual program, again affecting the average practical throughput. You can only use every instruction cycle once, either for filling the buffer or for computing the main loop.

The maximum throughput is therefore dependent on the application you use (how fast is data generated/computed/ready to move to/from the serial buffer) and the actual 'physical' bitrate is only a small part of the design decision.

jippie
  • 2,851
  • 12
  • 23
  • 1
    I really, REALLY doubt any of the boards out there have layout issues severe enough to prevent a 2 Mhz signal from working fine. 2 Mhz isn't exactly high frequency. – Connor Wolf Feb 19 '14 at 06:40
  • @FakeName At least one board on my desk here has increased BER when I push serial speed. I usually use 9600, that is more than enough for most applications and is robust. – jippie Feb 19 '14 at 06:44
  • No kidding! Huh. I wonder how bad the layout has to be to have that happen? I'd suspect it's not layout as much as poor-tolerance resonators/crystals, though. – Connor Wolf Feb 19 '14 at 06:49
  • 1
    High baud-rates, particularly if `U2Xn = 1` in the USART, tend to get pretty cranky about mismatch. – Connor Wolf Feb 19 '14 at 06:51
  • @FakeName I'm a dinosaur, I kinda like "9600 8N1" for all the wrong legacy reasons you can think of ;o) – jippie Feb 19 '14 at 06:54
  • Hell, I use 9600 myself for most debugging crap. It's not just you. It's just occationally I need to push a *lot* of data around, and knowing the limits is important. – Connor Wolf Feb 19 '14 at 07:01
  • I wouldn't be surprised if the increased BER is due to a cheap fake serial chip. (FTDI counterfeit) @ConnorWolf – jippie Aug 17 '15 at 07:05
3

Error checking is actually very easy and there is an AVR lib that does this in a one liner.

Read up on util/crc16.h and you should be good to go in no time with the included examples.

CRC is quite robust and fast for simple applications.

sachleen
  • 7,365
  • 4
  • 37
  • 55
80HD
  • 135
  • 2