使用pySerial连接FPV控制器COM口无数据返回问题求助
解决FPV控制器串口无响应的唤醒问题
问题背景
使用pySerial库通过COM口访问FPV控制器时,连接看似成功,但发送命令后始终得不到响应。仅在BetaFlight CLI中执行命令并释放端口后,代码才能正常运行;但重新插拔USB后,问题复现。推测是代码无法触发控制器的唤醒机制,导致设备忽略命令。
初始代码
port = '/dev/cu.usbmodem0x80000001' baudrate = 115200 import serial import time def read_vtxtable(): try: ser = serial.Serial(port, baudrate, timeout=5, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS) time.sleep(2) except serial.SerialException as e: print(f"Cant open this port {port}: {e}") return [] # Trying to initialize process and make controller alive ser.write('status\n'.encode()) time.sleep(0.05) # Asking controller about vtx data ser.write('vtxtable\n'.encode()) time.sleep(0.05) response = "" start_time = time.time() while time.time() - start_time < 5: if ser.in_waiting > 0: response += ser.read(ser.in_waiting).decode() time.sleep(0.05) ser.close() return response vtxtable_data = read_vtxtable() print(vtxtable_data)
问题根源
BetaFlight设备在USB刚连接后,串口处于等待唤醒的状态,需要特定的触发信号(如连续发送#字符)才能进入可响应命令的模式。初始代码仅发送普通命令,无法触发唤醒,因此设备无响应;而BetaFlight CLI会自动执行唤醒流程,所以后续代码能正常运行。
修复方案
模拟BetaFlight CLI的唤醒逻辑:循环发送#字符,同时检测设备是否进入CLI模式,或通过status命令验证设备已响应。
完整修复代码
port = '/dev/cu.usbmodem0x80000001' baudrate = 115200 import serial import time def wakeup_controller(ser, timeout=10): cli_prompt = "Entering CLI Mode, type 'exit' to return, or 'help'" timeout_time = time.time() + timeout override_wakeup_detection = False buffer = "" def write(cmd): ser.write((cmd + '\n').encode()) def get_info(): output = "" start_time = time.time() while time.time() - start_time < 1: if ser.in_waiting > 0: output += ser.read(ser.in_waiting).decode() time.sleep(0.05) return output while time.time() < timeout_time and not override_wakeup_detection: write('#') time.sleep(0.1) if ser.in_waiting > 0: buffer += ser.read(ser.in_waiting).decode() if cli_prompt in buffer: print("# Found wakeup phrase:", cli_prompt) return True else: print("# No response..") write('status') time.sleep(0.1) output = get_info() if len(output) > 0: print("# The board is alive") override_wakeup_detection = True return True return False def read_vtxtable(): try: ser = serial.Serial(port, baudrate, timeout=5, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS) time.sleep(2) except serial.SerialException as e: print(f"Cant open this port {port}: {e}") return [] # 先执行唤醒流程 if not wakeup_controller(ser): print("# Failed to wake up controller") ser.close() return [] # 发送vtxtable命令 ser.write('vtxtable\n'.encode()) time.sleep(0.05) response = "" start_time = time.time() while time.time() - start_time < 5: if ser.in_waiting > 0: response += ser.read(ser.in_waiting).decode() time.sleep(0.05) ser.close() # 整理响应为列表格式 return [line.strip() for line in response.split('\n') if line.strip()] vtxtable_data = read_vtxtable() print("VTX Table Data:") print('[') for line in vtxtable_data: print(f" '{line}',") print(']')
运行验证
运行修复后的代码,输出示例:
% python3 get_data.py # No response.. # No response.. # No response.. # The board is alive VTX Table Data: [ 'vtxtable', 'vtxtable bands 8', 'vtxtable channels 8', 'vtxtable ... ]
内容的提问来源于stack exchange,提问作者theUkrainian
相关产品推荐
相关产品推荐

