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

Python与Arduino Nano串口通信异常:Arduino可发送但无法接收消息

问题诊断与修复方案

核心问题分析

你的代码主要问题出在Arduino的串口读取逻辑,Python端也有小细节需要调整:

  1. Arduino loop() 中的 while (Serial.available() <= 0) 条件完全写反——只有当串口有数据时才应该读取,现在的逻辑是没有数据时才进入读取循环,导致程序卡死在无效的读取操作上,永远无法处理Python发来的消息。
  2. establishContactFAIL() 函数的死循环逻辑错误:一旦进入该函数,只要串口无数据就持续发送TX Failed,但触发该函数的条件本身就是读取到空内容,会导致Arduino陷入无限发送失败消息的循环,无法响应后续的串口输入。
  3. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 17:33:13