Table of Contents
Raspberry Pi and Arduino Talk with Serial Port Using Python
When a Raspberry Pi and an Arduino need to exchange small amounts of data, the serial port is usually the simplest bridge between them. The Arduino sends and receives bytes over USB serial, and Python on the Raspberry Pi can read and write those bytes with pyserial.
The main point to remember is that serial communication is byte-based. Python strings are not sent directly; they must be encoded into bytes before writing to the serial port, and incoming bytes should be decoded before treating them as text.
message = "string"
data = message.encode("utf-8")
text = data.decode("utf-8")
For one-byte integer values, Python can also convert between integers and characters:
value = 65
char = chr(value) # 'A'
number = ord(char) # 65
Arduino Side
Upload a simple sketch that reads a line from serial and sends a response back. Open the serial port at the same baud rate that Python will use.
void setup() {
Serial.begin(9600);
}
void loop() {
if (Serial.available() > 0) {
String input = Serial.readStringUntil('\n');
input.trim();
Serial.print("Arduino received: ");
Serial.println(input);
}
}
This sketch waits for a newline-terminated message. When it receives one, it prints the received text back to the serial port.
Raspberry Pi Side
Install pyserial if it is not already available:
python3 -m pip install pyserial
Find the Arduino serial device after plugging it into the Raspberry Pi:
ls /dev/ttyACM* /dev/ttyUSB* 2>/dev/null
Common device names are /dev/ttyACM0 for an Arduino Uno or /dev/ttyUSB0 for boards using a USB-to-serial adapter.
Then use Python to send a message and read the response:
import time
import serial
PORT = "/dev/ttyACM0"
BAUD = 9600
with serial.Serial(PORT, BAUD, timeout=2) as ser:
time.sleep(2) # Give the Arduino time to reset after opening serial.
ser.write(b"hello from raspberry pi\n")
ser.flush()
line = ser.readline()
print(line.decode("utf-8", errors="replace").strip())
If the port is correct and both sides use the same baud rate, the Raspberry Pi should print something like:
Arduino received: hello from raspberry pi
Bytes, Strings, and Unicode
In Python 3, serial data should be handled explicitly:
text = "hello"
bytes_to_send = text.encode("utf-8")
received_bytes = b"hello\n"
received_text = received_bytes.decode("utf-8").strip()
Useful conversions:
bytes_value = b"string"
text_value = bytes_value.decode("utf-8")
single_char = chr(65)
single_number = ord("A")
Avoid naming variables str or bytes, because those names shadow Python’s built-in types.
Troubleshooting
If nothing is received, check these points first:
- The Arduino sketch and Python script use the same baud rate.
- The Python script is opening the correct serial device.
- The message ends with
\nif the Arduino code usesreadStringUntil('\n'). - The user running the Python script has permission to access the serial device.
On Raspberry Pi OS, serial permissions are usually handled by the dialout group:
sudo usermod -aG dialout "$USER"
Log out and back in after changing group membership.
For short command and sensor messages, this pattern is enough: send newline-terminated UTF-8 text from one side, decode it on the other side, and keep the byte/string boundary clear in Python.
