0

I am trying to use Serial reading from a python serial code (which is running on my Jetson Nano) in my project, but in some loop in my code, my data is receiving wrong.

  • I use Serial.readBytesUntil() function for interrupt-like reading.
  • I use standart blue mini-USB cable for communication.
  • My Arduino Nano also connected a nRF24L01 module with SPI.
  • Baudrate is 9600 for both devices. I tried 115200 but there is no difference.
  • The data loss is about %10 of all loops with both test codes (image-1, image-2).
  • There is no positive difference when I use RX/TX pins on both boards with level shifter.
  • When I use the test code in my main code with USB connection, the data loss increases %50 of all loops. But Arduino serial monitor is fine like image-3.
  • When I use the test code in my main code with RX/TX pins, Arduino serial monitor looks like image-4 and Arduino IDE gives error like image-5.

Here is my receiver test code on my Arduino Nano.

void setup() {
 Serial.begin(9600);
 pinMode(LED_BUILTIN, OUTPUT);
 while (!Serial) {}
}
void loop() {
 char buffer[4];
 int deger = 0;
 if (Serial.available() > 0) {
 int size = Serial.readBytesUntil('\n', buffer, 4);
 if (size == 4) {
 Serial.print("deger: ");
 Serial.write(buffer);
 Serial.print(" size: ");
 Serial.print(size);
 // Bytes to integer
 deger = (buffer[1] - 48) * 100 + (int(buffer[2]) - 48) * 10 + (buffer[3] - 48);
 if (buffer[0] == '1') {
 deger = -1*deger; }
 Serial.print(" Sayi: ");
 Serial.println(deger);
 }
 if (deger < 0) {
 digitalWrite(LED_BUILTIN, HIGH);
 }
 else {
 digitalWrite(LED_BUILTIN, LOW);
 }
 }
}

And the python serial transmitter test code.

import serial
ser = serial.Serial('/dev/ttyUSB0',baudrate=9600,timeout=10)
while True:
 hata = -58
 if hata > 0:
 hata = str(hata)
 if len(hata) == 2:
 hata = '00' + hata
 elif len(hata) == 1:
 hata = '000' + hata
 else:
 hata = '0' + hata #Pozitive, Added 0
 elif hata < 0:
 hata = -1 * hata
 hata = str(hata)
 if len(hata) == 2:
 hata = '10' + hata
 elif len(hata) == 1:
 hata = '100' + hata
 else:
 hata = '1' + hata #Negative, Added 1
 else:
 hata = str(hata)
 hata = '000' + hata
 # For every loop, sends 4 character and "\n" Example: 1058\n
 gonder = hata + '\n' # For readBytesUntil function
 ser.write(gonder.encode('utf-8'))
 print(gonder.encode('utf-8'))

image-1: Arduino test code serial monitor screenshot

enter image description here

image-2: Python test code serial terminal screenshot

enter image description here

image-3: Arduino main project code monitor with USB cable screenshot

enter image description here

image-4: Arduino main project code monitor with RX/TX pins on GPIO screenshot

enter image description here

image-5: Arduino main project code IDE error

enter image description here

So, what did i do wrong? Thank you!

asked May 25, 2020 at 14:28
1
  • Already answered on the Arduino forum here Commented May 25, 2020 at 22:00

1 Answer 1

1

You are overflowing your buffer, and also allowing garbage reads.

First you need 5 bytes for your buffer not 4, and you need to ensure it is zeroed out before using it. This is because you are treating it like a C string, which means it must b zero terminated.

Secondly your use of Serial.readBytesUntil() is flawed. From the manual:

The function terminates (checks being done in this order) if the determined length has been read, if it times out (see Serial.setTimeout()), or if the terminator character is detected (in which case the function returns the characters up to the last character before the supplied terminator).

You are sending 5 bytes (1058\n) but telling it to read up to 4. Which leaves the \n in the buffer. The next time through you read another 4 bytes, which gives you \n which is the terminating character.

If you must use readBytesUntil then you need to specify a buffer that is bigger than the whole string including the terminator so that the terminator always occurs before the maximum number of bytes read. Including the trailing zero you would thus need at least 6 bytes in your buffer, maybe a couple more "just in case" (one can never tell with Arduino API functions...)

So to roll it all up:

 char buffer[8]; // <- Bigger buffer
 memset(buffer, 0, 8); // <- Clear it out
 int deger = 0;
 if (Serial.available() > 0) {
 int size = Serial.readBytesUntil('\n', buffer, 7); // <- Tell it to read more leaving room for the terminating NULL
 ... etc ...
if (size == 4) {
answered May 25, 2020 at 14:49
4
  • readBytesUntil doesn't put the terminating character in the buffer. but it is read. Commented May 25, 2020 at 15:49
  • 1
    @Juraj Not if it's the 5th character and you're only telling it to read up to 4... Commented May 25, 2020 at 16:00
  • Thank you! I will try to code like you said. What do say about the second problem (image-4, broken serial monitor) ? Commented May 26, 2020 at 11:53
  • That is most likely buffer overflow from your unterminated buffer. Commented May 26, 2020 at 11:53

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.