Issue with Pyserial/Arduino Communication

Hello all, frustrated Arduino noob here.

I'm trying to communicate with an Arduino using pyserial, and they don't seem to be communicating. I'm attempting to isolate the issue by reducing the problem down to just trying to make the LED turn on and off, but I'm still finding no luck after hours of googling and fiddling. My Python code is as follows:

import serial, struct, time
ser = serial.Serial(port='/dev/ttyACM0')
time.sleep(3)
a = 1
ser.write(struct.pack(">B", a))

and the Arduino code is

int ledPin = 13;

void setup() {
  Serial.begin(115200);
  pinMode(ledPin, OUTPUT);

  while(!Serial);

}

void loop() {
  if(Serial.available()){
    int input = Serial.read();
    Serial.println(input);
    if(input == 49 || input == 1){
      digitalWrite(stepPin, HIGH);
    }
    if(input == 0 || input == 48){
      digitalWrite(stepPin, LOW);
    }
  }
}

The perplexing thing is that, if I open the serial port in a Python terminal, then open the Serial Monitor in the Arduino software, everything works fine. The light turns on and off with a 1 or a zero using the code above in the Python terminal...but if I don't open the Serial Monitor, or I exit the serial monitor then close and reopen the port, nothing at all...I've been trying every variation of struct.unpack or encode() in case it's how the input is being parsed, but it doesn't look like Serial.available() is ever evaluating as nonzero...I feel like I've been searching for hours and have tried everything I could find or think of, so I'd be really grateful if anyone could provide some insight as to what is happening here.

Try printing out input to help you debug.

Try this Python

import serial, struct, time
ser = serial.Serial('/dev/ttyACM0',115200, timeout=3)
time.sleep(3)
if ser.in_waiting:
    junk = ser.readline().strip() # clean any junk from the buffer
    print("junk: " + junk[-10:].decode("utf-8")) 
a = 1 # or send an 'a' which is an easy key to press e.g. a =ord('a')
# Python 3.6 strings are utf-8, they seem to need encode to ascii for Pyserial
ser.write((chr(a)).encode('ascii'))
echo = ser.readline().strip()
print("debug: " + echo[-10:].decode("utf-8"))

Update: tested and fixed

This Python - Arduino demo may help. See also the more recent Serial Input Basics

...R

Which Arduino are you using? The issue you describe is almost always due to not opening the serial port correctly on the PC end.

Hi everybody,

I observed very similar behavior with interfacing to a Uno3 last week. Opening a serial port with pyserial did not work, unless I opened the port with the Arduino IDE beforehand.

For future reference:
I traced my problem down to my usage of pyserial: I used an ipython3 terminal in WSL 1 (Windows Subsystem for Linux) on windows 10. The problem only occured with this setup. When using the powershell of windows10, I was able to open the serial port with pyserial correctly. I guess the problem lies somewhere in the handling of serial ports in WSL1.

I know this might not exactly be what you have been seeing, but might be helpful for others encountering this in the future.

1 Like