penguin86
penguin86

Reputation: 109

Unable to send byte from Python serial.write() to Arduino

I wrote a python script that sends and receive data to and from an Arduino. I can receive data without problems, but when I send data it seems like the Arduino is receiving only garbage. The Arduino is connected to a linux pc via USB and the pc is running Python 3.8. Since the original code contains a lot of unrelated stuff and may be distracting, I prepared the simplest possible sketch to demontrate the problem:

Python code:

#! /usr/bin/env python

import serial
import time

if __name__ == '__main__':
    ser = serial.Serial("/dev/ttyACM0", 9600, timeout=0)
    time.sleep(5)   # Wait for Arduino to reset and init serial
    ser.write(67)

Arduino sketch

const byte LED_PIN = 13;

void setup() {
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);
  
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
}

void loop() {
  if (Serial.available() > 0) {      
    byte b = Serial.read();
    if (b == 67) {
         digitalWrite(LED_PIN, HIGH);
         delay(500);
         digitalWrite(LED_PIN, LOW);
    }
  }
}

This code flashes the onboard LED when receives a byte with value 67 (uppercase C). This works with the Arduino Serial Monitor, but not when running the Python script. I feel like my problem may be related to this question, but in that case the focus was on the user not considering the case of an empty serial input buffer, while I believe the problem is actually in the sent data. This is why I decided to leave out the receiving part and simplify the example using only the onboard led.

Update

I made it work changing the last line in the python script to:

    ser.write(bytes([67]))

(note the [] added around the integer value).

Anyone can explain why this syntax produces the correct result? It seems like I'm passing a single entry array to the function bytes().

Pardon my poor skills in Pyton, I know the question is probably basic.

Upvotes: 1

Views: 2118

Answers (1)

TomServo
TomServo

Reputation: 7409

It's really simple; the methods you tried that worked all conform to the specification for the pyserial library.

Per the Pyserial documentation:

write(data)
Parameters: data – Data to send.
Returns:    Number of bytes written.
Return type:    int
Raises: SerialTimeoutException – In case a write timeout is configured for the port and the time is exceeded.
Write the bytes data to the port. This should be of type bytes (or compatible such as bytearray or memoryview). Unicode strings must be encoded (e.g. 'hello'.encode('utf-8').

This is why the b'C style worked as well as the bytes call.

Attribution: Pyserial Page

Upvotes: 1

Related Questions