You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 23:42:30