Raspberry Pi 和 Arduino 使用 Python 通过串口通信

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")

避免把变量命名为 strbytes,因为这些名称会遮蔽 Python 的内置类型。

故障排查

如果没有收到任何内容,先检查以下几点:

  1. Arduino sketch 和 Python 脚本使用相同的波特率。
  2. Python 脚本打开的是正确的串口设备。
  3. 如果 Arduino 代码使用 readStringUntil('n'),消息需要以 n 结尾。
  4. 运行 Python 脚本的用户有权限访问串口设备。

在 Raspberry Pi OS 上,串口权限通常由 dialout 用户组处理:

sudo usermod -aG dialout "$USER"

更改用户组成员关系后,请注销并重新登录。

对于简短的命令和传感器消息,这种模式已经足够:从一端发送以换行符结尾的 UTF-8 文本,在另一端解码,并在 Python 中清楚地区分字节和字符串的边界。

Leave a Reply