秋月のESP32モジュール (ESP32-WROOM-32E) でWLEDを動かす

搭載スペースの都合で、ピンヘッダが生えていないDevKitCのようなESP32モジュールが欲しくなりました。

IOは簡単に使いたい、けどESP32モジュール単体は使い辛いということで、ピンヘッダ後付けの秋月のモジュールを使うことにしました。

秋月ESP32モジュール

akizukidenshi.com

よくあるDevKitCのようにUSB直結の端子は付いてないので、USB-UART変換器を噛ませます。これも秋月で購入。

akizukidenshi.com

結線

ESP32モジュールの下部にシリアル変換器用の端子がまとまっているのでそのまま利用。互いに繋ぐだけです。

書き込み

今回はIDEは使わず、WLEDをブラウザから直接書き込みました。

Welcome to WLED - WLED Project

ブラウザからマイコン開発というと、2010年頃のmbedのように外部ストレージとして認識されているマイコンにブラウザからダウンロードしたバイナリを保存するようなものがありましたが、その後ブラウザでネイティブでシリアル通信の仕組みが整ってブラウザ上のIDEが出てきていたなあと思い返します。

今回のWLEDもブラウザからシリアル通信を叩いて書き込みます。IDEも解さず、見た目は普通のwebページからマイコンに接続して書き込みができるというのは仕組みが分かっていても面白い感じです。

最初そのまま繋いだだけですが反応せず、(オフィシャル情報を探しもせず) 以下の記事を参考にさせてもらい書き込むことができました。

k-kuro.hatenadiary.jp

実際には以下の手順を行い、ソフト実行まで行きました。

(1) BOOTとENを押しながら電源投入

(2) ENを離す

(3) 書き込みが始まったらBOOTも離す

(4) 書き込み完了後にENを一度押す

一度書き込み完了後は、電源投入で自動的にソフトが走り始めますのでボタン操作はもう不要です。

まとめ

以上のやり方で秋月ESP32モジュールにWLEDを書き込み、LEDを点灯させることができました。

WLEDは外部から連携させるためにsACNやArt-Netなども対応し、非常に性能も自由度も高いソフトなので、今後も活用のシーンは多そうです。

2台のマイコンのシリアル通信で文字化けする (GNDループ)

M5Stamp S3Aを2台使ってシリアル通信を試したところ、通信内容が化けるという事象に遭遇しました。

基本的なことですが、これまで何となく上手くいっていたり、もしかしたらエラー起きていたけど気が付かなかったということで、今更ながらの学習になったのでメモです。

発生事象

Stamp S3AのTXピンとRXピンを繋ぎ、RXピン側のS3AからPCへ受信内容をUSB-UARTで出力しています。

TXピン側は常に"UART!\n"を送信しています。

ボーレートを遅くしてみたりしましたが、解消せずでした。

この時のPC側の受信ログとしては、

12:37:49.090 -> UP*Uj
12:37:49.156 -> UP*Uj
12:37:49.189 -> UP*Uj
12:37:49.254 -> UP*Uj
12:37:49.286 -> UP*Uj

といったものや、

12:45:46.549 -> IQ�
12:45:46.582 -> IQ�
12:45:46.646 -> IQ�
12:45:46.680 -> UIQ�
12:45:46.746 -> UIQ�
12:45:46.779 -> UIQ�
12:45:46.844 -> UP*Uj
12:45:46.878 -> UART!
12:45:46.944 -> UP*Uj
12:45:46.976 -> IQ�

といったものが出てきました。

ChatGPTに聞いてる

先日4oから5に進化したということで、試しに聞いてみました。

以下はChatGPT 5に、はてなブログ用にマークダウン記法で出力してもらった内容です。

ESP32-S3A同士をUART接続したらGND接続で通信が不安定になる原因と対策

原因:グラウンドループ

  • 2台のESP32-S3AをUSBでPCに接続すると、それぞれのGNDはPC側ですでに共有されています。

  • この状態でS3A同士のGNDもジャンパで直結すると、以下のような閉ループ(グラウンドループ)が発生します。

  • ループに スイッチング電源のリップルやPC間の電位差 が流れ、UART信号の基準電位が揺れて通信が不安定になります。

簡単な確認方法

  1. GND同士をつないだ状態と外した状態で通信の安定性を比較。

  2. 2台のPC(またはポート)間でGND電位差をテスターで測定

    数十 mV〜数百 mVの直流差やACノイズが見える場合あり。

対策(優先順)

1. アイソレーション

  • UART間にデジタルアイソレータ(例: ADuM1201 / Si86xx)やRS-485等の差動+アイソレータを挟む。
  • またはUSBアイソレータを片側に入れて電気的に分離する。

2. 単一基準にそろえる(ループを作らない)

  • 2台を同じPC・同じUSBハブに挿す。
  • 一方のUSBのVBUS(5V)をカット、またはデータ専用USBケーブルで電源の回り込みを防ぐ。
  • GND接続は一点接地にし、USB経由とジャンパ経由の二重経路を作らない。
  • 同じPCの場合、UARTのGNDジャンパは省略可能(TX/RXのみクロス接続)。

3. 配線と保護

  • GNDジャンパを使う場合は短く太く
  • TX/RXには33〜100Ω程度の直列抵抗を入れてリンギングやグランドバウンスを軽減。
  • 長いUSBケーブルやセルフパワー/バスパワー混在を避ける。

4. プロトコル側の耐性

  • UARTボーレートを下げる(例: 115200 → 57600 / 38400)。
  • 必要に応じて物理層差動(RS-485)に変更。

まとめ

既にUSBで共有されているGNDに、もう1本のGND線を足すとグラウンドループが発生し、ノイズ電流がUART通信に悪影響を与えます。
解決策は以下のいずれかです。

マイコン間のGNDを外す

それなりに良さそうな回答が出たようです。

上記の2にある対策として、GNDを外したところ正常に受信できました。

13:00:41.638 -> UART!
13:00:41.671 -> UART!
13:00:41.737 -> UART!
13:00:41.772 -> UART!
13:00:41.838 -> UART!

マイコンのGND間には40mV程度の電位差があり、確かにChatGPTが言う電位差の範囲そのものでした。

以上よりGNDループが原因と判断しました。

GNDループという言葉は知っていたものの、こういったところで発生するということを再認識しました。

追加トライ

ちなみにここまでは片方のマイコンはPCへ、もう片方はUSB HUB経由の接続でした。

ここで、マイコン間のGNDは外し、同じUSB HUBで接続すると同様に文字化けが発生しました。

この時にGNDを繋いでも文字化けは解消されず、当初の接続である片方はPC直結、片方はUSB HUB経由の接続に戻すと安定しました。

これも別ルートでGNDループが発生しているのでしょうか...?ただ、同じUSB HUBに2台マイコンを繋いで通信させるのがNGとなると何か通常の使い勝手としても難ありでは、と思ってしましましたが、一旦そういうものと割り切っておきます。

(環境: MacBook AirとUGREEN製多機能ハブ)

M5Stamp S3A Solves GPIO3 Touch Sensor Value Stuck Issue Found in M5Stamp S3

This article is a summary of the content from the following Japanese article for international users. I hope this helps someone with the same problem.

For more details, please refer to the link below and use translation tool.

M5Stamp S3でのタッチセンサ特定ピン (GPIO3) 読み取りで出力値ロック / M5Stamp S3Aで解決

Summary

  • Using GPIO3 as a touch input on ESP32 M5Stamp S3 caused all touch values to get stuck.

  • After some testing, I found that GPIO3 is pulled up to 3.3V, which gives unexpected input to the touch sensor pins and causes issues with the whole touch sensor system.

  • When I tried the exact same sketch on M5Stamp S3A, it worked correctly without the issue because any touch input pins are not pulled up.

  • If GPIO3 is avoided, the S3 still works fine, but only 13 touch pins can be used instead of 14.

This is same situation as below.

using touch_pad_read_raw_data() with touch sensors on esp32s3 reads high, unchanging values (IDFGH-11130) #12300

Thanks.

解決M5Stamp S3でのタッチセンサの特定ピン (GPIO3) 読み取りで出力値固着 / M5Stamp S3Aで改善

M5Stamp S3で特定のピンのタッチセンサの読み取りができない問題に遭遇し、M5Stamp S3Aでは同じスケッチでも期待通り正しく動作するという挙動の違いがあったので残しておきます。

先に結論

M5Stamp S3のGPIO3が外部抵抗で3.3Vへ強制プルアップされており、これを読むと一緒に使おうとしている他のピン含めてタッチセンサ全体の挙動がおかしくなる挙動が発生。 (出力値が固定される)

GPIO3をタッチ入力として使わなければ回避可能です。ただし、タッチ入力がMAX 14 → 13本になります。

GPIO3はADC入力としても使えることになっていますが、回路的に3.3Vに繋がってしまっているのでADC使用時にも同様の問題が発生しそうです。

やろうとしていたこと

タッチセンサを多用する基板を作ったのでその読み取りをするマイコンを探しており、1ボードで14ピンと多くのタッチ入力があるM5Stamp S3を使うことにしました。

事前のプロトタイピングはせずに先に基板をM5Stamp S3用に作って発注しました。

基板製造の待ちの間にいざソフトを、と思いまずはM5Stamp S3単品でピン入力をそのままシリアル通信で流すスケッチを試しました。

スケッチ

サンプルのESP32 -> Touch -> TouchReadをベースに、複数ピン (Stamp S3から2.54mmピッチのピンが出ている入力) から100msごとに読み出してシリアル出力するというシンプルなものです。

void setup() {
  Serial.begin(115200);
  delay(1000);
  Serial.println("ESP32 Touch Test");
}

void loop() {
  uint32_t a1 = touchRead(1);
  uint32_t a2 = touchRead(3);
  uint32_t a3 = touchRead(5);
  uint32_t a4 = touchRead(7);
  uint32_t a5 = touchRead(9);

  Serial.printf("%lu, %lu, %lu, %lu, %lu\n", a1, a2, a3, a4, a5);

  delay(100);
}

起きたこと

ピン1, 3, 5, 7, 9の順にタッチ読み取り値を出力していますが、ずっと固定された値が出続けます。

ピンに触れても離しても値は変わらず無反応で、常にこの数字が出ます。

16:16:56.430 -> 20793, 380229, 3407098, 4117270, 3162315
16:16:56.529 -> 20793, 380229, 3407098, 4117270, 3162315
16:16:56.628 -> 20793, 380229, 3407098, 4117270, 3162315
16:16:56.726 -> 20793, 380229, 3407098, 4117270, 3162315
16:16:56.825 -> 20793, 380229, 3407098, 4117270, 3162315

一旦リセットして再起動しても、値は違えど挙動としては同様です。 よく見ると最初の1ピン目の値がちょっと違うだけで、それ以降は同じですね。何か怪しい。

16:18:55.192 -> 20807, 380229, 3407098, 4117270, 3162315
16:18:55.291 -> 20807, 380229, 3407098, 4117270, 3162315
16:18:55.388 -> 20807, 380229, 3407098, 4117270, 3162315
16:18:55.485 -> 20807, 380229, 3407098, 4117270, 3162315
16:18:55.583 -> 20807, 380229, 3407098, 4117270, 3162315
16:18:55.680 -> 20807, 380229, 3407098, 4117270, 3162315

読み込みを1ピンだけ (GPIO1) に限定すると問題なく読み取れます。

しかし、2ピン (GPIO1と3) にした途端に同様の値ロックが発生。 低レベルAPIのtouch_pad_read_raw_data()を使ったり、手動でタッチセンサの初期化なども入れてみたりしましたが変わらずでした。

調べる

ChatGPTに聞いてみるとESP32-S3で以下のような記事があり、近しい事象に見えます。ただこれらではM5Stamp S3ではなさそうです。

フォーラムではタッチセンサとピンの間に抵抗を追加したり、あるいはtouchSetCycles()でデフォルト値から変更すると良いかもという意見もありましたが、手元の環境では効果ありませんでした。

M5Stamp S3Aでトライ

基板GOしちゃったよ!と思いつつどうしようかなと考えていると、ちょうど先日なんとなくで注文していたM5Stamp S3Aがあったので、ダメ元でS3Aで試してみました。

M5Stamp S3とS3Aの違いはアンテナやスイッチ、LED駆動などの改善で、コア自体やその他は特に変わっているアナウンスは無いので期待はしていませんでした。

全く同じスケッチを書き込みます。Arduino IDE上ではM5StackもESP32もいずれのライブラリでもS3A用は無かったので、そのままM5Stamp S3用を使っています。

結果は、、

16:20:18.848 -> 20425, 23097, 22466, 22007, 22257
16:20:18.947 -> 20445, 23104, 22466, 22019, 22256
16:20:19.045 -> 20432, 23105, 22466, 22019, 22256
16:20:19.144 -> 20429, 23107, 22469, 22036, 22255
16:20:19.242 -> 20432, 23105, 22453, 22025, 22257

あれ?ちゃんと動いています。

指でピンを順番になぞると値が変わり、シリアルプロッタでもちゃんと取れていそうな反応が見れました。

不思議に思い、動いたスケッチを再度S3に書き込みますが値ロックは変わらずでした。

真因

さらに調べていくとこのフォーラムに辿り着き、原因判明しました。

using touch_pad_read_raw_data() with touch sensors on esp32s3 reads high, unchanging values (IDFGH-11130) #12300

自分と同じようにM5Stamp S3で複数ピンのタッチ読み取り値がロックされるというものです。

その中で、ボードのGPIO3が抵抗を通じて3.3Vラインに回路として繋がっていることが言及されていました。

M5Stackのドキュメントページで回路図を確認すると、確かに以下のようにS3ではプルアップされています。

そしてS3Aではそれが無いという回路の変化が確認できます。

想定外の3.3Vが入力されることでタッチモジュールが正しく動作せず、さらにそれが他のピンの読み取り結果にも影響するという挙動に繋がっているようです。

恐らくの推測ですが、上記複数のフォーラムでM5Stamp S3以外で挙がっていた値のロックも、パッドサイズや環境なのかで想定外なのか内部カウンタの上限値超え?の入力がタッチセンサモジュールに入り、一度それが発生してしまうと他ピン含めタッチ出力値の固定に繋がってしまうというものだったのではないでしょうか。

M5Stamp S3の場合はこのきっかけが外部抵抗・電源接続によるプルアップだった、という形と予想します。

S3Aではタッチセンサに使われるGPIO1〜14は何も繋がっていないので、同様の問題は発生しなさそうです。改善として変更されたのでしょうか。

S3でGPIO3周りのタッチテスト

1ピンのみの入力では正しく動作を確認していましたが、この時はGPIO1を使っていました。これをGPIO3だけの入力にしてみると出力値のロックが発生しました。

逆に、GPIO3を除いて複数ピン入力を試すと、ダメだと思っていたS3でもちゃんとタッチ入力ができました。

以上より、複数ピンの読み取りなどが原因ではなく、GPIO3に由来するものだと確認できました。

よく見ると、最初に複数ピンで値がロックされると載せていた↑のログですが、リセット前後でGPIO1だけ数字が変わり、GPIO3を読む前のGPIO1は正しく取れていた、と推測できますね。

まとめ

M5Stamp S3とS3AのGPIO3の回路の違いから、複数ピン読み取り時のタッチセンサの挙動の違いが発生することを確認しました。

S3ではGPIO3をタッチ入力に使わないことで回避可能ですが、フルで14ピンの入力を使いたい、どうしてもGPIO3のタッチ入力が必要、などの場合はM5Stamp S3Aを使う必要があるということが分かりました。

タッチ基板ではフルで14ピン入力を使うため、追加でS3Aを発注しました。これでちゃんと動きますように、、

本題じゃなけどハマったこと

touchRead()で値を読む際、ESP32ではuint16_tで値が返されますが、ESP32-S2/S3ではuint32_tになる点に気付かずおかしな値が出ることに悩みました。

ESPRESSIFのArduino APIガイドにちゃんと記載がありました。 [Arduino-ESP32 TOUCH API] (https://docs.espressif.com/projects/arduino-esp32/en/latest/api/touch.html#arduino-esp32-touch-api)

This function will return touch pad value as uint16_t (ESP32) or uint32_t (ESP32-S2/S3).

本題じゃないけどS3とS3Aモジュール写真

M5Stack Tab 5使い始め

先日までSeeed studio XIAOを使っていましたが、別で最新よく使うM5Stackでちょっと大きな画面が星色思っていたところ新製品のTab 5が出たので早速購入しました。

Arduino IDE設定

M5StackのボードとM5Unifiedライブラリを最新にアップデートしたくらいです。

困りごと

シリアルモニタで出てこない事象が起きました。 きっと設定周りの何かだろうと思い、初期設定から少し変えて以下にすると無事出て来ました。

あとはWi-Fi周りがまだ使えない、RTCもArduino環境からは使えないなどで手元の他のM5Stack向けのスケッチがそのまま動かないという困りごとは多々あります。

まだまだライブラリが対応しておらず、無限リセットに陥るサンプルスケッチもあったり、そもそもコンパイルエラーが出るものも多いですが、これからの環境の拡充に期待です。

ESP32 (XIAO ESP32 S3) でArduinoのシリアルモニタで文章が途切れる

これはXIAOがとかESP32がとか、という話ではなくマイコン全般においてになると思いますが、初歩的な失敗をしてしまったのでメモ。

ESP-NOWで受信した内容を送るシリアル通信で文章が途切れる

事象

先日のESP32 (XIAO ESP32 S3) でESP-NOWを使い、受信した内容をシリアル通信で送るスケッチを書いていたら、内容が途切れていることに気付きました。

"This is a test."を繰り返し受信して、それをシリアルモニタに送るようにしていたのですが、以下のように正しく表示される時もあればそうでない時もある、むしろそうでない時の方が多いという困り事です。

21:08:32.232 -> This is a test.
21:08:32.232 -> Ta test.
21:08:33.217 -> 
21:08:34.233 -> a test.
21:08:36.233 -> This is a te
21:08:36.233 -> Thiest.

文章を短くすると打率が上がりました。

ESP-NOW側で受信失敗しているのかシリアルモニタ側か分かりませんでしたが、スケッチ内部でメッセージを確認するとしっかり全文受信できていたので問題はシリアル通信周りにあると考えました。

原因

マイコンやる上での禁じ手?ですが、割り込み内で余計な処理 = シリアル送信をしてしまっていたということです。非常に単純。。

先日のスケッチでは受信後の割り込みでいろいろシリアルで送るようにしていましたが、これがまずかったです。

// 受信時に呼ばれる関数の中身
void ReceiverXIAOS3_Recive_Data_cb(const esp_now_recv_info *info, const uint8_t *incomingData, int len) {
  memcpy(&XIAOS3_RECEIVER_INFORATION, incomingData, sizeof(XIAOS3_RECEIVER_INFORATION));
  Serial.print("Bytes rev: ");
  Serial.println(len);
  Serial.print("Sender device: ");
  Serial.println(XIAOS3_RECEIVER_INFORATION.Receiver_device);
  Serial.print("Message: ");
  Serial.println(XIAOS3_RECEIVER_INFORATION.Receiver_Trag);
  Serial.println();
}

改善策としては、割り込みで呼び出される上記関数からシリアル通信は排除して、受信文のコピーだけするようにし、メインループ内でシリアル通信をするようにしました。

すると、全ての文章が問題無くシリアルモニタに表示されるようになりました。

細かいタイミングなどのデバッグまでしていませんが、割り込み内部でシリアル通信のような時間が掛かる処理をさせたのがまずかったというのは間違い無さそうです。

ちなみにデバッグの最中でボーレートを115200から9600とか250000とか変えてみましたが効果はありませんでした。

まとめ

サンプルコードでやってたので大丈夫だろうと思ってましたが思わぬところに軽い落とし穴がありました。

シリアル通信に限らず、割り込み内での処理の管理はちゃんとやらねばと改めて思った次第です。

ESP32 (XIAO ESP32 S3) でブート後に再起動を繰り返す症状

ESP32 (XIAO ESP32 S3) でESP-NOWでベースができたので、他のソースコードに統合したところXIAOが再起動を繰り返しスケッチが動かない事象が起きました。

※顛末は非常にシンプルというか、ただのポカミスでした。。

再起動を繰り返すXIAO

まずは結論として原因から

setup() 中に呼び出すべきESP-NOWの関数 SenderXIAOS3_MACAddress_Requir(); が1つ抜けていたというオチでした。

上記のサンプルをプロジェクトに統合する際に、文字だけ見て espnow_init(); がESP-NOWのセットアップ関連の先頭だろうという思い込みで、その上の関数の記載を抜かしてしまいました。

void setup() {
  // Basic
  Serial.begin(BAUD);
  while(!Serial);
  delay(1000);  // give me time to bring up serial monitor
  Serial.println("Started.");

  // ESP-NOW
  SenderXIAOS3_MACAddress_Requir();     // これが抜けてた!
  espnow_init();
  esp_now_register_send_cb(SenderXIAOS3_Send_Data_cb);
  Association_ReceiverXIAOS3_peer();
  esp_now_register_recv_cb(ReceiverXIAOS3_Recive_Data_cb);

  Serial.println("ESP NOW started.");
}

発生事象

上記のESP-NOWのサンプルを統合した一発目の実行時に発生。

先ほど書いたように、発生事象としてはマイコンが再起動を繰り返して正しく動作しないというものと、以後のArduino IDEからの書き込みもできない (XIAOに接続できない) というものでした。

シリアルで流れてくるログの一巡はこんな感じです。これを何度か繰り返した後に動作を停止するようです。

09:32:22.206 -> Backtrace: 0x4204e080:0x3fca9510 0x42002eeb:0x3fca9530 0x42002f24:0x3fca9550 0x4200781b:0x3fca9570 0x4037d902:0x3fca9590
09:32:22.336 -> 
09:32:22.336 -> 
09:32:22.336 -> 
09:32:22.336 -> 
09:32:22.336 -> ELF file SHA256: d2cdf293e
09:32:22.336 -> 
09:32:22.336 -> Rebooting...
09:32:22.336 -> ESP-ROM:esp32s3-20210327
09:32:22.336 -> Build:Mar 27 2021
09:32:22.336 -> rst:0xc (RTC_SW_CPU_RST),boot:0x8 (SPI_FAST_FLASH_BOOT)
09:32:22.336 -> Saved PC:0x4037a8e6
09:32:22.370 -> SPIWP:0xee
09:32:22.370 -> mode:DIO, clock div:1
09:32:22.370 -> load:0x3fce2820,len:0x1188
09:32:22.370 -> load:0x403c8700,len:0x4
09:32:22.370 -> load:0x403c8704,len:0xbf0
09:32:22.370 -> load:0x403cb700,len:0x30e4
09:32:22.370 -> entry 0x403c88ac
09:32:23.553 -> Started.Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.
09:32:23.553 -> 
09:32:23.553 -> Core  1 register dump:
09:32:23.553 -> PC      : 0x4204e083  PS      : 0x00060330  A0      : 0x82002eee  A1      : 0x3fca9510  
09:32:23.553 -> A2      : 0x3fc9d86c  A3      : 0x3fcef940  A4      : 0x3fc9d86c  A5      : 0x00000000  
09:32:23.553 -> A6      : 0x3fc9ab84  A7      : 0x3fc9ab64  A8      : 0x820061d8  A9      : 0x3fca94f0  
09:32:23.553 -> A10     : 0x00000002  A11     : 0x3c0a2935  A12     : 0x00000000  A13     : 0x00000064  
09:32:23.584 -> A14     : 0x00000000  A15     : 0x3fc9ab64  SAR     : 0x00000008  EXCCAUSE: 0x0000001c  
09:32:23.584 -> EXCVADDR: 0x0000004c  LBEG    : 0x40056fc5  LEND    : 0x40056fe7  LCOUNT  : 0xffffffff  
09:32:23.584 -> 
09:32:23.584 -> 

setup() 内で書いているシリアルのテキストが一部出てきて、他が出てこなかったりしているので、setup() 中に問題が起きていると推定しました。

ログ中に「Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.」というエラーがあり、コア1がパニックを起こしていることが分かります。

「Guru Meditation Error: Core 1 panic'ed (LoadProhibited).」エラー

検索してみると、領域外でメモリを確保しようとした、巨大なメモリを確保しようとした、システムが使用しているIOピンを使用しようとした、などいくつか出てきました。

3つ目のはちょっと置いといて、どうやらメモリ周りで発生するエラーのようです。

今回抜かしてしまった SenderXIAOS3_MACAddress_Requir(); はESP-NOWやWi-Fiの初期セットアップをするものです。

ここで宣言していないメモリ領域にアクセスしようとしてのエラー?なのか分かりませんが、いずれにせよ入れるべきものを入れていなかった凡ミスなのであまり深追いしても仕方ないところです。が、ESP-NOWが使えないだけでなく、マイコンそのものが再起動して使えなくなるというのはちょっと重症な結果ですね。

参考に以下が SenderXIAOS3_MACAddress_Requir(); です。

void SenderXIAOS3_MACAddress_Requir(){
    WiFi.mode(WIFI_STA);
    WiFi.setChannel(ESPNOW_WIFI_CHANNEL);
    XIAO mac[MAX_ESP_NOW_MAC_LEN];
    while(!WiFi.STA.started()){
      Serial.print(".");
      delay(100);
    }
      WiFi.macAddress(mac);
      Serial.println();
      Serial.printf("const uint8_t mac_self[6] = {0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x};", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
      Serial.println();
}

リブートを繰り返すXIAOの救い方

再起動プロセスが走っている間も、その後の動作停止中もArduino IDEからは接続できなくなり、書き込みができなくなりました。

ブートローダーモードへ切り替える必要があります。

XIAO公式ガイドに切り替え方の案内があります。→ BootLoader Mode

一度PCとのケーブルを外し、本体のUSBコネクタの右側の"B"表記のある小さいスイッチを押しながら再度PCへ接続することでブートローダーモードに入り、スケッチの実行はされずに書き込み待ちの状態になります。

まとめ

つまらないミスが原因でしたが、コアのパニックで再起動ループという事象の体験とその対処方法を知れたのは良い教訓になりました。

コピペでミスしないようにしよう。。