Python与Arduino Nano串口通信异常:Arduino可发送但无法接收消息
问题诊断与修复方案
核心问题分析
你的代码主要问题出在Arduino的串口读取逻辑,Python端也有小细节需要调整:
- Arduino
loop()中的while (Serial.available() <= 0)条件完全写反——只有当串口有数据时才应该读取,现在的逻辑是没有数据时才进入读取循环,导致程序卡死在无效的读取操作上,永远无法处理Python发来的消息。 establishContactFAIL()函数的死循环逻辑错误:一旦进入该函数,只要串口无数据就持续发送TX Failed,但触发该函数的条件本身就是读取到空内容,会导致Arduino陷入无限发送失败消息的循环,无法响应后续的串口输入。- Python端启用了
dsrdtr=True,Arduino Nano不需要硬件握手信号,这个配置可能干扰串口通信。
修复后的代码
Arduino代码
void setup() { Serial.begin(9600); delay(1000); // 给串口初始化留时间 } void loop() { // 只有当串口有数据时才读取 if (Serial.available() > 0) { String command = Serial.readStringUntil('\n'); command.trim(); // 去除首尾空白(包括换行、空格) if (command == "TX") { Serial.println("RX"); delay(300); } else { // 收到未知指令时的反馈 Serial.println("Unknown command"); } } else { // 无数据时不做任何操作,避免死循环发送失败消息 // 如果需要心跳,可以在这里定时发送,但不要阻塞 } } // 移除原有的establishContactFAIL函数,避免死循环问题
Python代码
import serial import serial.tools.list_ports import time def getPort(): ports = serial.tools.list_ports.comports() connected = [element.device for element in ports] print("Connected COM ports: " + str(connected)) if not connected: print("No Port Available") return None return connected def establishConnection(ser): try: if not ser.is_open: ser.open() print("port open") print("PythonMSG: Transmitting") # 发送不带多余空格的指令,trim后和Arduino的判断匹配 ser.write(b'TX\n') # 给Arduino留处理时间 time.sleep(0.1) response = ser.readline().decode('utf-8').strip() if response: if response == 'TX Failed': print("No transmission received, try restarting device") else: print(f"ArduinoMSG: {response}") except serial.SerialException as e: if 'PermissionError' in str(e): print("Ensure you have the necessary permissions to access the COM port.") except KeyboardInterrupt: print("Communication interrupted") if ser.is_open: ser.close() finally: if ser.is_open: ser.close() def serialComm_Main(port): baudrate = 9600 # 关闭dsrdtr硬件握手,Arduino不需要 ser = serial.Serial(port, baudrate, bytesize=8, timeout=5, dsrdtr=False) establishConnection(ser) def Main(): port_list = getPort() if not port_list: print("Error: No valid port found") return port = port_list[0] serialComm_Main(port) Main()
额外注意事项
- 上传Arduino代码时,确保Python程序没有占用串口,否则会导致上传失败。
- 观察Arduino的RX指示灯:当Python发送消息时,RX灯应该闪烁,这表明数据已被Arduino接收。
- 如果仍有问题,检查串口波特率是否完全一致(两边都是9600),以及USB线是否正常(有些充电线没有数据传输功能)。
内容的提问来源于stack exchange,提问作者AustinB
相关产品推荐
相关产品推荐

