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


2020/05/02

今回はラズパイ実機から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コンテナで、ラズパイらしい組込テクニックを記事にしようかと画策しております。
記事を書いた人

記事の担当:taconocat

ナンデモ系エンジニア

電子工作を身近に知っていただけるように、材料調達からDIYのハウツーまで気になったところをできるだけ細かく記事にしてブログ配信してます。