【ラズパイでもDocker!】ラズパイでLチカ 〜 実機からShellで行う方法 & Docker AlpineコンテナからShellで行う方法の比較


※ 当ページには【広告/PR】を含む場合があります。
2020/05/02
【ラズパイでLチカ】Docker Alpineコンテナ上のNode.jsネイティブからラズパイのGPIOを操作する方法




今回はラズパイ実機からShellでLチカする方法を紹介し、それと比較してDocker AlpineコンテナからLチカを行ったときの内容です。
Dockerからラズパイ開発をしていく上であらためて基礎的な知識をおさらいしたい方向けの話題になっています。


実機からShellで



まずがあらためてラズパイに標準装備しているShellコマンドを用いてLチカする方法をおさらいしてみます。
今回はラズパイ3B+を利用します。

ピン番号の確認



一番手っ取り早くピン番号の確認するには、
pinout コマンドを実行してみましょう。

            $ pinout
,--------------------------------.
| oooooooooooooooooooo J8     +====
| 1ooooooooooooooooooo  PoE   | USB
|  Wi                    oo   +====
|  Fi  Pi Model 3B+ V1.3 oo      |
|        ,----.               +====
| |D|    |SoC |               | USB
| |S|    |    |               +====
| |I|    `----'                  |
|                   |C|     +======
|                   |S|     |   Net
| pwr        |HDMI| |I||A|  +======
`-| |--------|    |----|V|-------'

Revision           : a020d3
SoC                : BCM2837
RAM                : 1024Mb
Storage            : MicroSD
USB ports          : 4 (excluding power)
Ethernet ports     : 1
Wi-fi              : True
Bluetooth          : True
Camera ports (CSI) : 1
Display ports (DSI): 1

J8:
   3V3  (1) (2)  5V    
 GPIO2  (3) (4)  5V    
 GPIO3  (5) (6)  GND   
 GPIO4  (7) (8)  GPIO14
   GND  (9) (10) GPIO15
GPIO17 (11) (12) GPIO18
GPIO27 (13) (14) GND   
GPIO22 (15) (16) GPIO23
   3V3 (17) (18) GPIO24
GPIO10 (19) (20) GND   
 GPIO9 (21) (22) GPIO25
GPIO11 (23) (24) GPIO8 
   GND (25) (26) GPIO7 
 GPIO0 (27) (28) GPIO1 
 GPIO5 (29) (30) GND   
 GPIO6 (31) (32) GPIO12
GPIO13 (33) (34) GND   
GPIO19 (35) (36) GPIO16
GPIO26 (37) (38) GPIO20
   GND (39) (40) GPIO21

For further information, please refer to https://pinout.xyz/

        

ヘルプにもある通り、
ここのサイト でもっと詳しい情報が得られます。
今回は3番ピン(GPIO2)と9番ピン(GND)を適当な抵抗とLEDを接続したものでテストしました。

合同会社タコスキングダム|蛸壺の技術ブログ


抵抗値はLEDのスペック表などを参照して決め(分からなければ1kΩ程度を挿す)、LEDは端子の極性に注意します。 よく長い方が陽極側だという説明されているのを見ますが、個人的には短い方(陰極)をGNDに接続する、という覚え方をしています。

各コマンドの基本動作



まずGPIOポートを開放するためには、ピン番号を指定して、
export コマンドを実行します。 例えばここでは、GPIO2(ピン番号3)を開放します。

            $ echo 2 > /sys/class/gpio/export
$ ls /sys/class/gpio/
export       gpio2        gpiochip0    gpiochip504  unexport

        

GPIO2を解放後、
/sys/class/gpio/gpio2 というディレクトリが作成されています。 このディレクトリの中にGPIOを制御するための様々なファイルがあります。
入力と出力のどちらを行なうかを
direction コマンドで指定します。
今回のように信号を発信する場合はout指定で出力にします。 これでLEDが点灯・消灯します。

            $ echo out > /sys/class/gpio/gpio2/direction

        

次に指定したピンから信号の発信ON/OFFをするコマンドですが、まず
1value ファイルに書き込むと、電圧が印加されLEDが点灯します。 逆に 0 を書き込むと消灯となります。

            #Turn on
$ echo 1 > /sys/class/gpio/gpio2/value

#Turn off
$ echo 0 > /sys/class/gpio/gpio2/value

        

最後に以下の
unexport コマンドで、 gpio2 の制御終了は明示に記述させます。

            $ echo 2 > /sys/class/gpio/unexport
$ ls /sys/class/gpio/
export       gpiochip0    gpiochip504  unexport

        

これを実行すると
gpio2 のディレクトリが消去されます。
以上が基本的な制御の流れです。

Lチカ on 実機



まず適当なフォルダ直下に、以下のようなスクリプトを
blink.sh の名前で新規作成・編集・保存します。

            #!/bin/bash

echo 2 > /sys/class/gpio/export
sleep 1
echo out > /sys/class/gpio/gpio2/direction
sleep 1

for ((i=1; i<20; i++))
do
  echo $i
  echo 1 > /sys/class/gpio/gpio2/value
  sleep 0.2
  echo 0 > /sys/class/gpio/gpio2/value
  sleep 0.2
done

echo 2 > /sys/class/gpio/unexport

        

そして、この
blink.sh を走らせます。

            $ chmod +x blink.sh
$ ./blink.sh

        

でチカチカすると思います。

合同会社タコスキングダム|蛸壺の技術ブログ

ここまでの内容で参考になるサイト

RPi GPIO Code Samplesレッツラズパイ!〜Lチカ&Lピカをマスターしよう編〜

DockerコンテナからShellで

事前準備〜Dockerのインストール



まず
dockerRasbian にインストールします。 既に手元のラズパイにインストールされている方はこの節をスキップされてください。
なお、ここに
簡単にインストールできると紹介のあるスクリプト を行うと、

            % curl -sSL https://get.docker.com | sh
#...中略
Warning: apt-key output should not be parsed (stdout is not a terminal)
+ sudo -E sh -c echo "deb [arch=armhf] https://download.docker.com/linux/raspbian buster stable" > /etc/apt/sources.list.d/docker.list
+ sudo -E sh -c apt-get update -qq >/dev/null
W: https://download.docker.com/linux/raspbian/dists/buster/InRelease の取得に失敗しました  'download.docker.com' が一時的に解決できません
W: http://archive.raspberrypi.org/debian/dists/buster/InRelease の取得に失敗しました  'archive.raspberrypi.org' が一時的に解決できません
W: いくつかのインデックスファイルのダウンロードに失敗しました。これらは無視されるか、古いものが代わりに使われます。
+ [ -n ]
+ sudo -E sh -c apt-get install -y -qq --no-install-recommends docker-ce >/dev/null
E: パッケージ 'docker-ce' にはインストール候補がありません

        

といったパッケージのインストール候補が見つからないエラーが出ます。
インストールスクリプトをダウンロードして走らせる方法 に書いてあるような内容でインストールさせても結局は同じことで、

            % curl -fsSL https://get.docker.com -o get-docker.sh
% sudo sh get-docker.sh
#...中略
E: パッケージ 'docker-ce' にはインストール候補がありません

        

とエラーでとまります。
どうもレポジトリの
download.docker.com が上手く読み込めていないようです。
これは他のLinuxディストリビューションでも起こりうることですが、rasbian busterのリポジトリにリストしてあるのが
stable だけで、 stable の中にはまだdockerパッケージが含まれていないため起こるエラーのようです。
このエラーを回避のためには、
/etc/apt/sources.list.d/docker.listedge test のリポジトリを手動で追加するか、 こちらのサイト で紹介されているように nightly のチャンネルを指定して再びインストール・スクリプトを走らせると上手くいきます。

            % curl -fsSL get.docker.com | CHANNEL=nightly sh
#...中略
+ sudo -E sh -c echo "deb [arch=armhf] https://download.docker.com/linux/raspbian buster nightly" > /etc/apt/sources.list.d/docker.list
#...中略
+ sudo -E sh -c docker version
Client: Docker Engine - Community
 Version:           0.0.0-20190727010531-15bdbd7
 API version:       1.40
 Go version:        go1.12.6
 Git commit:        15bdbd7
 Built:             Sun Jul 28 07:43:31 2019
 OS/Arch:           linux/arm
 Experimental:      false
#...以下略

        

という感じにインストールが通りました。
次に
docker コマンドを使うのに、毎回 sudo docker なんて sudo を入れてタイプするのは面倒です。 なのでユーザー権限を与えます。

            % sudo usermod -aG docker [現在のユーザー名]
% docker --version
Docker version 0.0.0-20190727010531-15bdbd7, build 15bdbd7

        

これで
docker が準備完了できました。

Lチカ on Dokcer



docker越しにラズパイのGPIOを操作するには、
ここのリンク先のサイト で議論されているように、主に3通りの方法が考えられます。
今回は、shellでチカチカさせるので、ホスト側の
/sys 以下をコンテナ側の /sys にマウントさせて、先程使ったシェルを使って同じことをさせようと思います。
まずはおもむろに
armhf/alpine をベースにインタラクティブモードに入ります。

            $ docker run -it \
    --rm \
    -v /sys:/sys \
    armhf/alpine /bin/sh

        

すると、Rasbian上の
sys フォルダ以下がalpineコンテナ上に接続されています。 ポイントは -v オプションで、 sys フォルダをホストのOS側からコンテナ側に引っ張ってマウントしていることです。
インタラクティブモードから、
/sys/class/gpio/ の中身を覗いてみると、こんな感じです。

            $ ls /sys/class/gpio/
export       gpiochip0    gpiochip504  unexport

        

早速チカチカするか試します。
なお、何もパッケージ追加していない裸の
alpine イメージでは bash は使えませんので、素の sh コマンドで動作するように以下のLチカスクリプトに手直して利用します。

            #!/bin/bash

echo 2 > /sys/class/gpio/export
sleep 1
echo out > /sys/class/gpio/gpio2/direction
sleep 1

for i in `seq 1 20`
do
  echo $i
  echo 1 > /sys/class/gpio/gpio2/value
  sleep 0.2
  echo 0 > /sys/class/gpio/gpio2/value
  sleep 0.2
done

echo 2 > /sys/class/gpio/unexport

        

問題がなければこれで、実機と同様にチカチカするはずです。

ここまでの内容で参照になるサイト2



以下のサイトは、dockerコマンドの
--device オプションでGPIOを利用する際のやり方を解説してあります。

Raspbian Jessie Lite で Docker する - GPIO on Alpine Linux 編

まとめ



今回は実機でLチカさせる最も単純な方法である
shell コマンドの使い方の復習し、素のAlpineコンテナからも同じスクリプトを叩いてみることでチカチカできることを比較・検証しました。
ただ今回紹介した
sys ファルダ以下に配置してあるシェルコマンドを用いるやり方は簡単なラズパイのお勉強には利用できるものの、シェルコマンドで間接的に内部アドレス操作をしているので、結果的に処理パフォーマンスが遅くなるので、本番のラズパイ開発を進める場合には推奨されないやり方です。
今後は
--device オプションを介したdockerコンテナで、ラズパイらしい組込テクニックを記事にしようかと画策しております。