Raspberry Pi 和 Arduino 使用 Python 通过串口通信
当 Raspberry Pi 和 Arduino 需要交换少量数据时,串口通常是二者之间最简单的桥梁。Arduino 通过 USB 串口发送和接收字节,而 Raspberry Pi 上的 Python 可以使用 pyserial 读写这些字节。
需要记住的重点是:串口通信是基于字节的。Python 字符串不能直接发送;写入串口前必须先编码成字节,而收到的字节在作为文本处理前也应该先解码。
message = "string"
data = message.encode("utf-8")
text = data.decode("utf-8")
对于单字节整数值,Python 也可以在整数和字符之间转换:
value = 65
char = chr(value) # 'A'
number = ord(char) # 65
Arduino 端
上传一个简单的 sketch,从串口读取一行内容,并把响应发送回去。串口波特率需要与 Python 使用的波特率一致。
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);
}
}
这个 sketch 会等待以换行符结尾的消息。收到消息后,它会把收到的文本打印回串口。
Raspberry Pi 端
如果还没有安装 pyserial,先安装它:
python3 -m pip install pyserial
将 Arduino 插入 Raspberry Pi 后,查找 Arduino 的串口设备:
ls /dev/ttyACM* /dev/ttyUSB* 2>/dev/null
常见设备名包括 Arduino Uno 使用的 /dev/ttyACM0,或使用 USB 转串口适配器的开发板所用的 /dev/ttyUSB0。
然后使用 Python 发送一条消息并读取响应:
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 pin")
ser.flush()
line = ser.readline()
print(line.decode("utf-8", errors="replace").strip())
如果端口正确,并且两端使用相同的波特率,Raspberry Pi 应该会打印出类似内容:
Arduino received: hello from raspberry pi
字节、字符串和 Unicode
在 Python 3 中,串口数据应该显式处理:
text = "hello"
bytes_to_send = text.encode("utf-8")
received_bytes = b"hellon"
received_text = received_bytes.decode("utf-8").strip()
有用的转换:
bytes_value = b"string"
text_value = bytes_value.decode("utf-8")
single_char = chr(65)
single_number = ord("A")
避免把变量命名为 str 或 bytes,因为这些名称会遮蔽 Python 的内置类型。
故障排查
如果没有收到任何内容,先检查以下几点:
- Arduino sketch 和 Python 脚本使用相同的波特率。
- Python 脚本打开的是正确的串口设备。
- 如果 Arduino 代码使用
readStringUntil('n'),消息需要以n结尾。 - 运行 Python 脚本的用户有权限访问串口设备。
在 Raspberry Pi OS 上,串口权限通常由 dialout 用户组处理:
sudo usermod -aG dialout "$USER"
更改用户组成员关系后,请注销并重新登录。
对于简短的命令和传感器消息,这种模式已经足够:从一端发送以换行符结尾的 UTF-8 文本,在另一端解码,并在 Python 中清楚地区分字节和字符串的边界。
