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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 03:24:59