Unexpectedly slow rate

Hello!

I am currently using python to send data to an Elegoo Arduino Uno R3 and I cannot reach the expected 115200 baud rate. On a pro micro, I am able to reach that speed. I have been looking online and I came up short as to why I cannot reach that speed.

I have written a program to test the baud rate in python.

import time
import serial

def current_milli_time():
    return round(time.time() * 1000)

arduinoData = serial.Serial('COM4', 115200)
time.sleep(3)

update = current_milli_time()
updateRate = 0

while True:
    t = current_milli_time() - update

    arduinoData.write(b'c')
    
        
    updateRate += 1
    if (t > 1000):
        update = current_milli_time()
        baud = updateRate * 8
        print("baud rate: "+ str(baud) )
        updateRate = 0

And the code on both microcontrollers are:

void loop() {
    if (Serial.available())
      Serial.read();
}

On the Pro Micro, the python code returns around 114700, which is close to the 115200, but on the Arduino Uno, it only reaches around 16200 instead of the expected 115200.

I know the Pro Micro's ATmega32U4 has a usb tranciever inside, but I am not sure how it affects my results.

Are those results normal? Is my Uno toasted? Do I have something incorrectly setted up? Or Is my math wrong and I need to go back to school?

There can be no good answer until you post your entire sketch.

The small snippet of code for the microcontrollers is all the sketch! The 4 lines of codes are all that is needed to recreate the issue.
The 4 lines of codes are the result of stripping my actual project of all the unnecessary parts.

Welcome to the forum.

You are testing something else.
There is a USB cable between your computer and the Arduino boards. That USB cable is what this is about. How many data the computer can push over the USB bus depends on the USB device on the other side.

Elegoo Uno: The computer is communicating over USB to a usb-serial chip. That usb-serial chip communicates with the ATmega328P microcontroller via RX and TX. If the sketch is busy, some characters might be missed. What the sketch is doing has no part in your test. You are measuring the USB communication to the usb-serial chip on the Uno board.

Pro Micro: The computer is communicating over USB directly to the ATmega32U4 microcontroller. The Arduino code inside the microcontroller deals with the USB serial data.

Perhaps the usb-serial chip on the Elegoo Uno is very cheap and handles only one character at a time. Perhaps the Arduino code inside the ATmega32U4 for the USB is more optimized.

Does my explanation make sense ? Do you have more boards to try ? I didn't know that the difference would be that big.

Thank you Koepel for your help!

Sadly, I do not have any more boards to test with.
But I did check the chips, and the Elegoo board has the same Atmega16U2 and Atmega328P chips as the official Arduino Uno R3. I just checked with my own eyes on the board.

But it did make me think, and I took the time to update the USB firmware of the USB-serial chip, as I did play with UnoJoy one time, but I did reset it afterwards. Updating the firmware to the official firmware (here) didn't seem to change much at first, but now my python test returns 23000 instead of the 16000, which is faster. There can't be anything else on the board that needs updating, right?

It would be easy to rule it out as "You're using an unofficial clone, problems ensue", but so far I am not convinced.

So, apparently no setup() code was involved? No Serial.begin(unknown baud rate)? Interesting.

Oh yes, you do reach that. What you're testing is throughput, not baudrate.

Why 8? The UART in the Uno adds a start bit and a stop bit so it should be 10; that will not be the case with the Pro Micro as there is no UART involved.

At the application level, you should display characters per second, not a calculated baudrate.

Last note
If you use a Serial.begin() in the Arduino code, you will see that the baudrate setting has NO effect when using the Pro Micro. You can use 115200 in your python script and e.g. 9600 in the Pro Micro code.

@sterretje exactly right, this snippet shows that the baudrate of the arduino has no effect on the calculated results, the only requirement is that the ports be open.

import time
import serial

start = time.time()
end = 0
elapsed = 0

arduinoData = serial.Serial('COM4', 115200)

updateRate = 0

while True:
    end = time.time()
    elapsed = end - start

    arduinoData.write(b'c')
    updateRate += 1

    if (elapsed >= 1):
        print(updateRate * 10)
        start=time.time()
        updateRate = 0

the reading will not be accurate bit it will be close enough to judge

camsysca and sterretje are right: You don't show the full sketch for the Pro Micro, so we can almost assume that your setup() function is wrong and the baudrate is not really used on the Pro Micro because the data is using the USB bus and there is nothing "serial"-something in between and no baudrate is used.

You are still not testing the throughput because you don't know if data is missed, the ATmega32U4 (Pro Micro) should be able to read every byte, 9600 baud is just as accurate/reliable as 115200 baud.
The dummy baudrate for Serial.begin() is only there to be compatible with other boards.

Did you know that the ATmega328P (Uno) has a one byte input buffer for the Serial port ? Just one byte.

The code on the UNO /atmega328P is meaningless anyway, the USB to Serial converter (16u2) is feeding serial data to the atmega328p, but has no way to tell what, if anything, the atmega328p is doing with that serial data. You could hold the atmega328p in reset and get the same results (that is what is done for a loopback test, hold the processor in reset and short the Tx and Rx pins).

Could be because of Python....

Yes I did notice that and found it peculiar!
@Koepel I can assure I am not hiding any code. There is no setup function on the Pro Micro! I know how infuriating it is to debug when lacking information! And just to be sure, I added a Serial.Begin(115200) and like @sterretje said, no impact! Even on the Uno I added a Serial.Begin(x) and it doesn't have any effects on the measurement. It is dictated by the python script.

Talking about output, I tested @sumguy's code. I still get a blistering 140000 "baud" with the Pro Micro, but with the Uno, after testing multiple baud values, I can get a near perfect 9600, but I can only push it AT MOST 20000 baud, or 2000 chars per second, as we're trying to measure throughput here.

Honestly, that is a good theory. I took the time to try this COM Port Stress Test. At 115200, the pro micro achieved 129KB/s while the Uno 11 KB/s (yes, the software says "KB/s" as in Kilobytes per second... but they probably meant Kilobits) I guess it's python...? 12 Kb/s is somewhat close to the 115200 baud rate... while the pro micro is still going strong at... 129Kb/s... yeah... I'm suspicious.

I might try to test with another language if I don't just give up and go with the Pro Micro even if it has a limited amount of ports, though it might bite me in the ass in the future.

What bugs me too is that I got a faster rate after updating the firmware of the Atmega16U2.

I don't know a lot about microcontrollers, but could I bypass the Atmega32u2 of the Uno and use the TX & RX to communicate straight to my computer like the Pro Micro?

Once again I thank everyone who took the time out of their day to answer my curiosity. You guys are awesome!

Yes.
If your computer has a Serial COM port, then you can buy a RS-232-to-ttl-level module and connect the RX and TX of the ATmega328P directly to your computer.
The ATmega328P has no internal USB interface, it has only the Serial port at pin 0 and 1 to communicate.

This is all fun, but you are still not testing the throughput.
Can you make a block of data with a checksum and verify in the Arduino board that you have read the complete data block ?

11KB/s would be 110kb/s, real close to the 115200bps theoretical rate.

There's no flow control on the serial port of an Uno. If you output data at 115200bps and somehow only receive at 16200bps, you should be seeing a lot of missing data as well as the unexpectedly low rate.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.