Arduino-cli を WSL で使う

Windows の Arduino IDE だと ESP32 S3 ボードのビルドが遅い。
Linux環境だと速いとのことで Arduino-cli が WSL でも使えるようなのでやってみる。
usbipd というツールを使ってWSL側からUSBデバイスにアクセスできるようにしてボードにスケッチを書き込む。

環境について

以下環境で動作確認した。

  • Windows 10 Home 22H2
  • WSL環境: Ubuntu 24.04
  • usbipd-win: version 4.4.0
  • Arduino-cli: version 1.1.1

WSL環境での uname -a の値は👇️のとおり
Linux <MACHINE-NAME> 5.15.167.4-microsoft-standard-WSL2 #1 SMP Tue Nov 5 00:21:55 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux

事前準備その1 WSL側とUSBデバイスをつなぐ

※最後の lsusb コマンド以外は powershell側で実行する

  • usbipd-win のインストール
    👇️の How to install に従って winget なり msi インストーラなりを使ってインストールする。説明省略。
    https://github.com/dorssel/usbipd-win

  • バインド(要管理者権限)
    管理者権限が必要。新たに powershell のターミナルを起動する。
    usbipd にパスが通ってない...... Windowsでもパス情報引き継いでアドミンになる方法ってあるのかな?
    usbipd list で対象のBUSIDを確認し usbipd bind --busid <BUSID> でバインドする

  ❯ & 'C:\Program Files\usbipd-win\usbipd.exe' list
  Connected:
  BUSID  VID:PID    DEVICE                                                        STATE
  ...
  (途中省略)
  ...
  5-1    303a:1001  USB シリアル デバイス (COM12), USB JTAG/serial debug unit     Not shared 👈️つなぎたいやつ

  Persisted:
  GUID                                  DEVICE

  ❯ & 'C:\Program Files\usbipd-win\usbipd.exe' bind --busid 5-1  # 成功の場合何も応答がない
  ❯
  • アタッチ

※ここは管理者権限不要。

  ❯ usbipd attach --wsl --busid 5-1
  usbipd: info: Using WSL distribution 'Ubuntu-24.04' to attach; the device will be available in all WSL 2 distributions.
  usbipd: info: Detected networking mode 'nat'.
  usbipd: info: Using IP address 172.18.64.1 to reach the host.

これでWSL側で下記コマンドにて該当のUSBポートが見えていれば成功

  $ lsusb
  Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
  Bus 001 Device 002: ID 303a:1001 Espressif USB JTAG/serial debug unit
  Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub

事前準備その2 Arduino-cli 周りの環境構築とボード情報の調査

※WSL側で実行する。

  • シリアルポートがらみのデバイスファイル /dev/ttyACM# が属する dialout グループにユーザを追加
$ sudo adduser $USER dialout
  • 👇️下記に従ってArduino-cli をインストールする。今回は Linux 版の Homebrew を使ってインストールしてみた。
    https://arduino.github.io/arduino-cli/1.1/installation/

  • arduino-cli config init を実行して空の設定ファイルを作成する。
    ~/.arduino15/arduino-cli.yaml が作成される。

  • エディタを使って arduino-cli.yaml に追加のボード情報を入力する。
    今回は ESP32 と RPi Pico の情報を入力した。

board_manager:
    additional_urls: [
        # for ESP32
        https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json,
        # for RPi Pico
        https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json,
    ]
  • ボード情報を更新した後、core search コマンドで Core ID情報がわかる。
    この Core ID を使ってボード情報を取得する。 また board list コマンドを使って接続しているボードの FQBN を確認する(Core IDも確認できる)
    FQBN はボードを一意に特定する識別子みたいなもの。スケッチのビルドの際に必要となる。 ただ FQBN が 「AirM2M_CORE_ESP32C3」 となっている。ESP32S3 のはずなのに......
    と、ここでこのボード (ESP32-S3 Supermini) が Lolin S3 のボード情報を使うということを思い出した(こちら参照)。
    なので board listall コマンド結果を grep してみると、それらしいものを発見。
# ボード情報の更新
$ arduino-cli core update-index

# esp32ボードの Core ID を確認
$ arduino-cli core search esp32
ID            Version          Name
arduino:esp32 2.0.18-arduino.5 Arduino ESP32 Boards     # こっちは元からあると思われるボード情報 
esp32:esp32   3.1.3            esp32                                        # こっちがほしいやつ

# 接続しているボードの FQBN を確認
$ arduino-cli board list
Port         Protocol Type              Board Name          FQBN                            Core
/dev/ttyACM0 serial   Serial Port (USB) AirM2M_CORE_ESP32C3 esp32:esp32:AirM2M_CORE_ESP32C3 esp32:esp32

# そういえばこのボードは Lolin S3 の情報を使うんだったと思い検索してみたら、あった!
$ arduino-cli board listall esp32 | grep lolin
LOLIN C3 Mini                                      esp32:esp32:lolin_c3_mini
LOLIN C3 Pico                                      esp32:esp32:lolin_c3_pico
LOLIN S2 Mini                                      esp32:esp32:lolin_s2_mini
LOLIN S2 PICO                                      esp32:esp32:lolin_s2_pico
LOLIN S3                                           esp32:esp32:lolin_s3  # コレ!
LOLIN S3 Mini                                      esp32:esp32:lolin_s3_mini
LOLIN S3 Mini Pro                                  esp32:esp32:lolin_s3_mini_pro
LOLIN S3 Pro                                       esp32:esp32:lolin_s3_pro
WEMOS LOLIN32                                      esp32:esp32:lolin32
WEMOS LOLIN32 Lite                                 esp32:esp32:lolin32-lite
  • 上記で得られたCore ID情報を使ってボード情報をダウンロード、インストールする。ちょっと待つ。
$ arduino-cli core install esp32:esp32
Downloading packages...
esp32:esp32-arduino-libs@idf-release_v5.3-489d7a2b-v1 downloaded
......
(snip)
......
esp32:esp32@3.1.3 downloaded
Installing esp32:esp32-arduino-libs@idf-release_v5.3-489d7a2b-v1...
Configuring tool....
esp32:esp32-arduino-libs@idf-release_v5.3-489d7a2b-v1 installed
......
(snip)
......
Installing platform esp32:esp32@3.1.3...
Configuring platform....
Platform esp32:esp32@3.1.3 installed

スケッチのビルドとボードへの書込み

  • いつものきまりでスケッチは同名のディレクトリ配下においてある必要がある。
    そうしないと Can't open sketch: main file missing from sketch: /home/<user_name>/<user_name>.ino と出てエラーとなる。
  • FQBN は 上記で確認したもの、今回であれば Lolin S3 の esp32:esp32:lolin_s3 を指定する
  • 書き込んだあとボードをリセットする際にアタッチしていたUSBポートがデタッチされてしまう模様。
    書き込むたびに毎回アタッチしなおさないといけないのか。
    いちおう usbipd.exe attach --wsl --busid 5-1 のようにすればWSL側でもアタッチは実行できるのでバッチ化すればよいかも。
# ~/test/test.ino を作成したうえでコンパイル
~$ arduino-cli compile --fqbn esp32:esp32:lolin_s3 test
Sketch uses 290716 bytes (13%) of program storage space. Maximum is 2097152 bytes.
Global variables use 20188 bytes (6%) of dynamic memory, leaving 307492 bytes for local variables. Maximum is 327680 bytes.

Used platform Version Path
esp32:esp32   3.1.3   /home/hoge/.arduino15/packages/esp32/hardware/esp32/3.1.3

# USBポートを指定して書込む
~$ arduino-cli upload -p /dev/ttyACM0 --fqbn esp32:esp32:lolin_s3 test
esptool.py v4.8.1
Serial port /dev/ttyACM0
Connecting....
Chip is ESP32-S3 (QFN56) (revision v0.2)
Features: WiFi, BLE, Embedded Flash 4MB (XMC), Embedded PSRAM 2MB (AP_3v3)
Crystal is 40MHz
MAC: xx:xx:xx:xx:xx:xx
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 921600
Changed.
Configuring flash size...
Flash will be erased from 0x00000000 to 0x00004fff...
Flash will be erased from 0x00008000 to 0x00008fff...
Flash will be erased from 0x0000e000 to 0x0000ffff...
Flash will be erased from 0x00010000 to 0x00057fff...
Compressed 20160 bytes to 12987...
Writing at 0x00000000... (100 %)
Wrote 20160 bytes (12987 compressed) at 0x00000000 in 0.3 seconds (effective 508.3 kbit/s)...
Hash of data verified.
Compressed 3072 bytes to 143...
Writing at 0x00008000... (100 %)
Wrote 3072 bytes (143 compressed) at 0x00008000 in 0.0 seconds (effective 542.3 kbit/s)...
Hash of data verified.
Compressed 8192 bytes to 47...
Writing at 0x0000e000... (100 %)
Wrote 8192 bytes (47 compressed) at 0x0000e000 in 0.1 seconds (effective 711.7 kbit/s)...
Hash of data verified.
Compressed 290832 bytes to 154288...
Writing at 0x00010000... (10 %)
Writing at 0x0001ba0e... (20 %)
Writing at 0x000276ae... (30 %)
Writing at 0x0002d07c... (40 %)
Writing at 0x00033136... (50 %)
Writing at 0x000386c0... (60 %)
Writing at 0x0003df6e... (70 %)
Writing at 0x00043a93... (80 %)
Writing at 0x0004cde8... (90 %)
Writing at 0x000545c6... (100 %)
Wrote 290832 bytes (154288 compressed) at 0x00010000 in 2.7 seconds (effective 862.3 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting with RTC WDT...
New upload port: /dev/ttyACM0 (serial)

# ボードがリセットされ USB接続がデタッチされてしまうので再度アタッチする
# まずリスト表示 from WSL  
~$ usbipd.exe list
Connected:
BUSID  VID:PID    DEVICE                                                        STATE
5-1    303a:1001  USB シリアル デバイス (COM12), USB JTAG/serial debug unit     Shared

Persisted:
GUID                                  DEVICE

# アタッチ from WSL
~$ usbipd.exe attach --wsl --busid 5-1
usbipd: info: Using WSL distribution 'Ubuntu-24.04' to attach; the device will be available in all WSL 2 distributions.
usbipd: info: Detected networking mode 'nat'.
usbipd: info: Using IP address 172.18.64.1 to reach the host

ライブラリの導入

lib search で検索し、 lib install でインストール。

# HPDL1414 のライブラリを探してインストールする例
# 検索
$ arduino-cli lib search HPDL1414
Downloading index: library_index.tar.bz2 downloaded
Name: "HPDL1414"
  Author: Marek Ledworowski (marecl)
  Maintainer: Marek Ledworowski (marecl)
  Sentence: HPDL1414 Display Driver
  Paragraph: Simple library for HPDL1414 14-segment displays. Now with scrolling!
  Website: https://github.com/marecl/HPDL1414
  Category: Display
  Architecture: *
  Types: Contributed
  Versions: [1.0.0, 1.0.1, 1.1.0, 1.2.0, 2.0.0, 2.0.1, 3.0.0, 3.1.0, 3.2.0, 3.2.1]
  Provides includes: HPDL1414.h
Name: "HPDL1414-74HC595"
  Author: SQFMI
  Maintainer: SQFMI
  Sentence: An Arduino library for driving HPDL-1414 displays using shift registers
  Paragraph: An Arduino library for driving HPDL-1414 displays using shift registers, works with Open Source Hardware found here https://github.com/sqfmi/HPDL-1414-20x2-ESP32
  Website: https://github.com/sqfmi/HPDL1414-74HC595-Arduino
  Category: Other
  Architecture:
  Types: Contributed
  Versions: [1.0.0]

# インストール
~$ arduino-cli lib install HPDL1414
Downloading HPDL1414@3.2.1...
HPDL1414@3.2.1 downloaded
Installing HPDL1414@3.2.1...
Installed HPDL1414@3.2.1

参考

👇️ Arduino-cli 公式サイト
arduino.github.io

👇️ WSLでホスト側のUSBと接続する方法について learn.microsoft.com

👇️ Arduino-cli の使い方について。サイトがシンプルで綺麗で素敵なサイト。 blog.aoirint.com