Arduino UNO :: receiving UART data - garbage

Hi! :slight_smile:

I want to make one simple serial data logger with Arduino UNO and SD card, but I have a problem on the start :frowning:
I have external UART device which send me data every second with baudrate 115200 and in next form:

U=10.0V Tmp=15.0°C Hum=76% Uptime=234s

...after 5 seconds I have 5 sentences, for example:

U=10.0V Tmp=15.0°C Hum=76% Uptime=234s
U=10.0V Tmp=15.1°C Hum=77% Uptime=235s
U=10.0V Tmp=15.2°C Hum=76% Uptime=236s
U=9.9V Tmp=15.1°C Hum=77% Uptime=237s
U=9.9V Tmp=15.1°C Hum=76% Uptime=238s

...but on Serial monitor received data are broken...

I made another test: I wrote sketch which firstly send data to serial port and then It reads If anything came in Rx buffer and then print this to Serial monitor. Function .readBytesUntil which is used in sketch has two conditions for terminate: terminator z (for test, \n is in real case) is detected and buffer (100 Byte) is full.

Sketch:

#define BUFF_MAX 100

void setup()
{
  Serial.begin(115200);
}
void loop()
{
  char inBuffer[BUFF_MAX];
  delay(1000);
  Serial.println("U=10.0V  Tmp=15.0°C  Hum=76%  Uptime=234sz");
  while (Serial.available()>0)  
    {         
    byte sizeBuffer = Serial.readBytesUntil('z', inBuffer, BUFF_MAX);
    Serial.print("Received:");
    Serial.write(inBuffer);
    Serial.println();
    }
}

...when I upload this code to UNO and open Serial monitor, I can see this:

U=10.0V Tmp=15.0°C Hum=76% Uptime=234sz
U=10.0V Tmp=15.0°C Hum=76% Uptime=234sz
U=10.0V Tmp=15.0°C Hum=76% Uptime=234sz
U=10.0V Tmp=15.0°C Hum=76% Uptime=234sz
U=10.0V Tmp=15.0°C Hum=76% Uptime=234sz
U=10.0V Tmp=15.0°C Hum=76% Uptime=234sz

...this is OK...when I make a connection between Rx(0) and Tx(1), I receive garbage...:

Received:U=10.0V Tmp=15.0°C Hum=76% Uptime=234sŮdŮ
ŮcŮvŮ:Ů1ŮŮŮ Ů5Ů
ÂŮ ŮuŮ7Ů ŮpŮmŮ2¬
Received:
Received:U=10.0V Tmp=15.0°C Hum=76% Uptime=234sŮdŮ
ŮcŮvŮ:Ů1ŮŮŮ Ů5Ů
ÂŮ ŮuŮ7Ů ŮpŮ
Received:ŮmŮ2¬
Received:
Received:U=10.0V Tmp=15.0°C Hum=76% Uptime=234sŮdŮ
ŮcŮvŮ:Ů1ŮŮŮ Ů5ŮŮ
Received:
ÂŮ ŮuŮ7Ů ŮpŮ
Received:ŮmŮ2¬

What I'm doing wrong?...Please help me.

Thank you!

Garbage values often are indicative of a mismatch of baud rates.

Is the Serial monitor set to receive at 115200 baud?

Yes, serial monitor is set to 115200 baudrate.

Let me get that right: you are connecting directly Rx to Tx on your uno? (a wire between pin 0 and 1)? and you expect to see something correct on the console in your computer?

Yes, for a test a made a connection between Rx and Tx...so I sent simple text to Tx which was conected to Rx...received text must be the same as sent text-am I wrong?

well those 2 pins are the one connected back to your computer Serial driver through the USB cable for display...

if you connect them together what do you think happens? :slight_smile:

if you want to test sending the info, you should have another arduino and connect Tx from one to Rx of the other and Rx from one to Tx of the other and then run the reader pgm on the second arduino

Ok, I know for this UART to USB converter on UNO, but If I don't typing anything in Serial Monitor, Rx(0) pin is free in my opinion?

I made this simple test because I want to checked why I receive garbage from my external UART device...I tried SoftwareSerial too (I used pins 7 and 8 for Rx and Tx), but garbage is there too...

Maybe problem is in code that read Rx data?

well on the computer side it might be pulled low or just floating - imagine there is another cable leaving that pin and you don't know what's happening on that cable.

Ok, I test new sketch with SoftwareSerial Rx and Tx...

#include <SoftwareSerial.h>

#define BUFF_MAX 100
SoftwareSerial mySerial =  SoftwareSerial(7, 8); //rx,tx

void setup()
{
  Serial.begin(9600);
  mySerial.begin(9600);
}
void loop()
{
  char inBuffer[BUFF_MAX];
  while (mySerial.available()>0)  
    {         
    byte sizeBuffer = mySerial.readBytesUntil('\n', inBuffer, BUFF_MAX);
    Serial.print("Received:");
    Serial.write(inBuffer);
    Serial.println();
    }
}

I used FTDI cable and Putty on computer...
When I sent number 5, in serial monitor I received:
Received:5
2ŮÂŮ ŮuŮ7Ů ŮpŮŮŮ
Received:ŮR٬ŮRŮeŮeŮ
Ůe

...number 6:
Received:6
2ŮÂŮ ŮuŮ7Ů ŮpŮŮŮ
Received:ŮR٬ŮRŮeŮeŮ
Ůe

.
.
.

...number 9:
Received:9
2ŮÂŮ ŮuŮ7Ů ŮpŮŮŮ
Received:ŮR٬ŮRŮeŮeŮ
Ůe

I'm sure, I have problems with function which read Rx data but I don't know why exactly...In Putty I'm using the same baudrate as in serial monitor (9600 in this case), 8 data bits, without parity and 1 stop bit...

FTDI cable and Putty on computer --> connected to 0/1 (Serial) or 7/8 (mySerial)?

have you ensured common ground between Arduino and FTDI cable?

FTDI cable is connected in next way:

GND (FTDI) ---- GND (Arduino UNO)
Tx (FTDI) ----- 7 (Software Rx on Arduino Uno)

Other pins (Rx, Vcc, ...) on FTDI are not connected, because I don't need them.

For USB to UART TTL converter I tried option with: ATEN USB->RS232 converter and then MAX232 to convert to TTL...I opened Putty and serial monitor...and result is the same as in previous post (with FTDI cable)...I received just garbage...

There is No harm in not connecting Rx (FTDI) --> 8, I would suggest you do so to prevent floating pin - just in case your FTDI cable is sensitive. (or just ground it, don't leave it floating)

But I think your problem though is the way you receive the info and what you actually print:

you do

    byte sizeBuffer = mySerial.readBytesUntil('\n', inBuffer, BUFF_MAX);

and if you look at the function definition it's

 (byte)  Serial.readBytesUntil(character, buffer, length);

Serial.readBytesUntil() returns the number of characters read into the buffer (which you ignore)

You say that when you type number 5, in serial monitor you received:


Received:5
2ŮÂŮ ŮuŮ7Ů ŮpŮŮŮ
Received:ŮR٬ŮRŮeŮeŮ
Ůe

that actually makes a lot of sense. you sent only one char and a \r\n possibly from your console.

so the inBuffer has 3 character set: 5 in char [ 0 ], \r in char [1] and \n in char [2] and the function probably returned 3 (assuming your Putty terminal is set to send \r\n at the end of the line. if it only sends a \n then you have only 2 chars)

As you do

    Serial.print("Received:");
    Serial.write(inBuffer);

the inBuffer does have a 5 and a carriage return and this is the thing you see in the output


[b]Received:5[/b]
2ŮÂŮ ŮuŮ7Ů ŮpŮŮŮ
Received:ŮR٬ŮRŮeŮeŮ
Ůe

but because you did not tell the Serial.write function how many characters to print, the compiler is a bit confused.

Serial.write supports 3 modes:

Serial.write(val) 
Serial.write(str) 
Serial.write(buf, len)

where

val: a value to send as a single byte
str: a string to send as a series of bytes
buf: an array to send as a series of bytes and len: the length of the buffer

As you don't provide a length, and your parameter is not a single byte, and you have a parameter compatible with a string, the compiler goes for second option. it expects a well formatted string, with a \0 at the end. but because inBuffer is a variable declared in the loop function, its bytes are not set to zero like a global variable... it's just BUFF_MAX random garbage bytes that were on the stack.

The function does what it is supposed to do and the inBuffer data is sent as a series of bytes to the computer to display. the first 3 are good (the 5 and carriage return) and then you have all the garbage until you hit a zero or end of the inBuffer

So long story short:

  • capture the number of bytes received from the function Serial.readBytesUntil into a byte variable nbBytesReceived
  • do a Serial.write(inBuffer, nbBytesReceived)

then all the garbage won't appear after the Received:5

give it a try!

Hi J-M-L,

i tried your suggestion, so I add length of buffer in function serial.write and result was much better :slight_smile: thank you!

Then I tried to clear a buffer every cycle: memset(inBuffer, 0, sizeof(inBuffer));

Result is (almost) perfect, but...

For this test I took 2 Arduinos...first Arduno just sent one statemenet every 2 seconds (on Software serial pins 10 and 11). Sketch:

#include <SoftwareSerial.h>

SoftwareSerial mySerial =  SoftwareSerial(10, 11); //rx,tx

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
   mySerial.begin(115200);

}

void loop() {
  // put your main code here, to run repeatedly:
  delay(2000);
  mySerial.println("U=10.0V  Tmp=15.0°C  Hum=76%  Uptime=234s");

}

Second Arduino was just receiving this data:

#include <SoftwareSerial.h>

#define BUFF_MAX 100
SoftwareSerial mySerial =  SoftwareSerial(9, 8); //rx,tx

void setup()
{
  Serial.begin(115200);
  mySerial.begin(115200);
}
void loop()
{
  char inBuffer[BUFF_MAX];
  memset(inBuffer, 0, sizeof(inBuffer));
  Serial.print(inBuffer);
  while (mySerial.available()>0)  
    {         
    byte sizeBuffer = mySerial.readBytesUntil('\n', inBuffer, BUFF_MAX);
    Serial.print("Received:");
    Serial.write(inBuffer, 100);
    Serial.println();
    }
}

But when I opened serial monitor (of Arduino which was receiving data), I saw next:

Received:U=10.0« Tmp=15.0°C Hum=76% Uptime<234s
Received:U=10.0V TŰp=15.0°C Hum=76% Uptime=234s
Received:U=10.0V Tmp=15.0á°C Hum=76% Uptime=234s
Received:U=10.0V Tmp=15.0°C �Hum=76% Uptime=234s
Received:U=00.0V Tmp<15.0°C Hum=76% Uptime=234s
Received:U=10.0V Tmp=15.0°C Hum=76% Uptime=234s
Received:U=10.0V Tmp=15.0°C Hum=76% Uptime=234s

Arduinos had common GND.

...some received data are OK, but most of them are not...In my opinion this look like buadrate problem (maybe too high baudrate for Arduino?)...but Arduino has 16 MHz crystal, so on 115200 error should not be too high?

Yes my experience has been that while the doc says up to115200, it is too fast on arduino with software serial and some characters arrive with some bits garbled. (An issue for example when you talk to an esp8266). The other challenge with Software serial when you write quickly is that the buffer is only 64 bytes and if you don't read that fast enough you will overflow quickly.

You might want to use hardware serial if you need that speed - but if you need to send every 2 seconds then there is no rush you can go much slower.

Dejan_H:
I have external UART device which send me data every second with baudrate 115200

Not possible with an UNO. An UNO has JUST ONE Serial and this single Serial is connected to an USB-Serial and you can connect it to and use with your PC.

If you want to have an extra "external UART device" you will need to use an Arduino board which provides TWO Serial ports (Serial, Serial1) AT LAST!

For example use an Arduino MEGA2560 and connect your "external UART device" to "Serial1"!.

""Serial" on Arduino boards is meant for Arduino-PC-Serial communication only, you cannot use that for "an extra "external UART device".

Hi jurs,

for external UART device I meant "black box" which sends me data via UART.
Yes, one physical UART on UNO is problem, so I use software serial to receive data...but 115200 is too high for software serial as it looks...