第24回 Raspberry PiのGPIOを制御する(コマンド編)

今回はターミナルのコマンドプロンプトからRaspberry PiのGPIOピンを制御してみます。

今回の説明内容

今回はターミナル上のコマンドプロンプトを使ってRaspberry PiのGPIOピン制御をしてみます。制御手段としてはechoコマンドを使う方法とgpioコマンドを使う方法の2通り、制御の内容としてはLEDの点灯/消灯の制御とスイッチの状態読み取りを行います。

echoコマンドとgpioコマンドの使い方は後で詳しく説明します。なおechoコマンドは一般的なLinuxコマンド、gpioコマンドはRaspberry PiのGPIO制御用に開発された「Wiring Pi」と呼ばれているライブラリのコマンドです。

今回の説明内容は以下になります。

  • ブレッドボードの確認
  • GPIO制御方法概要
  • echoコマンドによるLED点滅制御方法
  • gpioコマンドによるLED点滅制御方法
  • catコマンドによるスイッチ状態読み取り方法
  • gpioコマンドによるスイッチ状態読み取り方法

 

ブレッドボードの確認

ブレッドボードに回路を組み立てましたので、念のため配線を確認しましょう。配線をする際は、Raspberry Piの電源はOFFにした状態で行うようにしてください。

Bb completed

配線を確認したら電源を入れます。リモート環境の場合は立ち上がったぐらいにssh接続します。

それでは、GPIO制御方法の概要から確認していきます。

 

GPIO制御方法概要

実際にGPIOがどのように制御されているか詳細に説明しようとすると、プロセッサのメモリ構成や内部構成の説明まで必要になってしまい、入門から外れた内容になってしまいますので、簡単に説明したいと思います。

Raspberry PiのGPIOを制御するには、メモリの特定の場所にデータを書き込んだり読み出したりすることにより行います。かなり細かい話になりますが、Raspberry PiのGPIOピンをONにするには、0x7E20001C番地にデータを書き込みます。(PICマイコンやAVRマイコンを経験された方であれば、レジスタの読み書き、と説明した方がわかりやすいかもしれませんね)

ただ普通のLinuxなどのOSでは、特定のメモリにデータを書き込む、ということはなかなか難しいです。そこで、Raspberry Piではシステム標準で簡単にGPIOピンを制御できる仕組みが用意されています。これが後で説明するechoコマンドによる制御方法です。ただ、このechoコマンドでの制御はできることも限られていたり、ちょっと使いづらいところもありますので、Wiring Piという有名なライブラリがリリースされてまいす。このライブラリにはgpioというコマンドがあり、このコマンドを使用するとechoコマンドより細かな制御ができたり、打ち込むコマンドの長さが短くなったりします。

それではこの2つの方法について説明していきます。

 

echoコマンドによるLED点滅制御方法

最初の制御方法はechoコマンドを使用します。

先ほど、Raspberry PiのGPIO制御は特定のアドレスのメモリにデータを書き込んだり、そこからデータを読み出したりする、と説明しましたが、これでは簡単に制御できませんので、Raspbianではファイルシステムに結びつけて制御する仕組みが提供されています。なんか「ファイルシステムに結びつけて、特定のアドレスのメモリを制御する」なんて、何言ってんの?、って感じになってしまいますので、具体例で確認しましょう。細かいことはどーでもいいですよね。

GPIOを制御するファイルは以下のディレクトリにまとめられています。

/sys/class/gpio/

例えばGPIO21であれば、

/sys/class/gpio/gpio21/value

というファイルに対して、0を書き込むとGPIO21ピンがOFFに、1を書き込むとGPIO21ピンがONになります。またこのファイルを読み取ることにより、現在のピンの状態(0か1か)がわかります。

それではこのあとGPIOピンを制御する方法について順を追って説明します。

GPIOピンを制御するには、GPIO21ピン(晴れ用のLED接続ピン)であれば /sys/class/gpio/gpio21/value に値を書き込みます。書き込みを行うにはエディタではなく、echoコマンドを使用します。このechoコマンドについて簡単に説明しておきます。

そもそもこのechoコマンドはファイルに書き込む目的のものではなく、文字列を表示するコマンドなんです。

それではechoコマンドの基本的な使い方を確認しておきましょう。ターミナルアプリからRaspberry Piにsshで接続したら、以下のコマンドを入力してリターンキーを押します。

pi@raspberrypi ~ $ echo 'Hello'

すると、以下のように表示されます。

pi@raspberrypi ~ $ echo 'Hello'
Hello

このechoコマンドは指定したパラメータ(上の例では Hello という文字列)を表示する機能を持っています。なんかあんまりいらないコマンドのような気もしますよね。でも第12回で説明した「リダイレクト」機能を使うとファイルに書き込むことができます。

第12回の説明では、リダイレクトを使ってlsコマンドの結果をファイルに出力する練習をしてみましたよね。このechoコマンドにリダイレクトを組み合わせると、lsコマンドの時と同じように表示結果をファイルに出力することができます。簡単な例で復習しておきましょう。リダイレクトはコマンドの後に “>”を書いて、その後にファイル名を書けば結果をファイルに出力できます。

pi@raspberrypi ~ $ echo 'Hello' > test.txt

実際に Hello という文字がtest.txtファイルに書き出されているか確認してみましょう。ファイルの中身を表示するためにここではcatコマンドを使用します。

pi@raspberrypi ~ $ cat test.txt
Hello

もうおわかりだと思いますが、Raspberry PiのGPIO制御はこのechoコマンドを使ってパラメータを先ほどのファイル(/sys/class/gpio/gpio21/value)に書き出すことになります。それでは、/sys/class/gpio/ディレクトリに中身を見てみましょう。

pi@raspberrypi ~ $ ls /sys/class/gpio/
export gpiochip0 unexport

このような結果になると思います。これから /sys/class/gpio/gpio21/ にある value というファイルをいじりたいのにそのファイルがありませんよね。

このシリーズの第2回で説明しましたが、GPIOピンは出力機能にしたり、入力機能にしたり、いろいろな機能をプログラムで設定することができることを説明しました。

上のように何もしていない状態で /sys/class/gpio/gpio21/ がないのは、GPIO21ピンの機能を設定していないためなんです。GPIOピンを制御するには、最初にGPIOピンをどのような機能として使うのかを設定して、その後にファイルに書き込んだりして制御します。

Raspberry PiのGPIOピンを制御する手順を整理すると以下のようになります。

  1. GPIOピンを使うよ!って宣言する
    例えばこれからGPIO21ピンを使う場合、/sys/class/gpio/exportというファイルにGPIOの番号を書き込みます。これを行うことにより、/sys/class/gpio/ディレクトリにGPIO21ピン制御に必要なファイルが生成されます。具体的には次のセクションで詳しくみてみます。
  2. 使う宣言をしたGPIOピンが入力なのか出力なのか指定する
    (1)で使う宣言したGPIOピンが入力なのか出力なのか指定します。
  3. GPIOを制御する
    これでやっとGPIOの制御ができるようになります。GPIO21ピンであれば、/sys/class/gpio/gpio/21/valueというファイルに0(ゼロ)か1(いち)を書き込みます。
  4. 使い終わったらGPIOピンを使い終わったよ!って宣言する
    GPIOピンの制御が終わったら使い終わったよ、って教えてあげます。

なお、最後の「使い終わったよ」宣言をしないで電源をOFFにした場合、初期状態にリセットされます。

それではこの手順を頭に入れていただいて次に実際にGPIOピンを制御してみます。

ここでは晴れ用のLEDが接続されているGPIO21ピンを制御してみます。

まずGPIO21ピンを使うよ、って宣言します。この宣言は、仮想ファイルの/sys/class/gpio/exportにGPIO番号を書き込みます。

pi@raspberrypi ~ $ echo 21 > /sys/class/gpio/export

これでGPIO21ピンを制御できる準備ができました。でも何も反応がないのでちょっと不安ですよね。それでは実際に先ほどの/sys/class/gpio/ディレクトリを見てみましょう。

pi@raspberrypi ~ $ ls /sys/class/gpio/
export gpio21 gpiochip0 unexport

という感じでgpio21ディレクトリが生成されています。ついでですので、この生成されたgpio21ディレクトリの中身もみておきましょう。

pi@raspberrypi ~ $ ls /sys/class/gpio/gpio21/
active_low device direction edge power subsystem uevent value

この後ですが、このgpio21/directionに入力か出力かの書き込みをして、gpio21/valueに0か1を書き込んでLEDの点灯、消灯を行います。

ではGPIO21ピンを出力ピンとして設定します。

pi@raspberrypi ~ $ echo out > /sys/class/gpio/gpio21/direction

これでいよいよLEDの点灯、消灯が制御できるようになりました。

まずは点灯させてみます。

pi@raspberrypi ~ $ echo 1 > /sys/class/gpio/gpio21/value

Fine led control

こんな感じで点灯しましたでしょうか。うまく点灯しない場合は回路接続、入力したコマンドなどをもう一度確認してみてください。次にLEDを消灯してみます。

pi@raspberrypi ~ $ echo 0 > /sys/class/gpio/gpio21/value

GPIO21ピンの制御が終わったら、最後に使わない宣言をします。

pi@raspberrypi ~ $ echo 21 > /sys/class/gpio/unexport

もう一度、/sys/class/gpio/ディレクトリの中身を確認してみます。

pi@raspberrypi ~ $ ls /sys/class/gpio/
export gpiochip0 unexport

gpio21ディレクトリがなくなっていますね。

このようにRaspberry Piの標準システムではファイルシステムを使ってGPIOピンを制御することになります。

 

gpioコマンドによるLED点滅制御方法

先ほどのechoコマンドによる制御はファイルシステムを通してGPIOを制御していましたが、コマンドで制御できる「Wiring Pi」というライブラリ(オープンソース)があります。以前はWiring Piのパッケージをインストールする必要がありましたが、RaspbianのJessieではインストール済みのようです。ということで以前はWiring Piのインストールから始める必要がありましたが、今はgpioコマンドをすぐに使えます。それでは早速使ってみましょう。

といきたいところですが、gpioコマンドでGPIOピンを制御する際のGPIO番号の指定方法は3通りあるのでその指定方法から確認します。

例えば上のechoコマンドと同じようにGPIO番号で指定する場合は、gpioコマンドを入力する際に -g オプションをつける必要があります。この方法を含め、3つの指定方法は以下になります。

指定方法 gpioコマンドオプション指定
GPIO番号で指定する -gオプションをつける
Wiring Piの番号で指定する オプション指定なし
つまりデフォルトではこの指定
物理的なピン番号で指定する -1 (数字の1)オプションをつける

今まで物理的なピン番号とGPIO番号は何回も出てきました。Wiring Pi番号はWiring Piライブラリ独自の指定番号で、ピン番号ともGPIO番号とも異なります。どのピンがどの指定方法で何番かわからなかったら、gpioコマンドで確認できます。gpio readallと入力すると指定番号が表示されます。

実際に確認してみます。

pi@raspberrypi ~ $ gpio readall
 +-----+-----+---------+------+---+---Pi 2---+---+------+---------+-----+-----+
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
 |     |     |    3.3v |      |   |  1 || 2  |   |      | 5v      |     |     |
 |   2 |   8 |   SDA.1 |   IN | 1 |  3 || 4  |   |      | 5V      |     |     |
 |   3 |   9 |   SCL.1 |   IN | 1 |  5 || 6  |   |      | 0v      |     |     |
 |   4 |   7 | GPIO. 7 |   IN | 1 |  7 || 8  | 1 | ALT0 | TxD     | 15  | 14  |
 |     |     |      0v |      |   |  9 || 10 | 1 | ALT0 | RxD     | 16  | 15  |
 |  17 |   0 | GPIO. 0 |   IN | 0 | 11 || 12 | 0 | IN   | GPIO. 1 | 1   | 18  |
 |  27 |   2 | GPIO. 2 |   IN | 0 | 13 || 14 |   |      | 0v      |     |     |
 |  22 |   3 | GPIO. 3 |   IN | 0 | 15 || 16 | 0 | OUT  | GPIO. 4 | 4   | 23  |
 |     |     |    3.3v |      |   | 17 || 18 | 0 | OUT  | GPIO. 5 | 5   | 24  |
 |  10 |  12 |    MOSI |   IN | 0 | 19 || 20 |   |      | 0v      |     |     |
 |   9 |  13 |    MISO |   IN | 0 | 21 || 22 | 0 | OUT  | GPIO. 6 | 6   | 25  |
 |  11 |  14 |    SCLK |   IN | 0 | 23 || 24 | 1 | IN   | CE0     | 10  | 8   |
 |     |     |      0v |      |   | 25 || 26 | 1 | IN   | CE1     | 11  | 7   |
 |   0 |  30 |   SDA.0 |   IN | 1 | 27 || 28 | 1 | IN   | SCL.0   | 31  | 1   |
 |   5 |  21 | GPIO.21 |   IN | 1 | 29 || 30 |   |      | 0v      |     |     |
 |   6 |  22 | GPIO.22 |   IN | 1 | 31 || 32 | 0 | IN   | GPIO.26 | 26  | 12  |
 |  13 |  23 | GPIO.23 |   IN | 0 | 33 || 34 |   |      | 0v      |     |     |
 |  19 |  24 | GPIO.24 |   IN | 0 | 35 || 36 | 0 | IN   | GPIO.27 | 27  | 16  |
 |  26 |  25 | GPIO.25 |   IN | 0 | 37 || 38 | 0 | IN   | GPIO.28 | 28  | 20  |
 |     |     |      0v |      |   | 39 || 40 | 0 | OUT  | GPIO.29 | 29  | 21  |
 +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
 | BCM | wPi |   Name  | Mode | V | Physical | V | Mode | Name    | wPi | BCM |
 +-----+-----+---------+------+---+---Pi 2---+---+------+---------+-----+-----+

この表で、真ん中の “Physical” は物理ピン番号、”wPi”はWiring Pi番号、”BCM”はGPIO番号になります。この入門シリーズでは、GPIO番号を使用しますので、gpioコマンドには -g オプションをつけて使用します。

gpioコマンドを使用してGPIOの出力制御するためのgpioコマンドの使い方は以下になります。

  • GPIOピンのモード設定
    gpio -g mode [GPIOピン名番号] [モード]というフォーマットになります。[モード]にはoutかinを指定することになります。モードには他の指定もありますが、この入門シリーズでは出力と入力しか扱いませんので、outかinの指定になります。
  • GPIOピンの出力制御
    gpio -g write [GPIOピン名番号] [値]というフォーマットになります。[値]には0か1を指定します。

それでは実際に試してみます。今度は曇り用のLEDを制御してみます。曇り用のLEDはGPIO20ピンに接続していますので、GPIO20ピンを出力モードに設定します。

pi@raspberrypi ~ $ gpio -g mode 20 out

次にGPIO20ピンをON(=1)にします。

pi@raspberrypi ~ $ gpio -g write 20 1

Cloudy led control

こんな感じで点灯しましたでしょうか。

残りのLEDの点灯も同様に確認してみてください。雨用、雪用、鉄道運行状況表示用の赤、緑、青の点灯が確認できればLED関連の接続は全てOKです。確認する際、もし興味があれば、Wiring Pi番号での指定、物理的なピン番号での指定も試してみてください。

 

catコマンドによるスイッチ状態読み取り方法

次のスイッチの状態を読み取ってみましょう。先ほど、echoコマンドでvalueファイルに1か0を書き込むと出力制御ができましたが、スイッチの状態を読み取るにはvalueファイルの中身を表示すればわかります。ファイルの中身は、具体的にはGPIOピンが3.3Vの場合は1、0Vの場合は0になります。この中間の値の時は、第12回で説明したGPIOの電気的特性に従います。

先ほど説明したGPIO制御手順に沿って作業してみます。スイッチを接続したGPIOピンはGPIO18ですので、このGPIOをこれから制御します。

まずGPIO18ピンを使うよ宣言です。

pi@raspberrypi ~ $ echo 18 > /sys/class/gpio/export

次にGPIO18ピンを入力ピンとして設定します。

pi@raspberrypi ~ $ echo in > /sys/class/gpio/gpio18/direction

これでvalueファイルの中身を確認すれば、その時点のスイッチの状態がわかります。スイッチはプルダウン抵抗をつけましたので、スイッチを押した時は1、はなした時は0になります。

なお、valueファイルの中身を表示するコマンドは catコマンドを使用します。まずはスイッチを押さないで読み取ってみます。

pi@raspberrypi ~ $ cat /sys/class/gpio/gpio18/value
0

0が表示され、スイッチが押されていないことがわかります。次に、スイッチを押したまま、valueファイルの中身を確認します。上矢印キーで先ほどのコマンドを呼び出して、リターンキーを押す時にスイッチを押しておいてください。

pi@raspberrypi ~ $ cat /sys/class/gpio/gpio18/value
1

今度は1って表示されましたよね。ということで、このようにGPIOの値を読み取ればスイッチの状態がわかります。

GPIO18ピンの制御が終わったら、最後に使わない宣言をします。

pi@raspberrypi ~ $ echo 18 > /sys/class/gpio/unexport

 

gpioコマンドによるスイッチ状態読み取り方法

gpioコマンドを使用してGPIOの入力を読み取るためのgpioコマンドの使い方は以下になります。

  • GPIOピンのモード設定
    先ほどの出力制御と同様です。gpio -g mode [GPIOピン名番号] [モード]というフォーマットになります。今回は入力ですので[モード]にはinを指定することになります。
  • GPIOピンの入力制御
    gpio -g read [GPIOピン名番号]というフォーマットになります。このコマンドを入力すると指定したGPIOピンの現在の値が表示されます。

それでは実際に試してみます。GPIO番号で指定しますので -g オプションを忘れずに。

pi@raspberrypi ~ $ gpio -g mode 18 in

次にGPIO18ピンの値を読み取ります。まずはスイッチを押さないで試してみます。

pi@raspberrypi ~ $ gpio -g read 18
0

次にスイッチを押した状態で試してみます。

pi@raspberrypi ~ $ gpio -g read 18
1

うまく確認できましたでしょうか。

もし動かなかったりわからないところがありましたらコメント欄かお問い合わせフォームでご連絡いただければと思います。

次回はPHPやPythonのプログラムでLEDの点滅制御、スイッチの読み取りをしてみます。ここまで確認できれば、あとはネットから天気予報情報と鉄道運行状況を取得してLEDを点滅させるだけです! (それがちょっと大変だったりしますが)

« »