Matrix Portal M4调用API遇BrokenPipeError,升级NINA固件失败求助
BrokenPipeError on Matrix Portal M4 + NINA Firmware Upgrade Sync Failures
问题详情
使用搭载CircuitPython的Adafruit Matrix Portal M4开发项目,调用API获取数据时触发BrokenPipeError: Expected 01 but got 00,错误回溯如下:
Retrieving data...Traceback (most recent call last): File "code.py", line 81, in <module> File "code.py", line 25, in get_arrival_times File "adafruit_portalbase/network.py", line 645, in fetch_data File "adafruit_portalbase/network.py", line 563, in fetch File "adafruit_requests.py", line 715, in get File "adafruit_requests.py", line 647, in request File "adafruit_connection_manager.py", line 347, in get_socket File "adafruit_connection_manager.py", line 249, in _get_connected_socket File "adafruit_connection_manager.py", line 61, in connect File "adafruit_esp32spi/adafruit_esp32spi_socketpool.py", line 114, in connect File "adafruit_esp32spi/adafruit_esp32spi.py", line 917, in socket_connect File "adafruit_esp32spi/adafruit_esp32spi.py", line 813, in socket_open File "adafruit_esp32spi/adafruit_esp32spi.py", line 430, in _send_command_get_response File "adafruit_esp32spi/adafruit_esp32spi.py", line 400, in _wait_response_cmd File "adafruit_esp32spi/adafruit_esp32spi.py", line 382, in _check_data BrokenPipeError: Expected 01 but got 00
尝试升级NINA固件解决问题时,Adafruit ESPTool报错:
Connecting... Connected successfully. Try hard reset. [Object.debug:191] Finished read loop Error: Couldn't sync to ESP. Try resetting.
项目代码参考第三方实现,具体如下:
import time import microcontroller from board import NEOPIXEL import displayio import adafruit_display_text.label from adafruit_datetime import datetime from adafruit_bitmap_font import bitmap_font from adafruit_matrixportal.matrix import Matrix from adafruit_matrixportal.network import Network STOP_ID = 'A31' DATA_SOURCE = 'https://api.wheresthefuckingtrain.com/by-id/%s' % (STOP_ID,) DATA_LOCATION = ["data"] UPDATE_DELAY = 15 SYNC_TIME_DELAY = 30 MINIMUM_MINUTES_DISPLAY = 9 BACKGROUND_IMAGE = 'assets/g-dashboard.bmp' ERROR_RESET_THRESHOLD = 3 def get_arrival_in_minutes_from_now(now, date_str): train_date = datetime.fromisoformat(date_str).replace(tzinfo=None) # Remove tzinfo to be able to diff dates return round((train_date-now).total_seconds()/60.0) def get_arrival_times(): stop_trains = network.fetch_data(DATA_SOURCE, json_path=(DATA_LOCATION,)) stop_data = stop_trains[0] nortbound_trains = [x['time'] for x in stop_data['N']] southbound_trains = [x['time'] for x in stop_data['S']] now = datetime.now() print("Now: ", now) nortbound_arrivals = [get_arrival_in_minutes_from_now(now, x) for x in nortbound_trains] southound_arrivals = [get_arrival_in_minutes_from_now(now, x) for x in southbound_trains] n = [str(x) for x in nortbound_arrivals if x>= MINIMUM_MINUTES_DISPLAY] s = [str(x) for x in southound_arrivals if x>= MINIMUM_MINUTES_DISPLAY] n0 = n[0] if len(n) > 0 else '-' n1 = n[1] if len(n) > 1 else '-' s0 = s[0] if len(s) > 0 else '-' s1 = s[1] if len(s) > 1 else '-' return n0,n1,s0,s1 def update_text(n0, n1, s0, s1): text_lines[2].text = "%s,%s m" % (n0,n1) text_lines[4].text = "%s,%s m" % (s0,s1) display.root_group = group # --- Display setup --- matrix = Matrix() display = matrix.display network = Network(status_neopixel=NEOPIXEL, debug=False) # --- Drawing setup --- group = displayio.Group() bitmap = displayio.OnDiskBitmap(open(BACKGROUND_IMAGE, 'rb')) colors = [0x444444, 0xDD8000] # [dim white, gold] font = bitmap_font.load_font("assets/fonts/6x10.bdf") text_lines = [ displayio.TileGrid(bitmap, pixel_shader=getattr(bitmap, 'pixel_shader', displayio.ColorConverter())), adafruit_display_text.label.Label(font, color=colors[0], x=20, y=3, text="Queens"), adafruit_display_text.label.Label(font, color=colors[1], x=20, y=11, text="- mins"), adafruit_display_text.label.Label(font, color=colors[0], x=20, y=20, text="Church"), adafruit_display_text.label.Label(font, color=colors[1], x=20, y=28, text="- mins"), ] for x in text_lines: group.append(x) display.root_group = group error_counter = 0 last_time_sync = None while True: try: if last_time_sync is None or time.monotonic() > last_time_sync + SYNC_TIME_DELAY: # Sync clock to minimize time drift network.get_local_time() last_time_sync = time.monotonic() arrivals = get_arrival_times() update_text(*arrivals) except (ValueError, RuntimeError) as e: print("Some error occured, retrying! -", e) error_counter = error_counter + 1 if error_counter > ERROR_RESET_THRESHOLD: microcontroller.reset() time.sleep(UPDATE_DELAY)
解决方案建议
1. 解决NINA固件升级同步失败问题
这是修复BrokenPipeError的核心步骤,尝试以下操作:
- 进入正确的固件上传模式:按住Matrix Portal M4上的
BOOT按钮,然后按RESET按钮,等待NeoPixel变为紫色后再松开BOOT,此时设备进入可烧录状态,再运行esptool。 - 检查硬件连接:使用带数据传输功能的USB线(避免用纯充电线),直接连接电脑后置USB端口(不要通过USB集线器)。
- 手动指定串口:先在系统设备管理器(Windows)或
ls /dev/tty.usbmodem*(Mac/Linux)找到设备对应的串口,运行esptool时添加--port参数,例如:esptool.py --port /dev/tty.usbmodem14101 write_flash 0x0 nina-fw.bin - 调整esptool版本:尝试安装旧版本esptool(如3.3)或最新版,命令:
pip install esptool==3.3 # 或安装最新版 pip install --upgrade esptool
2. 临时规避网络错误(固件升级前)
- 捕获BrokenPipeError:修改代码中的异常捕获逻辑,加入对
BrokenPipeError的处理,避免直接触发设备重置:except (ValueError, RuntimeError, BrokenPipeError) as e: - 增加请求超时:调用
fetch_data时添加超时参数,避免长时间等待:stop_trains = network.fetch_data(DATA_SOURCE, json_path=(DATA_LOCATION,), timeout=10) - 降低请求频率:将
UPDATE_DELAY从15秒调整为30秒,减少网络请求次数,降低连接出错概率。 - 开启网络调试:初始化Network时开启debug模式,查看更详细的网络交互日志,定位问题:
network = Network(status_neopixel=NEOPIXEL, debug=True)
内容的提问来源于stack exchange,提问作者goldstar
相关产品推荐
相关产品推荐

