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
image-2: Python test code serial terminal screenshot
image-3: Arduino main project code monitor with USB cable screenshot
image-4: Arduino main project code monitor with RX/TX pins on GPIO screenshot
image-5: Arduino main project code IDE error
So, what did i do wrong? Thank you!
-
Already answered on the Arduino forum hereP_B– P_B2020年05月25日 22:00:42 +00:00Commented May 25, 2020 at 22:00
1 Answer 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) {
-
readBytesUntil
doesn't put the terminating character in the buffer. but it is read.2020年05月25日 15:49:44 +00:00Commented 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...Majenko– Majenko2020年05月25日 16:00:51 +00:00Commented 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) ?dcwaves– dcwaves2020年05月26日 11:53:02 +00:00Commented May 26, 2020 at 11:53
-
That is most likely buffer overflow from your unterminated buffer.Majenko– Majenko2020年05月26日 11:53:41 +00:00Commented May 26, 2020 at 11:53
Explore related questions
See similar questions with these tags.