先日、UNO R4 WiFi のファームウェア更新をしたところ、Arduino IDE と通信ができなくなり、思わず「自治体の小型家電回収ボックス行きか !?」と青くなりましたが、気を取り直し、色々と調べたことを共有したいと思います。

はじめに

Arduino ボードの WiFi ファームウェアのアップデートに関するドキュメントは、以下の3つがありますが、UNO R4 WiFi 向けは後の2つです。

  1. Updating Firmware version and Uploading Certificates (最終更新:2024/01/17)
  2. UNO R4 WiFi Custom Firmware Upload to ESP32 (Advanced) (最終更新:2023/11/14)
  3. Update the connectivity module firmware on UNO R4 WiFi (最終更新:2024/04/11)

本項では最新の「3.」を元に、以下の項目について調査結果を報告します。

目次

WiFi ファームウェアバージョンの確認方法

次のコードで確認することができます。

#include <WiFiS3.h>

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  while (!Serial);
  delay(1000); // UNO R4 WiFi は、Serial 初期化完了まで少なくとも 600 ms 必要

  Serial.println("Latest: " + String(WIFI_FIRMWARE_LATEST_VERSION));
  Serial.println("Yours : " + String(WiFi.firmwareVersion()));
}

void loop() {
}

本稿執筆時点の Arduino IDE バージョンは 2.3.2 では、次のように表示されるハズです。ちなみに 0.4.1 は 2024年2月16日の更新 です。

Latest: 0.4.1
Yours : 0.4.1

失敗しない WiFi ファームウェアの更新方法

Update the connectivity module firmware on UNO R4 WiFi には、ファームウェアの更新方法として以下の4つが挙げられています。

  • Arduino IDE の Firmware Updater による更新
  • Arduino Cloud から OTA(Over The Air)による更新
  • アップデート用スクリプトによる更新
  • espflash による更新

既に Arduino Cloud を利用していれば最新版に更新されているハズなので、ここでは最もベーシックな Firmware Updater による更新を、注意事項と共に解説します。

Firmware Updater

「なんだ、実行するだけだろ」と思ったせっかちなアナタ、チョット待ってください。UNO R4 WiFi には他のボードには無い事情があり、ちゃんと以下のステップに従わないと、僕のように慌てふためくことになります。

1. BareMinimum スケッチをアップロードする

IDE のメニューから「ファイルスケッチ例01.BasicsBareMinimum」を開き、コンパイルした後、書き込みます。

BareMinimum
BareMinimum
BareMinimum
コンパイルと書き込み

新規スケッチを開いても良いでしょう。とにかく何もしない空のスケッチが必要です。

void setup() {
  // put your setup code here, to run once:
}

void loop() {
  // put your main code here, to run repeatedly:
}

2. IDE とボード間の USB 接続を完全に断ち切る

「出力」を閉じ、[未接続] を確認
「出力」を閉じ、[未接続] を確認

一旦ボードから USB ケーブルを完全に抜き、電源を OFF した後、IDE も終了させます。再び IDE を開き、シリアルモニタが閉じていること確認しましす。また複数の IDE が立ち上がっている場合も1つだけ残して他は全て閉じます。

さらに最下端のステータスバーで「出力」コンソールを閉じ、ステータスが [未接続] となっていることを確認します。

3. Firmware Updater を実行する

IDE のメニュから「ツールFirmware Updater」を選択します。続いて USB ケーブルを挿し電源を入れると「ボードを選択」が選べるようになります。UNO R4 WiFi を選択したら アップデートを確認 を押し、ファームウェアのバージョンを選択します。この時、ダウングレードも可能です。

Firmware Updater を起動
Firmware Updater を起動
ボードを選択
ボードを選択
ファームウェアのバージョンを選択
ファームウェアのバージョンを選択

4. インストールを実行

インストール を開始すると、約1分弱で完了します。

運悪く(=ボードと IDE 間の USB 接続を完全に断ち切れなかった)インストールに失敗したら、次の 更新に失敗した時のリカバリ方法 からの再インストールが必要です。

インストール開始
インストール開始
インストール成功
インストール成功
インストール失敗
インストール失敗

5. USB ケーブルを差し直す

インストール後は「ESP ダウンロードモード」という、IDE と RA4M1 が USB 接続できないモードのままなので、USB ケーブルを抜き、再び差し込んで電源を入れ直す必要があります。

またインストール失敗時は、何をやっても IDE と RA4M1 は繋がらない状態になります。リセットボタンのダブルクリックも効かず、LED の点滅を繰り返すだけの状態 に陥ります。この場合も念のため USB ケーブルの抜き差しはしておきましょう。

No device found on cu.usbmodem... Failed uploading: uploading error: exit status 1
No device found on cu.usbmodem... Failed uploading: uploading error: exit status 1

更新に失敗した時のリカバリ方法

Update the connectivity module firmware on UNO R4 WiFi には アップデート用スクリプトespflash の直接実行の2通りが示されています。前者が失敗した時の最後の砦として後者が紹介されている ので、ここでは後者でリカバリを試みることにします。

espflash の直接実行

1. PC の下準備

  • IDE が立ち上がっていると更新に失敗する ので、終了させておきます。
  • espflash の起動時に USB デバイス名の選択を間違えないよう、できるだけ PC から USB デバイスを抜いておきます。
  • GitHub から OS 毎の 最新版アップデート用スクリプト をダウンロード&解凍します。
ダウンロード&解凍されたアップデート用スクリプト(MacOS の場合)

2. ESP ダウンロードモードの設定

次の写真にある通り、ESP ヘッダ端子の4番ピン(ESP Download)と6番ピン(GND)を、ジャンパーピンメス−メスのジャンパーワイヤ でショートさせます。

ESP ヘッダピンのショート

3. ボードと PC の接続

UNO R4 WiFi を PC と USB ケーブルで接続し、ボードに電源を供給します。

4. ターミナル(またはシェル)の起動

解凍したアップデート用スクリプトのフォルダで、ターミナルソフト(またはシェル)を起動します。

5. espflash の起動

ターミナル(またはシェル)から次のコマンドで espflash を起動します。

  • Windows
bin\espflash write-bin -b 115200 0x0 (Get-Item .\firmware\UNOR4-WIFI-S3-*.bin).FullName
  • MacOS / Linux
./bin/espflash write-bin -b 115200 0x0 firmware/UNOR4-WIFI-S3-*.bin

おそらく Windows、MacOS とも下のような警告が出るでしょう。

セキュリティ警告(Windows)
セキュリティ警告(Windows)
セキュリティ警告(MacOS)
セキュリティ警告(MacOS)

Windows の場合は「詳細情報」を開き「実行」を押します。MacOS の場合は、次のコマンドを実行し、再び espflash を起動します。

chmod a+x update.command && sudo xattr -d com.apple.quarantine bin/espflash && sudo xattr -d com.apple.quarantine bin/unor4wifi-reboot-macos

6. USB ドライバの選択

espflash からは、下のようなメッセージと共に USB ドライバを選択するよう促されるので、矢印キーで「❯」を上下させ、正しいドライバ名(/dev/cu.usbmodem...)を選択します。

[2024-06-25T09:18:07Z INFO ] 🚀 A new version of espflash is available: v3.1.0
[2024-06-25T09:18:07Z INFO ] Detected 2 serial ports
[2024-06-25T09:18:07Z INFO ] Ports which match a known common dev board are highlighted
[2024-06-25T09:18:07Z INFO ] Please select a port
❯ /dev/cu.usbmodemDC5475EAF4182 - UNO WiFi R4 CMSIS_DAP
  /dev/tty.usbmodemDC5475EAF4182 - UNO WiFi R4 CMSIS_DAP

その後、書き込みが始まり、次のようになれば終了です。

[2024-06-25T08:38:17Z INFO ] Serial port: '/dev/cu.usbmodem14201'
[2024-06-25T08:38:17Z INFO ] Connecting...
[2024-06-25T08:38:17Z INFO ] Using flash stub
Chip type:         esp32s3 (revision v0.2)
Crystal frequency: 40MHz
Flash size:        8MB
Features:          WiFi, BLE
MAC address:       xx:xx:xx:xx:xx:xx
[00:00:15] [========================================]     877/877     0x0

また以下のようなエラーが出ることがあります。 IDE が立ち上がっていないか、または正しい USB デバイス名を確認し、再度 espflash を起動します。

Error: espflash::timeout

  × Error while connecting to device
  ╰─▶ Timeout while running FlashDeflateData command

UNO R4 WiFi が抱える事情

今回、失敗する理由と確実に成功させる手順を見出すにために下記を読み漁った結果、RA4M1 と ESP32-S3 が互いに影響を及ぼし合う関係が見えてきました。本記事には僕の「推測」も入っていますが、単なる「憶測」ではなく、これらに書かれた記述を読み解いてみた結果です。

読み間違えがあれば、ご指摘いただければと思います

RA4M1 が ESP32-S3 に及ぼす影響

まずは UNO R4 WiFi の回路図による事実確認です。次の図は、NLASB3157 というアナログスイッチ IC 周りの回路図です。USB の作動信号ライン(USB_D_PUSB_D_N)が、RA4M1 の P408 または SJ1(基板裏面の RAM4M1 USB 半田ブリッジジャンパ)によって切り替え可能になっている事が分かります。

NLASB3157 アナログスイッチによる USB の切り替え
NLASB3157 アナログスイッチによる USB の切り替え

Firmware Updater 実行時、ファームウェアデータを IDE から ESP32-S3 に流しているときは P408LOW のハズです。しかし、RA4M1 も USB に接続しようと P408HIGH に切り替えるような事があると、送出中のファームウェアデータが途切れることになります。

RA4M1 の USB 通信周りのソースコードを読み切れていないので推測になりますが、これが「2. IDE とボード間の USB 接続を完全に断ち切る」という手順が必要な理由だと思います。

この問題は、UNO R4 WiFi が日本に出回る(2023年10月)以前から IDE 開発の公式 GitHub で issue に上がっていましたがアプリケーションによる USB 通信の問題 もあり、IDE だけではどうにもならない問題と思われます。

ESP32-S3 が RA4M1 に及ぼす影響

一方、ESP32-S3 と RA4M1 との間には TXB0108DQSR という UART のレベル変換を行う IC があり、ESP32-S3 側から RA4M1 をリセットすることが可能になっています。恐らく RA4M1 にプログラムを書き込む際、「IDEアナログスイッチ ICESP32-S3 (USB)レベル変換 ICRA4M1 (UART)」という経路を辿り1、その後リセットをかけるための仕掛けでしょう。

TXB0108DQSR による UART のレベル変換
TXB0108DQSR による UART のレベル変換

5. USB ケーブルを差し直す」で「インストール失敗時は、何をやっても IDE と RA4M1 は繋がらない状態になります。リセットボタンのダブルクリックも効かず、LED の点滅を繰り返すだけの状態に陥ります」と書きましたが、これは ESP-32 が RA4M1 のリセットを繰り返しているために起きる事象ではないかと推測しています。

Serial.print が遅いのはなぜ?

UNO R4 WiFi の Serial.print()Serial.println() は Minima に比べ、とてつもなく遅い事が観測できます。例えば、ルイスキャロルの詩 の一節を Serial.print するだけの次のコードを実行してみます。

/*
  Minima
    ** Serial Speed Test **
    !Serial = 1
    Twas brillig and the slithy toves did gyre and gimble in the wabe...
    Total Time : 207

  WiFi
    ** Serial Speed Test **
    !Serial = 0
    Twas brillig and the slithy toves did gyre and gimble in the wabe...
    Total Time : 69792
*/
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  bool t = !Serial;
  while (!Serial);

#ifdef  ARDUINO_UNOR4_WIFI
  delay(1000); // It requires at least 600 ms to complete Serial initialization.
#endif

  Serial.println("\n** Serial Speed Test **");
  Serial.println("!Serial = " + String(t));

  uint32_t start = micros();
  Serial.print("Twas brillig and the slithy toves did gyre and gimble in the wabe.\n");
  uint32_t finish = micros();

  Serial.println("Total Time : " + String(finish - start));
}

void loop() {}

結果は次の通りです(単位はμs)。

Minima [μs] WiFi [μs]
207 69792

上記コードは Minima の SerialSerial1 の速度違いが議論されているスレッド The R4 Serial Problem からの引用です。同スレッドに示された計測結果は次の通りで、Minima の Serial1.print() は WiFi の Serial.print() とほぼ同じ速度 を示しています。

Serial [μs] Serial1 [μs]
254 68782

この結果が意味するのは、どちらも UART を使用しているということです。「なるほど、UNO R4 WiFi の Serial は ESP32-S3 を経由しているのね」とは簡単に納得できず、当然「なぜ、P408HIGH にして直接 USB と繋がないの?」という疑問が湧いてきます。

この辺りの仕組みはまだ解明できていませんが、UNO R4 WiFi と ESP32-S3 が抱える事情の1つとして挙げておきたいと思います。

2024年7月2日 追記 タイムリーなことに、フォーラムに More on the Serial topic という UNO R4 WiFi についてのスレッドが立ったので、Serial.print() が遅い理由を聞きました。やはりレベル変換 IC を介して ESP32-S3 と通信する UART クラスが原因とのこと。もう一方のアナログスイッチ経由でつながる USB クラスについては、超長いスレッドを紹介されました。何か新しい発見があれば別途報告しますネ。

おわりに

IDE メニューの中で1つだけ英語のままの Firmware Updater が気になり、実行しちゃったところから今回の調査となりました。未確認ですが、USB を介さずネットワーク経由でファームウェアを送れる Arduino Cloud であれば安全にアップデートできると思います。

それにしても「アップデートに失敗しました。もう一度試してください」のメッセージは、初心者には不親切過ぎます。何度試しても結果は変わらないのですから。実行前に注意書きとか警告が欲しいですよね :man_cook: