简体   繁体   中英

Arduino Serial.readBytes strange behaviour communicating with RPi

I'm trying to send 6 numbers from RPi 3 to Arduino Uno via Serial USB. They are supposed to be two longs, one int, and three separate bytes on the Arduino side, which makes 13 bytes to send from RPi3 with Python3. For Debugging, I leave them constant. Python code:

import serial
import struct
import time

ser = serial.Serial('/dev/ttyACM0',9600)
time.sleep(2)

b1 = 36
l1 = 2000 
l2 = 2000 
i1 = 120
b2 = 255
b3 = 2 

b1_struc = struct.pack("B",b1)
l1_struc = struct.pack("i",l1)
l2_struc = struct.pack("i",l2)
i1_struc= struct.pack("h",i1) 
b2_struc = struct.pack("B",b2)
b3_struc = struct.pack("B",b3)

order = b1_struc + l1_struc + l2_struc + i1_struc + b2_struc + b3_struc
# gives in total b'$\xd0\x07\x00\x00\xd0\x07\x00\x00x\x00\xff\x02'

while True:
    try:
        ser.write(order)
    except KeyboardInterrupt:
        quit()

I read them like this on the Arduino using a union/struc:

union Container {
  byte by[13];
  struct {
    byte b1;
    long l1;
    long l2;
    int i1;
    byte b2;
    byte b3;
  } ordercollection;
} order;

void setup(){
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop(){

  if (Serial.available() > 0) {
    while (Serial.available()) {
      long check1;
      check1 = 4413;
      Serial.readBytes(order.by,13);
      if (check1 == receivecheck() || check1 == -receivecheck()) {       
        blinkLED();        
      } 
      else {

      }
    }
  }
}

void blinkLED(){
    digitalWrite(LED_BUILTIN, HIGH);  
    delay(1000);                       
    digitalWrite(LED_BUILTIN, LOW);   
    delay(1000); 
}

long receivecheck() {
  long sum;
  sum = order.ordercollection.b1 + order.ordercollection.l1 + order.ordercollection.l2
    + order.ordercollection.i1 + order.ordercollection.b2 + order.ordercollection.b3;   
  return sum;
}

Because I cannot debug via serial monitor (it interfers the transmission) I'm using some kind of a checksum by adding up all sent numbers and if it is correct, the LED starts to blink. Now to my issue. If I use the Arduino IDE 1.8.1 on my Linux (Cinnamon 18.1 64-Bit) to upload the code above on the arduino, the transmission works EXACTLY 6 times, after that, the numbers are not transmitted properly anymore (the checksum changes from 4431 to different numbers and finally to -795081763 and remains on that value). I connected the Arduino to my RPi and tried to load the same code from the Arduino IDE there (Version 2:1.0.5+dsfg2-4), however it threw the error: invalid conversion from 'byte* {aka unsigned char*}' to 'char*' [-fmpermissive] which could be fixed by using

Serial.readBytes((char*)orders.by,13);

The result was the same: Exatly 6 right transmissions, then messed up. After excluding baudrate, timing errors etc. I changed the line:

   Serial.readBytes((char*)orders.by,15);

And strangely it worked. But when I load the same code with this changed line now from my linux notebook to the Arduino, it doesn't work at all (not a single transmission)! As I want to modify the Arduino code as least as possible (because several people are accessing it with their own projects), I'm am wondering, why it's not working the way I presented it in my code above with Serial.readBytes(orders.by,13); Is it something with the signed/unsigned byte/char thing so I can fix it by changing the python code?

Thanks!

EDIT

I solved one mystery: The Arduino IDE on Linux Mint seems to produce flawed results. I migrated the working code from the RPi to a Windows machine and got the same results for Serial.readBytes((char*)orders.by,15); and Serial.readBytes(orders.by,15); However I ponder why I have to set a length of 15 bytes even though my order is only 13 bytes long.

After you blink the LED, your code doesn't read from the serial for 2 seconds. In the mean time, you are constantly sending data from your Python code. This overflows the serial buffer and your serial stream gets out of sync.

You should slow down your Python code by adding a delay longer than 2 seconds.

while True:
    try:
        ser.write(order)
        time.sleep(3);
    except KeyboardInterrupt:
        quit()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM