Progress Log: ESP32 フラッシュ書き込みエラーの解決#

Task Description#

OSECHI検出器のESP32へのファームウェア書き込み時に以下のエラーが発生:

TypeError: argument of type 'NoneType' is not iterable
WARNING: Failed to communicate with the flash chip
Packet content transfer stopped

Arduino IDEからの書き込みが繰り返し失敗し、フラッシュチップとの通信ができない状態だった。

Outcome#

根本原因: OSECHIの電源スイッチがOFFだったため、ESP32に正常な電源が供給されず、GPIO12がフローティング状態になっていた。

解決策: スイッチをONにすることで、フラッシュ電圧が1.8Vから3.3Vに正常化し、書き込みが成功。

Learnings#

1. ESP32フラッシュ電圧の判定メカニズム#

ESP32は起動時に**GPIO12 (MTDI)**のレベルでフラッシュ電圧を判定:

GPIO12 = LOW (GND)       → 3.3V フラッシュ(標準)
GPIO12 = HIGH (3.3V)     → 1.8V フラッシュ(特殊)
GPIO12 = フローティング    → 不定(エラーの原因)

スイッチOFF状態ではGPIO12が不安定になり、誤って1.8V判定されていた。

2. 診断に有効だったコマンド#

# フラッシュ情報の取得
python3 -m esptool --port /dev/cu.usbserial-110 --baud 115200 flash_id

正常時の出力:

Manufacturer: 20 (XMC)
Device: 4017
Detected flash size: 8MB
Flash voltage: 3.3V

異常時の出力:

Manufacturer: ff
Device: ffff
Detected flash size: Unknown
Flash voltage: 1.8V

ff/ffffという値は、フラッシュチップと通信できていないことを示す重要な指標。

3. ESP32-D0WD-V3のフラッシュ仕様#

検出されたチップ情報:

  • Chip: ESP32-D0WD-V3 (revision v3.1)

  • Flash: XMC 8MB (Manufacturer: 20, Device: 4017)

  • Crystal: 40MHz

  • Features: Wi-Fi, BT, Dual Core, 240MHz

4. 確認済みの書き込み設定(Arduino IDE)#

Board: ESP32 Dev Module
Upload Speed: 115200
Flash Mode: QIO / DIO  ← どちらでも書き込み成功
Flash Size: 8MB (64Mb)  ← 重要!4MBではない
Flash Frequency: 40MHz

確認結果: スイッチONの状態であれば、QIOモードでもDIOモードでも書き込みが成功する。Flash Modeの選択は問題の原因ではなかった。

5. Flash ModeによるGPIOピン使用の違い#

QIO (Quad I/O):

  • データ線: 4本 (IO0, IO1, IO2, IO3)

  • 最速だが、外部ハードウェアと干渉しやすい

DIO (Dual I/O):

  • データ線: 2本 (IO0, IO1)

  • QIOより遅いが、安定性と互換性が高い

OSECHI検出器のように外部センサーを接続する場合、DIOモードが推奨

6. 書き込み時に重要なGPIOピン#

以下のピンは書き込み時に特別な役割を持つため、外部回路と干渉しやすい:

  • GPIO0: ブートモード選択(BOOT ボタン)

  • GPIO2: フラッシュデータ(QIO/QOUTモード時)

  • GPIO12 (MTDI): フラッシュ電圧選択

  • GPIO15 (MTDO): ブートメッセージ制御

これらのピンを使用する場合、プルダウン/プルアップ抵抗の追加が必要。

Next Steps#

データ取得の開始#

ファームウェアが正常に書き込まれたので、データ取得を開始できる:

# シリアルポート確認
haniwers-v1 port list

# データ受信テスト
haniwers-v1 port test /dev/cu.usbserial-110

# データ取得開始
haniwers-v1 daq --config examples/daq.toml

ドキュメント化の候補#

このトラブルシューティング経験を以下のドキュメントに反映することを検討:

  1. docs/users/: ユーザー向けトラブルシューティングガイド

    • ESP32書き込みエラーの一般的な原因と解決策

    • OSECHI電源スイッチの重要性

  2. docs/developers/faq.md: 開発者向けFAQ

    • ESP32フラッシュ診断方法(esptool flash_idの使い方)

    • GPIO12とフラッシュ電圧の関係

    • Flash Mode(QIO vs DIO)の選択基準

  3. CLAUDE.md: AI Agent向けガイド

    • ESP32書き込みエラーのチェックリスト追加

    • esptool診断コマンドの推奨

今後の予防策#

ファームウェア書き込み手順(チェックリスト):

  • OSECHIの電源スイッチをONにする

  • USB-Cケーブルで接続(データ転送対応ケーブル)

  • Arduino IDEのボード設定を確認

    • Flash Size: 8MB (64Mb)

    • Flash Mode: DIO

    • Upload Speed: 115200

  • 書き込み実行

  • シリアルモニターでデータ受信確認


参考情報#

esptoolコマンド例#

# 仮想環境にesptoolをインストール
$ uv venv /tmp/test-esp32/
$ source /tmp/test-esp32/bin/activate.fish
(test-esp32) $ uv pip install esptool


# フラッシュ情報取得
(test-esp32) $ uv run python3 -m esptool --port /dev/cu.usbserial-110 --baud 115200 flash-id

# チップ情報取得
(test-esp32) $ uv run python3 -m esptool --port /dev/cu.usbserial-110 --baud 115200 chip-id

# efuse確認
(test-esp32) uv run python3 -m esptool --port /dev/cu.usbserial-110 --baud 115200 summary

haniwers CLIによるポート管理#

# ポート一覧表示
haniwers-v1 port list

# ポート接続テスト(5秒タイムアウト)
haniwers-v1 port test /dev/cu.usbserial-110

# ESP32診断(esptool統合)
haniwers-v1 port diagnose /dev/cu.usbserial-110

# Flash情報のみ表示
haniwers-v1 port diagnose /dev/cu.usbserial-110 --flash-id

# Chip情報のみ表示
haniwers-v1 port diagnose /dev/cu.usbserial-110 --chip-id

新機能: port diagnoseコマンドがesptoolを直接ラップし、フラッシュ診断を簡単に実行できるようになった。異常値(ff/ffff, 1.8V)を自動検出し、対処法を提案する。

関連ドキュメント#

  • ESP32 Technical Reference Manual: GPIO12によるフラッシュ電圧選択

  • esptool documentation: フラッシュ診断コマンド

  • Arduino ESP32 documentation: ボード設定とFlash Mode