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

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

目次

今回の説明内容

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

これからターミナル上でコマンドを入力してGPIOを制御しますが、やり方は何通りかあります。この記事では代表的な2通りの制御方法を説明します。言葉の意味はあとで詳しく説明しますが、一つは「echoコマンド」を使う方法、もう一つは「gpioコマンド」を使う方法です。2通りのやり方を通して、GPIOの制御に少しずつ慣れていきましょう。

また、GPIO制御の内容としては「LEDの点灯/消灯の制御」と「スイッチの状態読み取り」を行います。

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

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

ブレッドボードの確認

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

Bb completed

配線を確認したら電源を入れます。

デスクトップタイプ機器構成の場合はターミナルアプリを起動します。リモート接続タイプ機器構成の場合は、ターミナルアプリでRaspberry Piにssh接続します。

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

GPIO制御方法概要

実際にGPIOがどのように制御されているか詳細に説明しようとすると、プロセッサのメモリ構成や内部構成の説明まで必要になり、入門から外れた内容になってしまいますので、概略の説明にとどめます。概要とはいってもかなり込み入った内容ですので、このセクションは理解できなくても問題ありません。

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

ただ、特定のメモリにデータを書き込む、ということはシステム上とても危険です。書き込む場所を間違えるとシステムが止まってしまうことがあります。最近はそれほど見かけませんが、WindowsでいうとブルースクリーンになりOSが止まったり、MacでいうとシステムパニックになってOSが再起動することがあります。この原因の一つがメモリにデータを書き込む際に、書き込み先を間違えてしまう、というものです。

このようにメモリに直接データを書き込むことは危険ですので、Raspbianでは直接メモリを読み書きすることなくGPIOピンを制御できる仕組みが用意されています。

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

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

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

Raspbianでは、特定のアドレスのメモリにデータを読み書きすることなくGPIO制御する方法として、ファイルシステムに結びつけて制御する仕組みが提供されています。

なんだか「ファイルシステムに結びつけて、特定のアドレスのメモリを制御する」って言われてもさっぱり???、って感じですよね。実際に動かしてみたほうが早く理解できますので、理屈は置いておいて実際に動作させてみましょう。

GPIOを制御するには、以下のディレクトリのファイルを操作します。

/sys/class/gpio/

例えばGPIO21ピンをON/OFF制御したいケースを説明します。

GPIO21ピンを制御するファイルとして、上のディレクトリの中に

/sys/class/gpio/gpio21/value

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

ファイルを読み書きしてGPIOピンを制御できるというのは、なんだか不思議な感じがします。でも直接メモリを読み書きすることを避ける方法としては面白いアイデアですよね。

それではこのあとGPIOピンを制御する手順を詳しく説明します。

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

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

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

pi@raspberrypi ~ $ echo 'Hello'

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

pi@raspberrypi ~ $ echo 'Hello'
Hello

「echo」とは日本語で「真似する」とか「反響」という意味ですが、この意味の通り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に書き出すことになります。

このようにRaspbianではechoコマンドを使用してGPIOのON/OFF制御ができますが、実際にechoコマンドでGPIOを制御するには前準備が必要になります。

次に、この前準備について説明します。

まず、/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ピンをどのような機能として使うのかを設定して、その後にファイルに書き込んだりして制御します。

Raspbianの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にした場合、初期状態にリセットされます。

それではこの手順に沿って、実際に晴れ用の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ピンを出力制御をするのか入力読み取りをするのか設定します。具体的にはgpio21/directionファイルに入力か出力かを書き込みます。入力の場合は「in」、出力の場合は「out」を書き込みます。

それでは以下のように入力して、GPIO21ピンを出力ピンとして設定します。

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

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

あとは、/sys/class/gpio/gpio21/valueファイルに0か1を書き込めばGPIOの出力制御ができます。まずは点灯させてみます。

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ディレクトリがなくなっていますね。

このようにRaspbianではファイルシステムを使ってGPIOピンを制御する方法が提供されています。

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

先ほどのechoコマンドによる制御はファイルシステムを通してGPIOを制御していましたが、コマンドで制御できる「Wiring Pi」というライブラリ(オープンソース)があります。Raspbian Stretchではデフォルトでインストールされていますが、Stretch-Liteにはインストールされていません。

そこで、リモート接続タイプの場合のみ、以下の手順でWiring Piをインストールします。

最初に以下のコマンドを入力してtmpディレクトリに移動します。

pi@raspberrypi ~ $ cd /tmp

次に、以下のコマンドを入力してWiringPiのパッケージをインターネットから取得します。

pi@raspberrypi /tmp $ wget https://lion.drogon.net/wiringpi-2.50-1.deb

30秒程度で取得が終わると思います。取得できたら以下のコマンドを入力してWiringPiのパッケージをインストールします。

pi@raspberrypi /tmp $ sudo dpkg -i wiringpi-2.50-1.deb

インストールできましたので自分のディレクトリに戻っておきましょう。

pi@raspberrypi /tmp $ cd
pi@raspberrypi ~ $ 

リモート接続タイプ機器構成の場合の準備ができました。

ここからはデスクトップタイプ、リモート接続タイプ共通の作業になります。

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

このGPIO番号の指定方法はgpioコマンドを入力する際にオプションで指定します。指定方法は以下になります。

指定方法 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を点滅させるだけです! (それがちょっと大変だったりしますが)

更新履歴

日付 内容
2015.12.6 新規投稿
2019.5.12 Stretch LiteのWiringPiインストール方法追加
通知の設定
通知タイミング
guest
0 コメント
本文中にフィードバック
全てのコメントを見る
みちお
みちお
3 年 前

親切な説明有難うございました。GPIO制御の理解が進みました。

目次