Possible bug in OrangutanSerial [not a bug]

Looking through the libPololu code I found a possibly incorrect baud rate calculation for serial connection:

OrangutanSerial.cpp line 361:
unsigned int baud_ubrr = (F_CPU - 8*baud) / (16*baud);

after some calculations we get: baud = F_CPU / (16 * (baud_ubrr + 0.5))

now let’s look at Atmega datasheet, page 175:
BAUD = fOSC / (16 * (UBRRn + 1))

Assuming fOSC is equal to F_CPU, the correct formula should be
unsigned int baud_ubrr = F_CPU / (16*baud) - 1;

Hope it will be corrected :slight_smile:


The representation you see in the code is equivalent to:

baud_ubrr = Round(F_CPU / (16*baud) - 1)

Because division of integers truncates, you need to add 0.5 to cause a positive number to be rounded correctly. One easy way to do that is to add half of the denominator to the numerator before the division:

Round(F_CPU / (16*baud) - 1)
= F_CPU / (16*baud) - 1 + 0.5
= (F_CPU - 16*baud) / (16*baud) + 0.5
= (F_CPU - 8*baud) / (16*baud)

Your suggested code doesn’t round, which means that you aren’t always going to get the closest possible baud rate to your desired baud rate.

- Ben

Thanks for the explanation, that was beyond my math skills. Actually I was trying to make serial servo work on it’s default 1mbit baud, but realized that there is no such ubrr value for 20Mhz CPU. Found this calculation while searching for the answer and was a little confused :slight_smile: So I am currently stuck with these servos, will need to buy a 16Mhz AtMega probably.

Do you actually need to communicate at 1Mbps?

Well, I don’t need that. The problem is that servos are preconfigured to communicate at 1Mbps and do not respond if I try to use another baud rate.