Hard fault with combination of ESP32SPI and wifi monitor
メンテナーはふだん 1 日以内に返信
@dhalbert がすでに取り組んでいます。
2026年11月2日 から。
評価
この issue はまだ評価されていません。
説明
CircuitPython version and board name
Adafruit CircuitPython 11.0.0-alpha.2-7-ge6bbfee76e on 2026-10-23; FeatherS3 with ESP32S3
(with SPI Airlift FeatherWing)
Adafruit CircuitPython 11.0.0-alpha.2-1-gf2acd4502a on 2026-10-22; Adafruit QT Py ESP32-S3 4MB Flash 2MB PSRAM with ESP32S3
(with SPI WIZnet WIZ850io W5500)
Adafruit CircuitPython 11.0.0-alpha.2-1-gf2acd4502a on 2026-10-22; ESP32-C5-DevKitC-1-N8R8 with ESP32C5
(with SPI WIZnet WIZ850io W5500)
Code/REPL
import time
import os
import random
import traceback
import json
import board
import busio
import digitalio
import supervisor
import microcontroller
from microcontroller import watchdog as w
from watchdog import WatchDogMode
import wifi
import ssl
import adafruit_connection_manager
import adafruit_requests
# set one active configured interface...
active = "eth"
UART = active == "uart"
ETH = active == "eth"
ESP = active == "esp"
# if multiple WIZnet devices, set lowest octet to avoid DHCP conflicts
OCTET = "24" # "ed", "cc", "d0", "24"
def uart_config():
uart = busio.UART(board.TX, board.RX, baudrate=1_000_000, timeout=0.1, receiver_buffer_size=65535)
return uart
def eth_config():
if "ESP32-S3" in os.uname().machine:
spi = board.SPI()
cs = digitalio.DigitalInOut(board.A0)
rst = digitalio.DigitalInOut(board.A1)
elif "ESP32-C5" in os.uname().machine:
spi = busio.SPI(board.IO8, MOSI=board.IO10, MISO=board.IO9)
cs = digitalio.DigitalInOut(board.IO1)
rst = digitalio.DigitalInOut(board.IO0)
return WIZNET5K(spi, cs, reset=rst, mac=f'de:ad:be:ef:fe:{OCTET}', debug=False)
def esp_config():
spi = board.SPI()
esp32_cs = digitalio.DigitalInOut(board.D13)
esp32_reset = digitalio.DigitalInOut(board.D12)
esp32_ready = digitalio.DigitalInOut(board.D11)
while True:
try:
radio = ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset, debug=False)
break
except Exception as ex:
traceback.print_exception(ex, ex, ex.__traceback__)
return radio
def connect(radio):
if radio.__class__.__name__ == "WIZNET5K":
ipv4_str = radio.pretty_ip(radio.ip_address)
elif radio.__class__.__name__ == "ESP_SPIcontrol":
while not radio.is_connected:
try:
radio.connect_AP(os.getenv("WIFI_SSID"), os.getenv("WIFI_PASSWORD"))
except Exception as ex:
traceback.print_exception(ex, ex, ex.__traceback__)
time.sleep(1)
ipv4_str = radio.ipv4_address
return ipv4_str
def do_uart():
print(f'{time.monotonic():.1f} UART writing...', end=' ')
start = time.monotonic()
written = uart.write(outbuf)
print(f'{written} bytes {(time.monotonic() - start):.3f}s')
print(f'{time.monotonic():.1f} UART reading...', end=' ')
start = time.monotonic()
read = uart.readinto(inbuf)
print(f'{read} bytes {(time.monotonic() - start):.3f}s')
def do_radio():
# choose your own URL adventure...
url = f'http://192.168.5.48/hello?{config}'
# url = f'https://httpbin.org/post'
print(f'{time.monotonic():.1f} {config} POSTing {len(outbuf)} bytes')
start = time.monotonic()
try:
with requests.post(url, json={'data': outbuf.decode()}, headers={'user-agent': 'Minimal'}) as r:
inbuf = r.content
end = time.monotonic()
print(f'{time.monotonic():.1f} {(end - start):.3f}s {r.status_code} {r.reason.decode()}')
except TimeoutError as ex: # TimeoutError: ESP32 not responding
end_sec = time.monotonic()
print(f'{time.monotonic():.1f} {(end - start):.3f}s Exception, resetting network and continuing...')
radio.reset()
time.sleep(1)
except Exception as ex:
end_sec = time.monotonic()
print(f'{time.monotonic():.1f} {(end - start):.3f}s Exception, continuing...')
traceback.print_exception(ex, ex, ex.__traceback__)
def restart_notify():
# choose your own URL adventure...
url = f'http://192.168.5.48/hello?{config}&reset={str(microcontroller.cpu.reset_reason).split(".")[-1]}&run={str(supervisor.runtime.run_reason).split(".")[-1]}'
start = time.monotonic()
try:
with requests.get(url, headers={'user-agent': 'Minimal'}) as r:
end = time.monotonic()
print(f'{time.monotonic():.1f} {(end - start):.3f}s {r.status_code} {r.reason.decode()}')
except TimeoutError as ex: # TimeoutError: ESP32 not responding
end_sec = time.monotonic()
print(f'{time.monotonic():.1f} {(end - start):.3f}s Exception, resetting network and continuing...')
radio.reset()
time.sleep(1)
except Exception as ex:
end_sec = time.monotonic()
print(f'{time.monotonic():.1f} {(end - start):.3f}s Exception, continuing...')
traceback.print_exception(ex, ex, ex.__traceback__)
time.sleep(3) # wait for serial
print("=" * 25)
uart = radio = config = None
if UART:
print(f'Initializing UART...')
uart = uart_config()
elif ETH:
from adafruit_wiznet5k.adafruit_wiznet5k import WIZNET5K
print(f'Initializing Ethernet...')
radio = eth_config()
config = "+".join((os.uname().sysname.split("ESP32")[1], radio.__class__.__name__))
print(f'{config} {connect(radio)}')
elif ESP:
from adafruit_esp32spi.adafruit_esp32spi import ESP_SPIcontrol
print(f'Initializing ESP32SPI...')
radio = esp_config()
print(f'Connecting to AP with ESP32SPI...')
esp_ipv4 = connect(radio)
config = "+".join((os.uname().sysname.split("ESP32")[1], "ESP32SPI"))
print(f'{config} {connect(radio)}')
if ETH or ESP:
print(f'Initializing requests...')
pool = adafruit_connection_manager.get_radio_socketpool(radio)
context = adafruit_connection_manager.get_radio_ssl_context(radio)
requests = adafruit_requests.Session(pool, context)
print(f'Initializing watchdog...')
w.timeout = 90
w.mode = WatchDogMode.RESET
print(f'Notifying server of restart...')
restart_notify()
# use for UART, ETH, or ESP
outbuf = bytearray(b'\x5A') * 1024
inbuf = bytearray(1024)
packets = 0
m = wifi.Monitor(queue=1024) # default channel=1
while True:
w.feed()
print("-" * 25)
time.sleep(1)
print(f'{time.monotonic():.1f} {m.queued()=} {m.lost()=}')
p = m.packet()
while p: # and (m.queued() > 50):
packets += 1
p = m.packet()
if random.randint(0, 25) == 0:
if uart:
do_uart()
else:
do_radio()
print(f'{time.monotonic():.1f} {m.queued()=} {m.lost()=}')
print(f'{time.monotonic():.1f} {m.queued()=} {m.lost()=}')
Behavior
CircuitPython firmware used is post- #11651 (includes the fix for wifi monitor re-init hard faults). ESP32SPI, WIZnet, or wifi monitor alone also don't trigger hard faults or watchdog... something about the combination (SPI-related, perhaps; the ESP32SPI and WIZnet libraries don't really do much heavy core stuff other than busio SPI).
Reproducer code is larger than I'd like, but I tried many simpler versions that didn't trigger hard faults or watchdog. Seemingly unrelated code changes can change the behavior, even make hard faults or watchdog timeouts go away, so it's been challenging to come up with a single code.py that will trigger on all three configs that contained what I think are the salient features. It is also possible that there is more than one issue across S3 vs C5, and ESP32SPI vs WIZnet.
Before putting in the watchdog code, the behavior was a permanent "freeze"...serial output stopped, no control-c possible, but MSC (S3, not C5) was still available. Hard reset was required. I may not have watchdog tuned quite right, still testing.
Code changes may also cause hard fault to become watchdog, or vice versa. It seems to be easier to trigger hard faults with longer, more complex code. Likewise, it seems harder to trigger hard faults with shorter, simpler code. Hard fault or watchdog seem to occur during an HTTP POST from the client point of view. The server will occasionally give a 400, 408, or 500 response with an exception indicating an incomplete request.
With the code above:
- S3 + ESP32SPI will hard fault in about 1 minute
- S3 + WIZnet will watchdog in 5-15 minutes
- C5 + WIZnet will watchdog in under 30 seconds (longer, given the addendum in Additional Information below)
The hard fault on the S3+ESP32SPI is the easiest to replicate with the above code.
I also tested UART (thinking it might be related to interrupts or some general busio issue), but did not see any hard faults or watchdog timeouts.
To test on hardware: there are a couple of the constants at the top of the code.py that may need to be tweaked, depending on testing config. Also the URL(s) used can (I think) be any HTTP server you can POST to. I mainly used a local server to capture the server log (and intervals between crashes), but also verified behavior with httpbin.org/post (commented out due to frequency of POSTs).
Here is almost 45 minutes of server log showing the hard faults and watchdogs:
access.log
192.168.9.208 - - [01/Nov/2026:17:43:52 -0600] "GET /hello?S3+WIZNET5K&reset=POWER_ON&run=STARTUP HTTP/1.1" 200 242 "-" "Minimal"
192.168.6.43 - - [01/Nov/2026:17:43:54 -0600] "GET /hello?S3+ESP32SPI&reset=POWER_ON&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.9.36 - - [01/Nov/2026:17:43:56 -0600] "GET /hello?C5+WIZNET5K&reset=POWER_ON&run=STARTUP HTTP/1.1" 200 243 "-" "Minimal"
192.168.6.43 - - [01/Nov/2026:17:44:51 -0600] "GET /hello?S3+ESP32SPI&reset=SOFTWARE&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.9.36 - - [01/Nov/2026:17:45:40 -0600] "GET /hello?C5+WIZNET5K&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.6.43 - - [01/Nov/2026:17:46:53 -0600] "GET /hello?S3+ESP32SPI&reset=SOFTWARE&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.9.36 - - [01/Nov/2026:17:47:27 -0600] "GET /hello?C5+WIZNET5K&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.6.43 - - [01/Nov/2026:17:48:47 -0600] "GET /hello?S3+ESP32SPI&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.9.36 - - [01/Nov/2026:17:49:11 -0600] "GET /hello?C5+WIZNET5K&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.9.208 - - [01/Nov/2026:17:49:48 -0600] "GET /hello?S3+WIZNET5K&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 245 "-" "Minimal"
192.168.6.43 - - [01/Nov/2026:17:50:46 -0600] "GET /hello?S3+ESP32SPI&reset=SOFTWARE&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.9.36 - - [01/Nov/2026:17:50:54 -0600] "GET /hello?C5+WIZNET5K&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.9.36 - - [01/Nov/2026:17:52:41 -0600] "GET /hello?C5+WIZNET5K&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.6.43 - - [01/Nov/2026:17:53:14 -0600] "GET /hello?S3+ESP32SPI&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.9.36 - - [01/Nov/2026:17:54:24 -0600] "GET /hello?C5+WIZNET5K&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.6.43 - - [01/Nov/2026:17:55:21 -0600] "GET /hello?S3+ESP32SPI&reset=SOFTWARE&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.6.43 - - [01/Nov/2026:17:55:56 -0600] "GET /hello?S3+ESP32SPI&reset=SOFTWARE&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.9.36 - - [01/Nov/2026:17:56:08 -0600] "GET /hello?C5+WIZNET5K&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.9.208 - - [01/Nov/2026:17:56:49 -0600] "GET /hello?S3+WIZNET5K&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 245 "-" "Minimal"
192.168.9.36 - - [01/Nov/2026:17:57:51 -0600] "GET /hello?C5+WIZNET5K&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.6.43 - - [01/Nov/2026:17:58:11 -0600] "GET /hello?S3+ESP32SPI&reset=SOFTWARE&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.9.36 - - [01/Nov/2026:17:59:34 -0600] "GET /hello?C5+WIZNET5K&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.6.43 - - [01/Nov/2026:18:00:11 -0600] "GET /hello?S3+ESP32SPI&reset=SOFTWARE&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.9.36 - - [01/Nov/2026:18:01:18 -0600] "GET /hello?C5+WIZNET5K&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.6.43 - - [01/Nov/2026:18:02:28 -0600] "GET /hello?S3+ESP32SPI&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.9.36 - - [01/Nov/2026:18:03:01 -0600] "GET /hello?C5+WIZNET5K&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.6.43 - - [01/Nov/2026:18:03:37 -0600] "GET /hello?S3+ESP32SPI&reset=SOFTWARE&run=STARTUP HTTP/1.1" 200 242 "-" "Minimal"
192.168.6.43 - - [01/Nov/2026:18:04:24 -0600] "GET /hello?S3+ESP32SPI&reset=SOFTWARE&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.9.36 - - [01/Nov/2026:18:04:45 -0600] "GET /hello?C5+WIZNET5K&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 243 "-" "Minimal"
192.168.6.43 - - [01/Nov/2026:18:06:06 -0600] "GET /hello?S3+ESP32SPI&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.9.36 - - [01/Nov/2026:18:06:28 -0600] "GET /hello?C5+WIZNET5K&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.6.43 - - [01/Nov/2026:18:07:16 -0600] "GET /hello?S3+ESP32SPI&reset=SOFTWARE&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.9.36 - - [01/Nov/2026:18:08:15 -0600] "GET /hello?C5+WIZNET5K&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.9.208 - - [01/Nov/2026:18:08:51 -0600] "GET /hello?S3+WIZNET5K&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 245 "-" "Minimal"
192.168.6.43 - - [01/Nov/2026:18:09:44 -0600] "GET /hello?S3+ESP32SPI&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.9.36 - - [01/Nov/2026:18:09:59 -0600] "GET /hello?C5+WIZNET5K&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.6.43 - - [01/Nov/2026:18:10:48 -0600] "GET /hello?S3+ESP32SPI&reset=SOFTWARE&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.9.36 - - [01/Nov/2026:18:11:42 -0600] "GET /hello?C5+WIZNET5K&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.6.43 - - [01/Nov/2026:18:13:09 -0600] "GET /hello?S3+ESP32SPI&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.9.36 - - [01/Nov/2026:18:13:25 -0600] "GET /hello?C5+WIZNET5K&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.6.43 - - [01/Nov/2026:18:15:00 -0600] "GET /hello?S3+ESP32SPI&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 242 "-" "Minimal"
192.168.9.36 - - [01/Nov/2026:18:15:11 -0600] "GET /hello?C5+WIZNET5K&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.9.208 - - [01/Nov/2026:18:15:54 -0600] "GET /hello?S3+WIZNET5K&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 245 "-" "Minimal"
192.168.9.36 - - [01/Nov/2026:18:16:54 -0600] "GET /hello?C5+WIZNET5K&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.6.43 - - [01/Nov/2026:18:17:04 -0600] "GET /hello?S3+ESP32SPI&reset=SOFTWARE&run=STARTUP HTTP/1.1" 200 243 "-" "Minimal"
192.168.6.43 - - [01/Nov/2026:18:17:53 -0600] "GET /hello?S3+ESP32SPI&reset=SOFTWARE&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.9.36 - - [01/Nov/2026:18:18:39 -0600] "GET /hello?C5+WIZNET5K&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.6.43 - - [01/Nov/2026:18:19:54 -0600] "GET /hello?S3+ESP32SPI&reset=SOFTWARE&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.9.36 - - [01/Nov/2026:18:20:22 -0600] "GET /hello?C5+WIZNET5K&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.6.43 - - [01/Nov/2026:18:20:39 -0600] "GET /hello?S3+ESP32SPI&reset=SOFTWARE&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.9.36 - - [01/Nov/2026:18:22:16 -0600] "GET /hello?C5+WIZNET5K&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 243 "-" "Minimal"
192.168.9.208 - - [01/Nov/2026:18:22:27 -0600] "GET /hello?S3+WIZNET5K&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 245 "-" "Minimal"
192.168.6.43 - - [01/Nov/2026:18:22:42 -0600] "GET /hello?S3+ESP32SPI&reset=SOFTWARE&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
192.168.9.36 - - [01/Nov/2026:18:23:59 -0600] "GET /hello?C5+WIZNET5K&reset=WATCHDOG&run=STARTUP HTTP/1.1" 200 243 "-" "Minimal"
192.168.6.43 - - [01/Nov/2026:18:24:52 -0600] "GET /hello?S3+ESP32SPI&reset=SOFTWARE&run=STARTUP HTTP/1.1" 200 244 "-" "Minimal"
"reset=WATCHDOG" in the log is clear enough. "reset=SOFTWARE" indicates a hard fault in these cases. It takes more code to capture the safemode reason (it must be done in safemode.py and passed to code.py using a file, nvm, or alarm memory), and I stripped that out of this version.
Description
No response
Additional information
addendum: I have a slight error in the posted code (different from many prior iterations) where the watchdog should be fed within the while p: loop, but I don't think this fully explains the watchdogs, especially since there were freezes before the watchdog code. Responses are typically about a half second, pretty consistently, and the monitor queue drains in 5-10 seconds on S3+ESP32SPI (allowing the watchdog to be fed). I put the watchdog inside the loop now, and adjusted the random.randint() upwards (to 50 on the C5) to keep the monitor queue from growing too fast, and the watchdog timeouts still occur during POST. I'll continue to test variations and add anything that may help.
(Some previous WIZnet-specific comments on this issue were in #11472)
- 主要言語
- C
- スター
- 4.6k
- フォーク
- 1.4k
- 平均マージ
- 1日 9時間
- マージ済み PR(30日)
- 173
環境構築
このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
adafruit/circuitpython のほかの issue
-
documentation enhancement
難易度 2/5 1〜3時間 初心者へのやさしさ 67/100
adafruit/circuitpython#11689 ·
メンテナーはふだん 1 日以内に返信
-
SD card read errors are not reported to the host and send bad data対応中かも @mikeysklar が今日担当しました。 オープンbug sdcardio storage usb
難易度 3/5 1〜2日 初心者へのやさしさ 55/100
adafruit/circuitpython#11715 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
-
Feather RP2350: MAX3421E instead of PIO USB host, or a second build?対応中かも @mikeysklar が 4 日前に担当しました。 オープンrp2 usb
adafruit/circuitpython#11697 · コメント 5 件 · 担当者 2 名 ·
メンテナーはふだん 1 日以内に返信
-
rp2040 zephyr
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
adafruit/circuitpython#11690 ·
メンテナーはふだん 1 日以内に返信
-
Metro ESP32-P4 wifi issue/packet loss対応中かも @dhalbert が今日担当しました。 オープンbug esp32-p4 network
難易度 4/5 1〜2日 初心者へのやさしさ 45/100
adafruit/circuitpython#11682 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
adafruit/circuitpython の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
ly05010419/MacNativeGames#1697 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
aminya/project_options#303 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 90/100
メンテナーはふだん 1 日以内に返信
-
bug core p3
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
RunanywhereAI/runanywhere-sdks#1258 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
rocketproplab/phoenix-fc-sensor-board#18 · コメント 1 件 ·