🙁

WSL(Ubuntu)にArduino IDEを導入する

に公開

WSLでもArduino IDEを使う

WSLこと「Windows Subsystem for Linux」は、Windows上でLinuxを使えるというものです。今回、既にWindowsArduino IDEを利用していた最中、真更なArduino IDEの環境が欲しくなることがありました。

そこで、WSL上のLinux(Ubuntu 22.04.5 LTS)にこれをインストールします。本記事は、その手順や露見した問題点をまとめるものです。なおWSLLinuxの導入手順などは、本記事の主旨から逸れるため扱いません。導入済みを前提としています。また、Windows11を使用しているため、Windows10他異なる環境では、本記事の手順の限りではない可能性があります。

手順

大筋はこちらの記事を参考にしました。

https://lang-ship.com/blog/work/windows-wsl-arduino-ide/

ただし、この記事冒頭にあるような「環境破壊」~「初期セットアップスクリプト」の手順は行っていません。

0. アップデート・アップグレード

念のため、アップデートを確認します。場合によっては時間が掛かります。

update・upgrade
~$ sudo apt update
~$ sudo apt full-upgrade

1. Arduino IDEをダウンロードする

本記事では、Arduinoというフォルダーを作ります。単に整理整頓のためです。

フォルダーの呼称

Windowsで普通folderと呼ぶ概念は、Linuxではなぜかdirectoryと表現する習俗があります。その上で、本記事では徹頭徹尾フォルダーと表現します。

フォルダーを作る
~$ mkdir Arduino    # フォルダーを作る
~$ cd Arduino/      # フォルダーに移動する
~/Arduino$          # 現在のフォルダー名に変わる

次にArduino IDEをダウンロードします。ただしWSLは基本的にCUI環境ですから、ブラウザーでダウンロードということはしません。wgetコマンドがこの行為に相当します。

とは言え、調べなければ何も分からないので、普通にブラウザーで公式サイトを確認します。ブラウザーなら(変なものでなければ)何でも可。

https://www.arduino.cc/en/software/

ダウンロードページ
ダウンロードページ(2025/05/14現在)

Linuxに向けたものは二つあります。手順を参考にしている記事ではZipファイルの方(Linux ZIP file 64 bits (X86-64))を選んでいたので、本記事ではこれに遵いました。

両者の違いはこの通りです。

  • .zip
    解凍する必要がある
    権限を変更する必要はない
  • .AppImage
    解凍する必要はない
    実行権限を与える必要がある
Arduino IDEダウンロード
~/Arduino$ wget https://downloads.arduino.cc/arduino-ide/arduino-ide_2.3.6_Linux_64bit.zip
︙
~/Arduino$ ls
arduino-ide_2.3.6_Linux_64bit.zip

lsコマンドで、arduino-ide_2.3.6_Linux_64bit.zipがダウンロードできている(手許に存在する)ことを確認しました。

AppImageの場合

Linux AppImage 64 bits (X86-64)の方も試しました。

ダウンロード

AppImageダウンロード
~/Arduino$ wget https://downloads.arduino.cc/arduino-ide/arduino-ide_2.3.6_Linux_64bit.AppImage
︙
~/Arduino$ ls
arduino-ide_2.3.6_Linux_64bit  arduino-ide_2.3.6_Linux_64bit.AppImage  arduino-ide_2.3.6_Linux_64bit.zip ⋯

このまま実行しようとすると、権限によって阻止されます。

Permission denied
~/Arduino$ ./arduino-ide_2.3.6_Linux_64bit.AppImage
-bash: ./arduino-ide_2.3.6_Linux_64bit.AppImage: Permission denied

実行権限を付える

これは、ファイルに関する権限の内、実行に関する権限が与えられていないためです。

  1. 権限確認
権限を確認する
~/Arduino$ ls -l arduino-ide_2.3.6_Linux_64bit.AppImage
-rw-r--r-- 1 ⋯ ⋯ 200980456 Apr  9 20:45 arduino-ide_2.3.6_Linux_64bit.AppImage

ls -lで、ファイルの権限を始め、基本的な情報を表示します。権限を表すのはこの部分です。

rw-r--r--
  1. 権限の種類と意味

これは次のように読解します。(基本の三つのみ記載)

表記 意味
r 読み取り(read)
w 書き込み(write)
x 実行(execute)
- 対応する権限無し

本来はrwxrwxrwxの順に並んでおり、-がある場合、その対応する箇所に該当する権限が無いことを示します。「r」が無ければ、ファイルの内容を見ることができません。「w」が無ければ、ファイルの内容を編集することができません。「x」が無ければ、ファイルを実行することができません

今回はxが無いため、実行時にPermission deniedとエラーになったのです。

  1. 権限の対象者

rwxが三つ並んでいるので、「三つの異なる対象者」についての権限をそれぞれ示します。

箇所 対象者
rwx------ ファイルの所有者(個人)
---rwx--- ファイルの所有グループ(複数人)
------rwx よその人全て
対象の確認
             ↓所有者
-rw-r--r-- 1 ⋯ ⋯ 200980456 Apr  9 20:45 arduino-ide_2.3.6_Linux_64bit.AppImage
                ↑所有グループ

今回は「自分がダウンロードしたファイル」ですから、「所有者は自分」になっているはずです。よって、今回注目するのは一つ目のrw-になります。
(何かの間違いで自分でない場合は、chownコマンドで所有者を変えるとよいでしょう)

権限を変更する際はchmodコマンドを使うことが一般的です。chmod u+xあるいはchmod 744で実行権限を与えます。しかしここでは、せっかくなので異なる方法を紹介します。

Nautilus

https://qiita.com/Ronstadt/items/6a473a1522617fca69b3

Windowsでいう所の「エクスプローラー」です。これをWSLにインストールしてみます。

https://learn.microsoft.com/ja-jp/windows/wsl/tutorials/gui-apps#install-nautilus

nautilusのインストール
~/Arduino$ sudo apt install nautilus

実行はやはりコマンドです。

nautilusの起動
~/Arduino$ nautilus

nautilus画面

arduino-ide_2.3.6_Linux_64bit.AppImageを「右」クリックします。エクスプローラー同様、メニューが出てきます。

右クリックメニュー
Propertiesを選ぶ

プロパティー
Permissionsを表示(一部加工済み)

チェックボックスに承認します。

実行許可

この結果、先のls -lの表示はこのように変化します。

実行権限付与
~/Arduino$ ls -l arduino-ide_2.3.6_Linux_64bit.AppImage
-rwxr-xr-x 1 ⋯ ⋯ 200980456 Apr  9 20:45 arduino-ide_2.3.6_Linux_64bit.AppImage

コマンドを使わずに所有者、所有グループ、その他全員に実行権限が与えられました。所有者だけに限定したい場合は、chmodコマンドを使ってください。

これで実行準備が整いました。AppImageは圧縮ファイルではありませんから、次に示す解凍の手順を踏む必要はありません。但し、不足機能の追加は必要です。

また、Arduino IDEの実行はコマンドで行いますが、Nautilusを導入した場合は、マウスクリックでも実行できるようになります。

2. Zip解凍

Zipファイルの解凍もコマンドで行います。ただ、今回の環境にはzipコマンド(圧縮)もunzipコマンド(解凍)もなかったため、せっかくなので両方導入しました。

zip・unzipインストール
~/Arduino$ sudo apt install zip unzip

解凍する術を得たので、解凍します。

~/Arduino$ unzip arduino-ide_2.3.6_Linux_64bit.zip
︙
~/Arduino$ ls
arduino-ide_2.3.6_Linux_64bit  arduino-ide_2.3.6_Linux_64bit.zip

解凍され、arduino-ide_2.3.6_Linux_64bitフォルダーが作られました。

3. 不足機能導入

参考元の記事にもある通り、不足するパッケージをインストールしなければ動きませんでした。

今回は、公式サイトの手順に倣います。

universe追加
~/Arduino$ sudo add-apt-repository universe
Adding component(s) 'universe' to all repositories.
Press [ENTER] to continue or Ctrl-c to cancel.      # エンターキーを押す
︙
~/Arduino$ sudo apt install libfuse2

しかし、これだけではまだ動きませんでした。

libnss3がない
~/Arduino$ cd arduino-ide_2.3.6_Linux_64bit/
~/Arduino/arduino-ide_2.3.6_Linux_64bit$ ./arduino-ide
./arduino-ide: error while loading shared libraries: libnss3.so: cannot open shared object file: No such file or directory

libnss3を直接指定してもよいそうですが、libnss3-devを指定しても動作しました。何が違うのかはよくわかりません。

libnss3追加
~/Arduino/arduino-ide_2.3.6_Linux_64bit$ sudo apt install libnss3
libnss3-dev追加
~/Arduino/arduino-ide_2.3.6_Linux_64bit$ sudo apt install libnss3-dev

最後に、どう考えても日本語を使いたいので、日本語フォントをインストールします。こちらを参考にしました。

https://www.linux.digibeatrix.com/customization-and-configuration/install-fonts-ubuntu/

今回は、なんとなくIPAフォントを選びました。恐らく、日本語に相当する文字領域のフォントであれば、何をどのように用意しても良いのではないでしょうか。

fonts-ipafont追加
~/Arduino/arduino-ide_2.3.6_Linux_64bit$ sudo apt install fonts-ipafont

4. 実行

動かすにもコマンド上で行います。参考までに、arduino-ide_2.3.6_Linux_64bitフォルダーの内容を見てみましょう。この中の「arduino-ide」が、Windowsで謂う所の実行ファイルです。

arduino-ide_2.3.6_Linux_64bit
arduino-ide_2.3.6_Linux_64bitの中

Arduino IDE起動
~/Arduino/arduino-ide_2.3.6_Linux_64bit$ ./arduino-ide

動いている様子
背景はWSLの端末

初期の状態では英語表記ですが、設定から日本語に変更しています。なお、言語の変更などIDEの詳細については、本記事の内容から逸れるため扱いません。

5. WSLUSB

ここでWSL特有の弊害が生じます。今我々はWindowsPCを使っておりますが、このPCUSBポートにArduinoを接続しても、Windowsが認識するばかりで、「WSL上のLinuxは認識しません」。このため、USBを認識させる手順が必要になります。

https://learn.microsoft.com/ja-jp/windows/wsl/connect-usb

ここからは、Windowsの操作とLinuxの操作が混在します。本記事ではこのような表記で区別しています。

区別例
~/⋯$ Linuxの操作
PS C:\> Windowsの操作

デフォルト設定

WindowsからWSLに関する設定や操作を行う際には、wslコマンドを使います。このコマンドを使う上で、今使用しているLinux(Ubuntu)を既定のものに設定しておきます。

https://learn.microsoft.com/ja-jp/windows/wsl/install#check-which-version-of-wsl-you-are-running

インストールされているLinuxの一覧は、このように知ることができます。私の環境では、Dockerがある分も表示されています。

インストール済みLinux一覧
PS C:\> wsl --list --verbose
  NAME                   STATE           VERSION
* Ubuntu                 Running         2
  docker-desktop         Stopped         2
  docker-desktop-data    Stopped         2

ここで着目するべきは、*Ubuntuについているか否かです。嘗て私の環境では、docker-desktop-dataについていました。これを変更するには、次のようにします。

Ubuntuをデフォルトに設定する
PS C:\> wsl --set-default Ubuntu
この操作を正しく終了しました。

またVERSIONとあるのは、WSL1WSL2かを示すものです。新しい2になっていることを確認しましょう。

USBデバイスを調べる

ここでは、usbipdコマンドを使います。標準搭載しているものではないため、インストールする必要があります。

https://github.com/dorssel/usbipd-win/releases

システムの種類によって適切な方を選択します。設定から、「システム」>「バージョン情報」で確認できます。

システムの種類

私の場合はこのようにx64とあるので、usbipd-win_x.x.x_x64.msiを選ぶと良いはずです。arm64もありますが、x86はありません。5.0.0からarm64版が追加されているようなので、x86もそのうち対応されるかもしれませんし、されないかもしれません。

このファイルを実行すれば、usbipdが使えるようになります。私が以前導入したものは3.0.0でしたので、この機会に5.0.0を導入し直しました。(その後5.1.0が公開されていました。)

usbipd
PS C:\> usbipd.exe --version
5.0.0-10+Branch.master.Sha.⋯.⋯

usbipdが有効になったら、このようにしてUSBデバイスの一覧を見ることができます。

USBデバイス一覧(一部隠蔽)
PS C:\> usbipd list    
Connected:
BUSID  VID:PID    DEVICE                                                        STATE
1-2    2886:002d  USB シリアル デバイス (COM4), USB 大容量記憶装置, USB 入 ...  Shared
1-3    ____:____  USB 入力デバイス                                              Not shared
1-5    ____:____  Goodix fingerprint                                            Not shared
1-6    ____:____  Integrated Webcam                                             Not shared
1-10   ____:____  インテル(R) ワイヤレス Bluetooth(R)                           Not shared

Persisted:
GUID                                  DEVICE
________-____-____-____-____________  USB Serial Converter

今回Arduinoボードとして接続しているのは、1-2のものです。

WSLに認識させる

今回は既に1-2Sharedとなっていますが、Not sharedの場合は次のようにして共有します。

共有
PS C:\> usbipd bind --busid 1-2
usbipd: info: Device with busid '1-2' was already shared. # 共有済みの場合メッセージが出る

この操作のみ、管理者権限が必要でした。以降は必要ありません。今回は既に共有してあったので、そもそも必要ありませんでした。

愈愈、WSLUSBデバイスが接続されます。

接続(一部隠蔽)
PS C:\> usbipd attach --wsl --busid 1-2
usbipd: info: Using WSL distribution 'Ubuntu' to attach; the device will be available in all WSL 2 distributions.
usbipd: info: Detected networking mode 'nat'.
usbipd: info: Using IP address xxx.xxx.xxx.xxx to reach the host.

WSLから確認する

WSLからも接続したデバイスが見えていることを確認します。

lsusb(一部隠蔽)
~$ lsusb
Bus 002 Device 001: ID ____:____ Linux Foundation 3.0 root hub
Bus 001 Device 002: ID 2886:002d Seeed Technology Co., Ltd. Wio Terminal
Bus 001 Device 001: ID ____:____ Linux Foundation 2.0 root hub

Seeed Technology Co., Ltd. Wio Terminalが、今回接続したArduinoボードです。

補遺:異なる状態の存在するボード

Arduino UNOは単純

一般に「Arduinoボード」と言えば、Arduino UNOシリーズを指すことが多いのではなかろうかと思って居ります。ご存じの通りArduino UNOには、電源のオン・オフを切り替えるスイッチのようなものは特別付いておらず、USBなどで「電源が供給されると動作する」だけの、全く単純な動きを見せます。

Bootloader mode

しかし、広義にArduinoボードを論う時、即ち派生品を含める時にはその限りではなくなります。

例に、Wio Terminalには電源スイッチに相当する物理的な機構があり、このスイッチの操作で三つの状態を切り替えて利用します。

Wio-Terminal-Bootloader
引用:https://wiki.seeedstudio.com/Wio-Terminal-Getting-Started/

  • 一つは、電源が入っておらず停止している状態。
  • 一つは、電源が入って動作している状態。
  • そして最後に、電源が入っているが動作しておらず、書き込みできる状態。

usbipd listWio Terminalを認識する時は、少なくとも電源が入っていなければなりません。

特に最後の状態を「Bootloader mode」と言います。原則として、この状態にした上でArduino IDEからプログラムを書き込みます。

また同社の提供するSeeeduino XIAOは、電源スイッチこそなかれRSTピンがむき出しになっています。これを素早く短絡させることで、動作している状態からBootloader modeに移行する仕組みです。

XIAO-reset
引用:https://wiki.seeedstudio.com/Seeeduino-XIAO/

状態による区別

XIAOを例に、単に動作している状態とBootloader modeとで、二つのコマンドの表示を比較しています。

単に動作している状態
# Windows
PS C:\> usbipd.exe list
Connected:
BUSID  VID:PID    DEVICE                                                        STATE
1-2    2886:802f  USB シリアル デバイス (COM4)                                  Attached
1-3    ____:____  USB 入力デバイス                                              Not shared
︙

# WSL
~$ lsusb
Bus 002 Device 001: ID ____:____ Linux Foundation 3.0 root hub
Bus 001 Device 005: ID 2886:802f Seeed Technology Co., Ltd. Seeed XIAO M0
Bus 001 Device 001: ID ____:____ Linux Foundation 2.0 root hub
bootloader mode
# Windows
PS C:\> usbipd.exe list
Connected:
BUSID  VID:PID    DEVICE                                                        STATE
1-2    2886:002f  USB シリアル デバイス (COM5), USB 大容量記憶装置, USB 入 ...  Shared
1-3    ____:____  USB 入力デバイス                                              Not shared
︙

# WSL
~$ lsusb
Bus 002 Device 001: ID ____:____ Linux Foundation 3.0 root hub
Bus 001 Device 004: ID 2886:002f Seeed Technology Co., Ltd. Seeeduino XIAO
Bus 001 Device 001: ID ____:____ Linux Foundation 2.0 root hub

表示される名称も然り、COM4COM5か、802f002fかというように、まるで異なるデバイスかのような扱いに感じます。実際、それぞれ別途usbipd bindSharedに設定しなければなりません。この現象はWio Terminalでも同様です。

一方、動く以外に状態のないArduino UNOの場合、このような現象は見られませんでした。

再接続の自動化

--auto-attachオプションをつけることで、コマンドが終らなくなり、デバイスの再接続が自動で行われるようになります。

自動再接続の様子
PS C:\> usbipd attach --wsl --busid 1-2 --auto-attach       
usbipd: info: Using WSL distribution 'Ubuntu' to attach; the device will be available in all WSL 2 distributions.
usbipd: info: Detected networking mode 'nat'.
usbipd: info: Using IP address xxx.xxx.xxx.xxx to reach the host.
usbipd: info: Starting endless attach loop; press Ctrl+C to quit.
WSL Attached
WSL Detached
WSL usbip: error: Attach Request for 1-2 failed - Device not found
WSL usbip: error: Attach Request for 1-2 failed - Device busy (exported)
usbipd: warning: The device appears to be used by Windows; stop the software using the device, or bind the device using the '--force' option.
WSL Attached

6. LinuxArduino

ここからは、WSLに限らずDebian系のLinuxArduinoボードを扱う際の設定です。例えば、VirtualBoxでも同様の手順を行います

結論から言えば、Arduinoボードを扱う「権限」を与えます。chmodコマンドを使って手作業で権限を付与している情報もありますが、ここでは「権限に関するルールを定める」方法を紹介します。

手順が煩雑ですから、流れを図示します。

USB認識の確認

こちらは既に述べたlsusbでの確認です。

lsusb(一部隠蔽)
~$ lsusb
Bus 002 Device 001: ID ____:____ Linux Foundation 3.0 root hub
Bus 001 Device 002: ID 2886:002d Seeed Technology Co., Ltd. Wio Terminal
Bus 001 Device 001: ID ____:____ Linux Foundation 2.0 root hub

先ほどは存在を確認するばかりでしたが、今回はデバイス名の左にある数値2886:002dを記録します。2886は「vendor id」、002dは「product id」を示します。

特にvendor idである2886は、Seeed社のものであれば共通の値を取るようです。次は、Seeed製の別デバイスXIAOを見た様子です。

XIAOの場合
~$ lsusb
Bus 002 Device 001: ID ____:____ Linux Foundation 3.0 root hub
Bus 001 Device 006: ID 2886:002f Seeed Technology Co., Ltd. Seeeduino XIAO
Bus 001 Device 001: ID ____:____ Linux Foundation 2.0 root hub

vendor idである2886の共通していることが分かるでしょう。このように、それぞれのデバイスで異なるproduct idではなく、製造元で固有のvendor idを用いることで、「同社製造のデバイス全てについて共通の設定」ができるのです。

従って、記録する値はvendor idである2886のみでも構いません。

USB権限のルール設定

権限を定めるルールを.rulesファイルとして作成し、/etc/udev/rules.d/というフォルダーに配置します。作成する際のファイル名は自由でよいと思われますが、99_~~.rules98_~~.rulesというように、数字を99から始めて付する習俗が見られます。

本記事でも、99-seeed-boards.rulesというファイル名で作成しました。

現在地は/etc/udev/rules.dであることに注意
/etc/udev/rules.d$ cat 99_seeed_boards.rules 
ATTRS{idVendor}=="2886", ENV{ID_MM_DEVICE_IGNORE}="1"
SUBSYSTEM=="usb", ATTRS{idVendor}=="2886", MODE="0666"
SUBSYSTEM=="tty", ATTRS{idVendor}=="2886", MODE="0666"

ATTRS{idVendor}=="2886"は先のvendor idです。
ENV{ID_MM_DEVICE_IGNORE}="1"ModemManagerにデバイスを制御させないための記述だそうです
MODE="0666"は権限です。chmod 666と同様、読み取りと書き込みを全てのユーザーに許可しているようです。

ファイルを配置しただけでは意味が無いため、設定を適用します。

$ sudo udevadm control --reload-rules

グループへの追加

自分をdialoutグループに追加します。

始めは誰も属していない
$ cat /etc/group | grep dial
dialout:x:20:

dialoutグループに自分が属していなければ、このようなコマンドで追加します。グループにユーザーを追加するコマンドは複数あるため、お好きな方法で構いません。

$ sudo gpasswd -a 「自分のユーザー名」 dialout 
ユーザ 「自分のユーザー名」 をグループ dialout に追加

これで/etc/groupの内容が更新されます。

$ cat /etc/group | grep dial
dialout:x:20:「自分のユーザー名」

一方、idコマンドでは確認できない場合があります。

$ id
uid=1000(「自分のユーザー名」) gid=1000(「自分のグループ名」) groups=1000(「自分のグループ名」),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),125(lpadmin),137(sambashare)
$ id | grep dial # dial で検索すると何も該当しない

その際は再起動します。WSLでない場合は、一般的な再起動方法で構いません。

しかしながら、WSLの再起動はWindowsから行います。なお再起動と言い乍ら、一度シャットダウンします。

PS C:\> wsl --shutdown

WSLのターミナルが閉じた場合は、再びWSLを起動しましょう。ターミナルが残っているならば、このようなメッセージが出ているかもしれません。

[プロセスはコード 1 (0x00000001) で終了しました]
このターミナルを Ctrl+D で閉じるか、Enter キーを押して再起動できます。

指示の通り再起動することができます。

7. Arduino IDEからArduinoへの書き込み

ArduinoボードをUSBケーブルでWindows PCに接続した上で、usbipd attachWSLに(自動)接続します。その後の手順は通常のArduino IDEと同じ操作ですから、本記事では説明を省きます。

最終的に、ArduinoボードがArduino IDEから認識できたら設定完了です。適当なプログラムを書き込んでみましょう。果たして書き込めたでしょうか。

Arduino UNO R3の場合、正常にプログラムを書き込むことができました。

Arduino IDEから書き込めないボードが存在する?

註にて触れたように、Wio Terminalを使った場合、加えてSeeeduino XIAOを使った場合、どうも書き込むことができませんでした。

当然乍ら、Windowsから書き込むことは問題なくできています。
また、VirtualBoxで試した場合には書き込めることを確認しました
更に、同じWSLに於いて、Rust(cargo-hf2)による書き込みは以前からできておりました。

VirtualBoxで同じように設定したのですから、設定が誤っているわけではないはず。何より、Rustとは言えWSLで書き込むことは出来ていました。しかもArduino IDEWio Terminalを認識している⋯。

Wio Terminalを認識している

ここまで条件が揃っていて、書き込みに必ず失敗します。

No upload port found

︙
No device found on ttyACM0
Set binary mode
Send auto-baud
Set binary mode
Failed uploading: uploading error: exit status 1

思いつく手段は幾つか試してみたものの、未だ書き込みに成功したことは一度とありません。にも拘わらず、Arduino UNO R3を試したところ失敗することなく書き込むことができました。

以上の事から、WSLとボードの相性の問題なのではないか、との仮説を立てて諦めました。何より、VirtualBoxであれば何の障壁もなく書き込めるのですから、もはや其方で宜しいでしょう。

Discussion