Search code examples
pythonarduinoserial-portpyserial

How to write and read binary (not ASCII encoded) to Arduino with pyserial


I need to make a Raspberry Pi communicate with an Arduino. I will only need values between 0 and 180, and this is within the range of a single byte so I want to only send the value in binary, and not send it with ASCII encoding for faster transfer (i.e.: if I want to write a "123" to the Arduino, I want 0x7B to be sent, and not the ASCII codes for 1, then 2, then 3 (0x31,0x32, 0x33).

In my testing I have been trying to write a Python program that will take an integer within that range and then send it over serial in binary.

Here is a test I was trying. I want to write a binary number to the Arduino, and then have the Arduino print out the value it received.

Python code:

USB_PORT = "/dev/ttyUSB0"  # Arduino Uno WiFi Rev2

import serial

try:
   usb = serial.Serial(USB_PORT, 9600, timeout=2)
except:
   print("ERROR - Could not open USB serial port.  Please check your port name and permissions.")
   print("Exiting program.")
   exit()

while True:
    command = int(input("Enter command: "))
    usb.write(command)
    
    value = (usb.readline())
    print("You sent:", value)

And here is the Arduino code

byte command;
void setup()
{
    Serial.begin(9600);

}

void loop()
{
    if (Serial.available() > 0)
    {
        command = Serial.read();
        Serial.print(command);
    }
    
}

All this gives me is this:

Enter command: 1
You sent: b'0'
Enter command: 4
You sent: b'0000'

Solution

  • usb.write(command) expects command to be of type bytes not int.

    It seems the write method internally calls bytes(), since it sends the number of zero bytes that you called it with.
    Calling bytes() with an integer, creates a zero filled byte array, with the specified number of zeroes.
    If you want to send a single byte, you need to call it with a list with a single element.

    You should do:

    command = bytes([int(input("Enter command: "))])