ししかわの二足ロボ研修ブログ

M5Stack UnitV2でロボットを動かす(下準備):ししかわの二足ロボ研修 Part.4

ししかわの二足ロボ研修
「UnitV2」はM5Stackの半分くらいのサイズ感

ししかわです。

社員研修の一環で二足歩行ロボットを作って、競技会「Humanoid Autonomous Challenge(HAC)」に参加します。

記事一覧

前回からM5Stackの画像認識モジュールM5Stack UnitV2」をM5Stackのユニットとしてではなく単独で使い、ロボットを制御できるようにしよう!というマニアックな計画を進めています。

UnitV2で好きなプログラムを動かすための下準備として、まずUnitV2の仕組みを調べてみます。今回のゴールとして、電源投入時に自動で起動する「画像認識サーバ」を止めてみましょう。この作業を通じてUnitV2のLinuxの基本的な構造や、プログラム自動起動の仕組みも理解できます。

なお、UnitV2のビルトイン機能の紹介や使い方の説明は、既に他のブログ記事が複数出ているため本連載では割愛します。トラブルシュートも含め公式ドキュメントが詳しいです。

m5-docs
The reference docs for M5Stack products. Quick start, get the detailed information or instructions such as IDE,UIFLOW,Ar...

組込みLinuxボードとしての「M5Stack UnitV2」

前回説明したとおり「M5Stack UnitV2」は画像認識機能のベースとしてLinuxがインストールされているのでした。

「UnitV2」はM5Stackの半分くらいのサイズなのにLinuxが動く

組込みLinuxの知識がないと「この小さいボードでLinuxが動いてるってどういうこと?」「LinuxってUbuntuとかRaspbian(現RaspberryPi OS)のこと?」など、疑問に思うことでしょう。

そこで、次の疑問点について説明します。

  • そもそもLinux/組込みLinuxとは何か
  • UnitV2で動いているLinuxの種類は何か
  • 画像認識機能が自動で立ち上がるのは、どんな仕組みによるものか

そもそもLinux/組込みLinuxとは何か

Linuxに馴染みの無い方もいるかと思いますので簡単におさらいします。

OSとしてのLinuxは、プロセス管理やメモリ管理、ハードウェアとの通信などOSとしてのコア機能を司る「Linuxカーネル」と、カーネルを用いたライブラリやアプリケーションからなる「ユーザランド」からなります。ユーザランドのアプリケーションはLinuxカーネルとシステムコールを介してやりとりします。Linuxカーネルに含まれる各ハードウェア用のドライバはカメラやネットワークインタフェースカード(NIC)を制御します。

Linuxユーザランドとカーネル

Linuxカーネルがハードウェア毎の違いを吸収して共通のAPIを用意しているため、ユーザランドのアプリケーションは(たいていの場合)ハードウェアの差異を気にせずに済みます。例えば皆さんのPCでUSBカメラを違うものに差し替えても同じようにZoomが使えているのはLinuxカーネルのドライバのおかげです。また、多くのドライバはカーネルモジュールとして提供されています。必要なモジュールのみ実行時に動的に読み込む作りにすることでカーネル本体のサイズは小さく保てます。

UbuntuなどのディストリビューションはLinuxカーネルに加えて様々なユーザランドのプログラム群で構成されます(図中の点線枠)。

ユーザの用途に応じて様々なディストリビューションがあります。例えばUbuntu DesktopはデスクトップPCとしての用途を想定しているため、アプリケーションマネージャやGUI、開発用のライブラリが初めから入っていてすぐに使い始められます。

一方、組込み機器でLinuxを使う場合、はじめから用途が特定のタスクに限定できるので、Linuxカーネルの他には必要最小限のアプリケーションだけインストールしてあれば十分です。既存のディストリビューションを使わずとも、カーネルやユーザランドのプログラムを自分で選択してコンパイルすればよいのです。

UnitV2で動いているLinuxの種類は何か

ここからは実際にUnitV2を操作しながら進めてみます。手元にUnitV2を持っている方はぜひコマンドを自分で打ちながら試してみてください!

M5Stack UnitV2はPCとUSBケーブルで接続するだけでネットワークが有効になります。

UnitV2とPCをUSB接続する

手始めにSSH接続してみましょう。UnitV2にはunitv2.localという名前でアクセスできます。またm5stackという名前の初期ユーザが登録されています。

host-pc% ssh m5stack@unitv2.local
m5stack@unitv2.local's password: (初期パスワードは12345678)
unitv2%

(こんなに小さいカメラにSSH接続できてしまうのは不思議な感じですね!)

さて、UnitV2ではどんなディストリビューションが使われているでしょうか?OSの種類に関する情報はたいてい/etc/ディレクトリ配下にありますので見てみましょう。

unitv2% ls /etc/
...
os-release
...

unitv2% cat /etc/os-release
NAME=Buildroot
VERSION=2020.02.8
ID=buildroot
VERSION_ID=2020.02.8
PRETTY_NAME="Buildroot 2020.02.8"

なるほど、OSはBuildrootというもののようです。あまり聞き慣れないですね。

Buildroot - Making Embedded Linux Easy

公式サイトには次のような説明があります。

Buildroot is a simple, efficient and easy-to-use tool to generate embedded Linux systems through cross-compilation.

Buildrootは冒頭で説明したような組込み機器のためのLinuxシステムを生成するツールです。GUIなどで必要なパッケージを定義すると、それら一式を備えたミニマルなLinuxシステムが作れます。

Buildrootは「クロスコンパイル」に対応しています。クロスコンパイルとは、開発用の環境と異なる環境で動くプログラムをコンパイルすることです。たとえばx86_64アーキテクチャの開発用PCでシステム一式をビルドして、armv7アーキテクチャのUnitV2に書き込み、動かすことができます。

クロスコンパイルの例

ということでUnitV2は特定のディストリビューションではなく、UnitV2向けに専用にビルドされた組込みLinuxであることが確認できました。

他にも幾つかの設定を確認してみましょう。

ロードされているカーネルモジュールは次のとおりです。8188fu(Wi-Fiアダプタのドライバ)、nls_utf8(多言語サポート)、ehci_hcd(USBドライバ)などがロードされています。

unitv2% lsmod
Module Size Used by Tainted: G 
vfat 6820 1 
ntfs 73756 0 
nls_utf8 1457 0 
msdos 5668 0 
grace 5158 1 
fat 42384 2 vfat,msdos
ehci_hcd 33777 0 
cifs 169945 0 
8188fu 836118 0

さきほどSSHでunitv2というホスト名でアクセスできました。これは/etc/hostsで定義されています。

unitv2% cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 unitv2

(今は使っていませんが)UnitV2はWi-Fiアクセスポイントにもなります。これは/etc/wpa_supplicant.confで定義されています。

unitv2% cat /etc/wpa_supplicant.conf 
ctrl_interface=/var/run/wpa_supplicant
eapol_version=1
ap_scan=1
fast_reauth=1

network={
ssid="M5-2.4G"
psk=(Wi-Fiアクセスポイントのパスフレーズ)
}%

プログラム自動起動の仕組み

UnitV2はUSBケーブルを挿すと電源が自動でONになります。起動すると、

  • SSHサーバ
  • Wi-Fiアクセスポイント
  • 画像認識機能のテスト用Webサーバ(ブラウザからアクセスできる)

などが自動起動します。これらがどこで起動されるか確認していきます。

まず「画像認識機能のテスト用Webサーバ」の本体ですが、m5stackユーザのホームディレクトリ配下にありました。

unitv2% ls -l /home/m5stack
total 0
drwxrwxr-x   10 m5stack  avahi         1768 Jan  1 00:03 payload
unitv2% ls -l /home/m5stack/payload
total 48
drwxr-xr-x    2 m5stack  staff         2400 Apr 28  2021 bin
drwxr-xr-x    2 m5stack  staff          160 Apr 28  2021 data
drwxr-xr-x    2 m5stack  staff         3032 Apr 28  2021 models
-rwxr-xr-x    1 m5stack  staff          382 Apr 21  2021 run_notebook.py
-rwxr-xr-x    1 m5stack  staff         1575 Apr 21  2021 server.py
-rwxr-xr-x    1 m5stack  staff        30619 Apr 28  2021 server_core.py
-rwxr-xr-x    1 m5stack  root          1292 Jan  1 00:18 server_log.txt
-rwxr-xr-x    1 m5stack  root            87 Jan  1 00:06 server_system_config.json
drwxr-xr-x    6 m5stack  staff          832 Apr 28  2021 static
drwxr-xr-x    2 m5stack  staff          304 Apr 28  2021 templates
drwxr-xr-x    2 m5stack  staff          328 Apr 28  2021 tools
drwxr-xr-x    6 m5stack  staff          696 Apr 28  2021 uploads

/home/m5stack/payload/server.pyがサーバを起動するPython製スクリプトでした。もちろんここに置いたスクリプトがひとりでに起動するわけではなく、どこかでこのスクリプトを実行する仕組みがあるはずです。探してみましょう。

前述のとおり、UnitV2のLinuxシステムはBuildrootで作られています。まずはBuildrootのマニュアルから、システムの初期化に関する記述を探します。

The Buildroot user manual

The BusyBox init program will read the /etc/inittab file at boot to know what to do.

説明がありました。Linuxが起動して最初に実行されるのはinitというプログラムで、/etc/inittabに定義された処理を行います。

etc/inittabを確認します。

unitv2% cat /etc/inittab
(略)
# now run any rc scripts
::sysinit:/etc/init.d/rcS
(略)

inittabの細かな記法の説明は省略します(inittabのファイルにコメントで書かれています)。/etc/init.d/配下にあるrcSというスクリプトを実行しているようです。この中身を確認してみます。

unitv2% cat /etc/init.d/rcS
#!/bin/sh


# Start all init scripts in /etc/init.d
# executing them in numerical order.
#
for i in /etc/init.d/S??* ;do
(中略、スクリプトを順番に実行している)
done

コメントの説明にある通り、/etc/init.d/配下のSから始まる名前のスクリプトを順番に実行しています。だんだん欲しい情報に近づいてきましたね。init.dの中には何が入っているでしょうか。

unitv2% ls -l /etc/init.d  
total 128
-rwxr-xr-x    1 avahi    avahi         1012 Jan 18  2021 S01syslogd
-rwxr-xr-x    1 avahi    avahi         1004 Jan 18  2021 S02klogd
-rwxr-xr-x    1 avahi    avahi         1876 Jan 18  2021 S02sysctl
-rwxr-xr-x    1 avahi    avahi          274 Jan 18  2021 S05avahi-setup.sh
-rwxrwxr-x    1 avahi    avahi         1167 Apr  6  2021 S05initled
-rwxrwxr-x    1 avahi    avahi          667 Apr  6  2021 S06wifipwr
-rwxrwxr-x    1 avahi    avahi          673 Jan  1 00:00 S100setup-priv
-rwxrwxr-x    1 avahi    avahi          501 Apr  6  2021 S10loadfsko
-rwxrwxrwx    1 root     root           600 Jan  1 00:00 S110thermal
-rwxr-xr-x    1 avahi    avahi         1684 Jan 18  2021 S20urandom
-rwxr-xr-x    1 avahi    avahi          404 Jan 18  2021 S21haveged
-rwxr-xr-x    1 avahi    avahi          459 Jan 18  2021 S30cgroupfs
-rwxr-xr-x    1 avahi    avahi         1635 Jan 18  2021 S30dbus
-rwxr-xr-x    1 avahi    avahi          438 Jan 18  2021 S40network
-rwxr-xr-x    1 avahi    avahi          617 Jan 18  2021 S41dhcpcd
-rwxr-xr-x    1 avahi    avahi          581 Jan 18  2021 S49ntp
-rwxr-xr-x    1 avahi    avahi          285 Jan 18  2021 S50avahi-daemon
-rwxr-xr-x    1 avahi    avahi          210 Apr  6  2021 S50mosquitto
-rwxr-xr-x    1 avahi    avahi          445 Apr  6  2021 S50nginx
-rwxr-xr-x    1 avahi    avahi          531 Apr  6  2021 S50sshd
-rwxr-xr-x    1 avahi    avahi          916 Apr  6  2021 S80dhcp-relay
-rwxr-xr-x    1 avahi    avahi          779 Apr  6  2021 S80dhcp-server
-rwxr-xr-x    1 avahi    avahi          427 Jan 18  2021 S80dnsmasq
-rwxrwxr-x    1 avahi    avahi          630 Apr  6  2021 S81mdev
-rwxrwxr-x    1 avahi    avahi          638 Jan  1 00:00 S85runpayload
-rwxrwxr-x    1 avahi    avahi          741 Jan  1 00:00 S90wifi-conf
-rwxrwxr-x    1 avahi    avahi         1428 Jan  1 00:00 S95ip-conf
-rwxrwxrwx    1 root     root           596 Jan  1 00:00 S96ntpdate
-rwxrwxr-x    1 avahi    avahi         5492 Jan  1 00:00 automount.sh
-rwxr-xr-x    1 avahi    avahi          423 Jan 18  2021 rcK
-rwxr-xr-x    1 avahi    avahi          408 Jan 18  2021 rcS

初期化のためのスクリプトが色々置かれていました。ファイル名を見るとSSHの起動(S50sshd)、Wi-Fiの設定(S90wifi-conf)はここで処理されることが分かります。

そしてS85runpayloadという、それっぽい名前のファイルもありますね(先のpythonスクリプトは/home/m5stack/payloadにあるのでした)。

unitv2% cat /etc/init.d/S85runpayload

#!/bin/sh

case "$1" in
        start)
                printf "Starting payload: "
                cd /home/m5stack/payload
                python3 /home/m5stack/payload/server.py &> /tmp/payload.info &
                [ $? = 0 ] && echo "OK" || echo "FAIL"

                ;;
        stop)
                printf "Stoping payload: "
                killall -9 python3
                [ $? = 0 ] && echo "OK" || echo "FAIL"
                ;;
        restart|reload)
                $0 stop
                $0 start
                ;;
        *)
                echo "Usage: $0 {start|stop|restart}"
                exit 1
esac

exit 0

中身を見てみると…ビンゴ!これはserver.pyを起動しています。ついでにサーバのエラーログはtmp/payload.infoに出力されることもわかりました。

以上の検証から、今回のゴールである「画像認識サーバ」が自動で立ち上がるのを止めるには、S85runpayloadを他の場所に移してしまえばよさそうです。

ここで1点補足。このスクリプトの移動にはルート権限が必要ですが、デフォルトではユーザm5stackはsudoを使えません。次の記事に紹介されている手順でsudoが使えるようになります。

404
ページが見つかりませんでした。
unitv2% sudo mv /etc/init.d/S85runpayload /home/m5stack/
unitv2% sudo reboot

再起動してブラウザからunitv2.localにアクセスしてもサーバが起動していません。変更が反映されていますね!


以上、UnitV2の中身を確認してきました。想像していたよりも普通にLinuxだということが実感してもらえたのではないでしょうか。cd、ls、catなどのコマンドは当たり前に使えますし、「UnitV2だけの特別なコード」みたいなものもありません。ロボットの画像処理のために「Raspberry Piよりも小さくてLinuxが使える開発ボード」を探している方には、きっと有力な選択肢となるでしょう。

次回はクロスコンパイル環境を整えて、UnitV2でHello Worldを動かしてみます。

→次の記事

M5Stack UnitV2用クロスコンパイル環境の構築:ししかわの二足ロボ研修 Part.5
ししかわです。 社員研修の一環で二足歩行ロボットを作って、競技会「Humanoid Autonomous Challenge(HAC)」に参加します。 記事一覧 M5Stackの画像認識モジュール「M5Stack UnitV2」をM5Sta...
タイトルとURLをコピーしました