Search code examples
arduinoraspberry-piserial-portcommunication

Unstable Communication Between Raspberry Pi and Arduino Over Serial


I am making a system where I have a Pi that will send a string over UDP to an Arduino that has Wifi. The Arduino will then send some data back to the Pi. This part works flawlessly. Then the Pi will relay this same data over Serial to an Arduino Mega that has no Wifi. This is my problem. I am able to receive all the data over UDP but when I try to receive data and then send this over Serial, it glitches and nothing works. It just receives null values. I know this because on the Arduino Mega, I have setup a system where it will simply take the data it received and just send it back with the letters "ACK" signed on them so that I know that it was successfully received. All I get is null things. But when I just send the string "HI" over the Serial port and disable the UDP stuff, it magically works... sometimes. What could be going wrong?

Code on the Pi

#!/usr/bin/env python3
import serial
import time
import socket

serialData = 'null \n'


s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
message = b'pi'
addr = ("192.168.71.146", 2390)


def wifirecv():
    global serialData
    s.sendto(message, addr)
    data, address = s.recvfrom(10240)
    #print(data.decode())
    angle = data.decode()
    serialData = angle + ' \n'

while(True):
    ser = serial.Serial('/dev/ttyACM0', 115200, timeout=1)
    ser.flush()
    ser.close()
    ser.open()
    while True:
        try:
            wifirecv()
            print(serialData)
            ser.write(serialData.encode('utf-8'))
            #ser.write(b'hi')
            line = ser.readline().decode('utf-8').rstrip()
            print(line)
        except(KeyboardInterrupt):
            ser.close()
            print("Serial Closed")
            exit()

Code on the Mega

void setup() {
  Serial.begin(115200);

}

void loop() {
  while(Serial.available() != 0){
    String data = Serial.readStringUntil('\n');
    Serial.println(data + ": ACK");
  }

}

Solution

  • Despite you mention that the response from the Arduino works fine, I believe that you should use the SerialEvent interrupt callback rather than polling for the .available method. It is a much more reliable way to detect when data is present in the input buffer. I would form the input string char by char, as done in the official tutorial.

    I think that the approach you opted for might be causing timing issues on the serial port since you said:

    I am able to receive all the data over UDP but when I try to receive data and then send this over Serial, it glitches and nothing works

    those glitches might also be a consequence of the selected baudrate or (again) the polling approach. This is reinforced by your statement:

    Serial port and disable the UDP stuff, it magically works... sometimes

    Have you tried using read_until(LF, None) instead of readline()? I've had better results with the first one in some acquisition routines. Check this for reference

    Are you using any other resources from the Pi or the Arduino? I am not sure if the UDP messes up with the serial communication from the RPi. I would seriously doubt it, but just check if there are no reported issues with the socket library.

    Finally, a tiny time.sleep(ms) between the write() and the read() in your RPi might not hurt the communication too much. For instance, in my recent experience with the I2C protocol, a tiny delay makes a huge difference for reliable communication.

    The bottom line is: you have timing issues.