I would like to decode a serial communication.

I have already found out how the protocol works. I can also send serial data with my logic analyzer and control the device this way.

I would like to integrate this function into an Arduino, but my Arduino Mega 2560 throws out completely different serial data than my Logic Analyzer.

The baud rate fits. 230400.

The first byte is 0x42. This is recognized correctly by the Arduino. After that, unfortunately, only gibberish comes out.

Does anyone have any idea how I can approach the problem?

enter image description here

enter image description here

  • What is the voltage of the signal? Which arduino pins are you using?
    – Abel
    Dec 31, 2023 at 13:40
  • 5V - Pin 18/19 (TX1/RX1)
    – Jens1888
    Dec 31, 2023 at 13:50
  • In that case, simply attempt to read multiple bytes into a buffer.
    – Abel
    Dec 31, 2023 at 13:51
  • 4
    It is better to post the code as text rather than a picture. There's a formatting button in the question editor to properly format the code when you insert it. Since the output is text, you can put it in the question the same way you do the program code.
    – JRE
    Dec 31, 2023 at 14:14
  • 1
    @Abel I hate myself for that. I had measured the voltage. 5V. I then ordered a Mega 2560 especially for this project because I didn't want to build a voltage divider. Whatever I measured was wrong. The voltage is 3.3V. I've been at it for half a day now. Such an unnecessary mistake. Thanks for the hint.
    – Jens1888
    Dec 31, 2023 at 14:19

4 Answers 4


You get the first byte correctly but miss the next bytes because you are busy printing out the first byte instead of receiving the following bytes.

Your code cannot to all that at once, especially if you are using Arduino libraries like that.

This is the upsides and downsides of Arduino, it lets you do simple things easily, but either your requirements already grew out of being simple and suitable for Arduino, or you are using the Arduino libraries without considering what they are capable of and how.

So instead of waiting for first byte and immediately printing it out, it might make more sense to wait and read bytes until you have read some whole packet and have enough time to print the bytes before next byte arrives.

Another thing, how do you even know your Arduino can use 230400 bps rate? If it uses a 16 MHz clock source, you cannot get exacltly 230400 but the closes baud rate is 222222 bps, and that is already a 3.55% error to what you need. Usually the target is better than 1% error, but in a pinch many devices might work within 2% error because in theory it allows both devices to be within 2% of the nominal rate. Having an error of 3.5% is usually too large and very close to the point of not working at all.

Edit: OK, it cannot be a software issue because Arduino UART does use interrupts and uses a ring buffer for buffering data.

What is known is that a 16 MHz AVR cannot exactly hit 230400 bps and will have 3.5% error in the baud rate which exceeds recommendations for maximum baud rate error. What even makes the situation worse is that instead of a more precise crystal, the Arduino Mega2560 uses a ceramic resonator with additional 0.5% tolerance, 0.3% temperature stability, and 0.2% aging. A crystal would have in any case better than 0.01% tolerance for all scenarios. So the most likely cause is that the Arduino Mega2560 can be simply said not to support baud rate of 230400 reliably so that is why it does not work.

And also the Mega256 data sheet says that minimum input high voltage is 0.6*Vcc, so using a 5V MCU that will be 3.0V minimum, so it will be within specification to receive a 3.3V signal. So the voltage issue is extremely unlikely.

  • The Arduino Mega 2560 had a 64Byte Buffer for that. This allows the loop to run without interrupting the serial reception.
    – Jens1888
    Dec 31, 2023 at 14:20
  • @Jens1888 Please explain where this 64 byte buffer is? It is not in the MCU for sure. Do you mean on the USB UART? Or is this a feature of Arduino code to provide you interrupt reception and transmission with a 64 byte buffer in code?
    – Justme
    Dec 31, 2023 at 14:30
  • 1
    I don't know exactly how the buffer is realized. However, there is one. Its a Arduino Feature for all Serial Comms. arduino.cc/reference/en/language/functions/communication/serial/…
    – Jens1888
    Dec 31, 2023 at 14:39
  • @Jens1888 If there is no source code for the libraries, nobody knows how it really works. I do not understand why the Arduino libraries deliberately want to hide all the important stuff how it works so you can't see why it does not work when it does not work. But in this case it must use interrupts to read data into ring buffer. But I have never investigated how it receives data if baud rate mismatch causes framing errors.
    – Justme
    Dec 31, 2023 at 14:51
  • 1
    @Justme: Here is the AVR implementation of the Arduino core. The “RX complete” ISR is implemented in HardwareSerial_private.h. Other bits of the serial communication library are in the other files named HardwareSerial*. Jan 1 at 11:21

You need to understand the MCU you are using to be able to test and diagnose that the functionality meets your needs.

  1. The accuracy of the baud/bit rate has to be considered for EACH serial link. In this case you have the serial link to your external device and the serial link to the Arduino console (a serial to USB converter implemented in an ATMEGA8). Here is a good link to understand the problem of baud/bit rate generation: https://wormfood.net/avrbaudcalc.php

Notice here that you cannot actually set 230.4k because of the rough granularity as UBRR approaches 1. You actually get 250k baud, which is used often for serial addressed DMX peripherals and works well on most Arduino variants. In you case however, this is you first problem, a mismatch between your peripheral bit rate and the Arduino 2560.

This is the relevant table for the 2560

  1. There will be a difference between the baud/bit rate for your two serial connection since the console serial link is defined in a separate MCU (the ATMEGA8) and they have different crystals. You should examine the schematic for the Arduino Mega 2560 and try to understand the configuration.

Here there is an obvious answer to most of your problem, and that is to eliminate one of the two serial connections. You already discovered that the Arduino Zero works successfully, you just didn't go on to discover why (and it's not the clock rate for the MCU that is the issue).

In several Arduino variants they have a direct USB peripheral controller built in. Look at the Arduinos that use the ATMEGA32u4 or as you found the more modern variants such as the Arduino Zero. In these variants the console transfer actually happens at USB speeds for the serial transfer, this is a rate fixed at the USB connection state rate.

You should experiment with raising the baud/bit rate on the console higher than the peripheral bit rate you are using, that may solve your immediate problem with the MEGA 2560. I'd suggest you try setting the console to 500k or 1M, this may depend on what your IDE device is (PC or Linux) allows configuration for of course. My suggestion would be to move to an MCU with inbuilt USB.

  • 1. The Arduino core sets the UART to double speed mode (U2Xn = 1) when possible. For 230.4 kb/s, you get UBRR = 8, and an actual baud rate of 222.2 kb/s, (error = −3.5%). Not as bad as the 8.5% error you are showing, but still worrisome. 2. The two MCUs on the board (ATmega2560 and ATmega16U2) have the same type of UART, clocked at the same frequency. Their baud rate errors may be large, but they will match, ensuring trouble-free communication between them. Jan 1 at 20:24
  • @EdgarBonet, agreed on U2XN, but it's still a sizeable error rate assuming the crystals are exactly the same frequency. In actuality the two crystals will differ slightly which could easily add another +/-1% variance. As I said, for the Arduino Mega 2560 with two separate async channels (one to the peripheral and one to the USB/serial converter it would be beneficial to raise the baud rate on the console uplink. Jan 1 at 22:41

At that baud rate you have 23Kcps, giving you ~40us for each loop invocation. IIRC the default serial buffer length is 16 characters, and you don't comment on the speed of the serial interface you are using for println() relative to the incoming data rate. It is therefore possible that you might be simply getting behind on the incoming stream.

Your question asks for an approach to diagnosing.

If possible I'd start by changing the input stream to have the same bitrate, but with the characters spaced well apart. See if that works.

If it does, the issue is likely either tied to loop timing and responsiveness, or could be related to the crystal/PLL accuracy at that rate. (If may simply be the clock rate isn't a good match for the baudrate generator, with drift building up after the first character.)


I don't know how else to confirm a solution here. @Abel gave the decisive hint. I measured the voltage of the signal incorrectly.

Edit: I can't accept my own answer as a solution for another 2 days.

  • 1
    Actually it does not matter. The problem may be elsewhere. If you received the first byte correct, the voltage might just not be the issue, but your Arduino not buffering the data for you, or the fact that it cannot reach the required 230400 bit rate without too much error. The Mega2560 data sheet says at 5V, a digital input will see 3.0V reliably as logic high, so this may be the least of your issues.
    – Justme
    Dec 31, 2023 at 14:37
  • I use an Arduino Zero that runs on 3.3V and it works perfectly.
    – Jens1888
    Dec 31, 2023 at 14:46
  • 1
    You cannot compare those two. Of course a 32-bit ARM MCU running at 48 MHz clock can set the baud rate more precisely than 8-bit AVR running at 16 MHz. I believe the voltage of the MCU is not the problem, but hitting the correct baud rate. So simply because using an Arduino Zero works, it still does not prove it was a voltage problem to begin with.
    – Justme
    Dec 31, 2023 at 14:54
  • That makes sense. As already written, the 2560 should recognize the 3.3V as HIGH.
    – Jens1888
    Dec 31, 2023 at 15:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.