Arduino与树莓派串口通信:单次Python代码触发Arduino重启?
Arduino串口通信:单次运行Python代码触发重启的问题与解决
为什么每次单次运行Python代码都会收到初始数据?
是的,调用serial.Serial()打开串口时,确实会触发Arduino Uno重启。
原因在于Arduino Uno的硬件设计:它的USB串口芯片会将串口打开事件转化为DTR引脚的电平变化,而DTR引脚直接连接到Arduino的复位电路。当树莓派这边执行serial.Serial()打开串口时,DTR引脚被拉低,触发Arduino复位,导致sketch从头开始运行——所以你每次都会收到初始的Arduino,7,0(重启后random()的初始种子固定,第一次生成的随机数相同,data2也重置为0)。
而带while True的循环代码只打开一次串口,Arduino仅重启一次,之后持续运行loop(),自然能收到递增的data2序列。
如何编写不触发Arduino重启的单次运行Python程序?
有三种可行方案,按需选择:
方案1:Python代码中禁用DTR信号控制
使用pyserial库的dsrdtr=False参数,打开串口时禁止自动控制DTR引脚,避免触发复位:
import serial # 替换为你的Arduino实际串口端口 arduino_port = "/dev/ttyACM0" # 打开串口时禁用DTR,同时关闭RTS/CTS流控 ser = serial.Serial( port=arduino_port, baudrate=9600, timeout=2.0, dsrdtr=False, rtscts=False ) # 读取一次数据并输出 received_data = ser.readline().decode("utf-8").strip() print(f"Received from Arduino: {received_data}") # 关闭串口 ser.close()
方案2:修改Arduino硬件,断开复位触发
找到Arduino Uno板上RESET引脚与GND之间的跳线帽(部分板是DTR相关的连接点),拔掉跳线帽或剪断DTR到复位电路的连线。这种方法彻底解决重启问题,但会导致后续无法通过USB上传sketch,需要用ISP编程器烧录,适合不需要频繁更新代码的场景。
方案3:在Arduino sketch中保存状态到EEPROM
如果不想修改Python代码或硬件,可以将data2的数值保存在Arduino的EEPROM(非易失性存储)中,每次重启后读取之前的值继续递增:
#include <EEPROM.h> int data1; int data2; void setup() { Serial.begin(9600); // 从EEPROM地址0读取之前的data2值 data2 = EEPROM.read(0); // 首次运行时初始化data2为0(EEPROM初始值为255) if (data2 == 255) { data2 = 0; } } void loop() { data1 = random(0, 50); Serial.print("Arduino,"); Serial.print(data1); Serial.print(","); Serial.println(data2); data2++; // 将新的data2值写入EEPROM,注意EEPROM约有10万次写入寿命 EEPROM.write(0, data2); EEPROM.commit(); delay(2000); }
这种方法即使Arduino重启,也能恢复之前的计数,不会每次都从0开始。
内容的提问来源于stack exchange,提问作者user3217032
相关产品推荐
相关产品推荐

