西川和久の不定期コラム
「Raspberry Pi3 Model B」で遊んでみよう!Part2
~GPIO入門1。ポートのオン/オフとステータス取得編
2016年6月20日 06:00
前回のPart1は「Raspberry Pi3 Model B」の簡単な紹介だったが、今回Part2はいよいよRaspberry Pi特有のGPIOをコントロールする。そう言う筆者もここから先は未知の世界。いろいろ調べながらの執筆となった。まずは基本。ポートをオン/オフし、LEDをピカピカさせてみたい。
GPIOの仕様
GPIOとは“General Purpose Input/Output”の略であり、前回、「GPIO×26 3.3V/16mA、UART、I2C、SPI、I2S、PWM、5V、3.3V/50mAで構成」と書いたが具体的なピンアサインが分からないと何もできない。公式サイトによると、以下の図の通り。


これによると赤色の5Vが2つ、橙色の3.3Vが2つ、黒色のGNDが8つ。そしてGPIOが上に12、下に14配置されている。またGPIOのそれぞれは複数の機能を割り当て可能で、今回は一番単純な操作のみを行なう。さらにに複雑な操作はPart3か4で扱う予定だ。
なおGPIOはモデルによって26ピンと40ピンがあり、「Raspberry Pi3 Model B」は40ピン構成だ。互換性を保つため40ピン中1~26ピンまでは、26ピンモデルと同じ仕様になっている。
gpioコマンドを使ってコントロール
一般的にWindowsでもLinuxでもハードウェアをコントロールするには、デバイスドライバを用意しなければならない。とは言え、ここからプログラミングが必要となるとハードルが高過ぎるため、今回インストールした「RASPBIAN」には、予め複数方法が用意されている。その1つが「gpio」コマンドだ。このコマンド1つで、GPIOの設定やステータスを得ることができる。
手始めに、本当にソフトウェア的にGPIOをコントロールできるのか、公式サイトに見習って(笑)、LEDのオン/オフに挑戦する。回路は簡単!ピン12/GPIO18へLEDを接続、適当な抵抗を繋ぎ、ピン39/GNDへ落とす。これで準備は完了だ。
まず、“gpio readall”でGPIOのステータスを表示してみると以下のようになった。
$ gpio readall
+-----+-----+---------+------+---+---Pi 3---+---+------+---------+-----+-----+
| 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 | IN | TxD | 15 | 14 |
| | | 0v | | | 9 || 10 | 1 | IN | 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 | IN | GPIO. 4 | 4 | 23 |
| | | 3.3v | | | 17 || 18 | 0 | IN | GPIO. 5 | 5 | 24 |
| 10 | 12 | MOSI | IN | 0 | 19 || 20 | | | 0v | | |
| 9 | 13 | MISO | IN | 0 | 21 || 22 | 0 | IN | 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 | IN | GPIO.29 | 29 | 21 |
+-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
| BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM |
+-----+-----+---------+------+---+---Pi 3---+---+------+---------+-----+-----+
中央のPhysicalが実際のピンアサイン(BCMはGPIO番号、wPiはWiringPiと呼ばれるC言語のライブラリ用)なので、先の図を眺めつつ、何がどうなっているのか1つずつ追うのが理解の早道だろう。
なお、GPIOの初期値は全てMode INになっており、V=1の部分はプルアップ(電源へ抵抗で釣る)、V=0の部分はプルダウン(GNDへ抵抗で落とす)の処理が内部的に行なわれ、オープン(ハイ・インピーダンス)になっているポートはないようだ。各GPIOのプルアップ/ダウンはプログラマブルで変更できる。
gpioコマンドで特定のポートをコントロールするには、
1)ポート番号を指定してINかOUTを設定
2)ポート番号を指定してreadかwrite
の手順を踏む必要がある。またポート番号は“物理的なピン番号”か“GPIO番号”を指定可能だ。
$ gpio -1
※物理的なピン番号指定
$ gpio -g
※GPIO番号指定
まず、ポートを出力用に設定する。コマンドは以下の通り。
$ gpio -g mode 18 out
※GPIO18を出力に設定
$ gpio -1 mode 12 out
※12pinを出力に設定(上記と同じ意味となる)
$ gpio readall
+-----+-----+---------+------+---+---Pi 3---+---+------+---------+-----+-----+
| BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM |
| 17 | 0 | GPIO. 0 | IN | 0 | 11 || 12 | 0 | OUT | GPIO. 1 | 1 | 18 |
※確かにpin12/GPIO18のモードがOUTになった。V=0
モードがOUTになったがV=0なのでLEDは消灯。LEDを点灯するにはV=1にする。コマンドは以下通り。
$ gpio -g write 18 1
※GPIO18を1に設定
$ gpio -1 write 12 1
※12pinを1に設定(上記と同じ意味となる)
$ gpio readall
+-----+-----+---------+------+---+---Pi 3---+---+------+---------+-----+-----+
| BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM |
+-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
| 17 | 0 | GPIO. 0 | IN | 0 | 11 || 12 | 1 | OUT | GPIO. 1 | 1 | 18 |
※確かにpin12/GPIO18のVが1になった。これでLEDは点灯する
LEDを消灯するには
$ gpio -g write 18 0
※GPIO18を0に設定
$ gpio -1 write 12 0
※12pinを0に設定(上記と同じ意味となる)
とすればよい。いかがだろうか? gpioコマンドを使えば、LEDのオン/オフ程度は非常に簡単に行えることがお分かり頂けたと思う。
応用例としてPHPを使って、一定間隔LEDが点灯/消灯を繰り返すプログラムを書いてみた(2秒ずつオン/オフを5回)。
<?php
system("gpio -g mode 18 out"); // GPIO18を出力モードへ
for ($i = 0; $i < 5; $i++) { // 5回繰り返し
system("gpio -g write 18 1"); // LED点灯
sleep(2); // 2秒そのまま
system("gpio -g write 18 0"); // LED消灯
sleep(2); // 2秒そのまま
}
?>
$ php led.php
※プログラムのファイル名がled.phpの場合、これで実行できる
逆にGPIOのステータスを読み込むには、該当ポートをプルアップにして、GNDとショートさせた方が回路的に楽なので、ポートを入力モードに切り替えてから、
$ gpio -g mode 18 in
※GPIO18を入力に設定
$ gpio -g mode 18 up
※プルダウンの時はgpio -g mode 18 down
+-----+-----+---------+------+---+---Pi 3---+---+------+---------+-----+-----+
| BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM |
+-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
| 17 | 0 | GPIO. 0 | IN | 0 | 11 || 12 | 1 | IN | GPIO. 1 | 1 | 18 |
※GPIO18がV=1となった。
として、GPIO18をプルアップにする。そしてそのままステータスを読み込むと、
$ gpio -g read 18
1
※GPIO18は1
スイッチか何かでGPIO18とGNDをショートすると(プルアップしているため、ショートすると電流が流れるものの、KΩ単位の抵抗で釣っているので微々たるもの。問題ない)、
$ gpio -g read 18
0
※GPIO18は0
となる。パラレル出力の簡単なセンサーであれば、同様の手法で値を取得可能だ。センサーからのデータさえ得られれば、後はプログラムでその内容を処理すればいい。
Pythonを使ってコントロール
「RASPBIAN」には“RPi.GPIO”と呼ばれるPythonのパッケージも用意されている。先にあげた“WiringPi”はC言語用でコンパイルが必要になるが、こちらはPHP同様、スクリプト言語なので即実行でき手軽だ。
またgpioコマンドはコマンドレベルの操作となり、PHPなどではsystem()を使わなければならず美しくないが、こちらはファンクションで操作でき、美しく書くことができる。
“RPi.GPIO”パッケージの詳細はこちらを参考にして欲しい。LEDをオン/オフする程度であれば、
setmode() モード設定
setup() セットアップ
output() アウトプット
cleanup() 後片付け
この4つのファンクションを使えばいい。具体的なコードは以下の通り(LEDを5秒点灯して消灯する)。
#!/usr/bin/python
# coding: utf-8(ソースコードはutf8)
# timeモジュールをインポート
import time
# RPi.GPIOモジュールをインポートして別名GPIOとして扱う
# RPi.GPIO.setmode(RPi.GPIO.BCM)などと書くのが面倒なため
import RPi.GPIO as GPIO
# GPIO番号で操作。物理的なpin番号で扱う場合は GPIO.setmode(GPIO.BOARD)となる
GPIO.setmode(GPIO.BCM)
# GPIO18を出力モードへ
GPIO.setup(18, GPIO.OUT)
# GPIO18を1へ。LED点灯
GPIO.output(18, 1)
# 5秒待つ
time.sleep(5)
# GPIO18を0へ。LED消灯
GPIO.output(18, 0)
# 後片付け
GPIO.cleanup()
これを例えばled.pyファイルに保存して、chmod +x led.pyで実行可能にした後、
$ ./led.py
で作動する。更に複数のGPIOへLEDを接続した場合、18と書いてダイレクトに指定している部分を配列とし、
bcm_list = [18,23,24]
GPIO.setup(bcm_list, GPIO.OUT)
と、このように書けば、配列の中で指定したポート全てが一度で設定可能だ。ポートを読み取るのは(別名GPIO、GPIO番号で操作の場合)、
# GPIO18を入力へ/プルアップ
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)
# GPIO18を入力へ/プルダウン(上記とどちらか)。
# もしくは , pull_up_down= 以降、必要なければ書かなくてもよい
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
# 画面にGPIO18のステータス0か1を表示
print GPIO.input(18)
となる。
いずれにしても先のPHPでsystem()を使うより、よりプログラムらしくなるのがお分かり頂けただろうか。
このほかGPIOの操作は、「ファイルシステムを使う方法」や、少し触れた「C言語のライブラリ“WiringPi”を使う方法」もあるので、興味のある人はインターネットで検索して欲しい。
余談になるが、(正確には違うが)1bitのポート単位で(簡単とは言え)プログラミングするのは何十年ぶりか!?の勢いだ(笑)。
筆者はもともとハードウェアからコンピュータを始めた世代で、一番初めに作ったのはオール手配線(笑)のMotorola MC6802を搭載したワンボードマイコン。当時高校生だったが、高価なNECの「TK-80」は買えずお年玉を握りしめてパーツを購入、自作した。
その後、仕事でMSXのゲームを作ったり、Z80のワンボードを設計して外部機器をコントロールするなど、直接ポートを叩くプログラムが主だった記憶がある。当時、開発環境はCP/M80。C言語を使ったROM化も割と早い時期から実戦に投入した(確かWhitesmith C)。今回久々にポート叩いて「そう言えば……」と思い出した次第だ。
Part2はGPIOを使う基本中の基本でポートをオン/オフし、LEDを点灯/消灯してみた。コントロール方法も複数あり、得意もしくは簡単なものから試すのがいいだろう。次回Part3は、もう少し実用的(?)なGPIOのコントロールを行ってみたい。

楽天市場 売れ筋ランキング
Amazon売れ筋ランキング
Anker Soundcore Life P2 Mini【完全ワイヤレスイヤホン / Bluetooth5.3対応 / IPX5防水規格 / 最大32時間音楽再生 / 専用アプリ対応】ブラック
¥4,490
Anker Soundcore P40i (Bluetooth 5.3) 【完全ワイヤレスイヤホン/ウルトラノイズキャンセリング 2.0 / マルチポイント接続 / 最大60時間再生 / PSE技術基準適合】ブラック
¥7,990
イヤホン bluetooth ワイヤレスイヤホン 48時間の再生時間 重低音 LEDディスプレイ表示 小型/軽量 IPX7防水 ブルートゥース 接続瞬時 Hi-Fi ブルートゥースイヤホン Type-C 急速充電 ぶるーとぅーすイヤホン iPhone/Android/Pad適用 スポーツ/通勤/通学/WEB会議 (ホワイト)
¥39,999
【VGP 2025 金賞】EarFun Air Pro 4 ワイヤレスイヤホン Bluetooth 5.4/50dBアダプティブ式 ハイブリッドANC/最先端チップ「QCC3091」aptX Losslessに対応/ハイレゾ LDAC対応/Snapdragon Sound™ に対応/Auracast™に対応/52時間連続再生【6マイクAI 通話/PSE認証済み】 装着検出機能 (ブラック)
¥9,990
EarPods with 3.5 mm Headphone Plug
¥2,668
by Amazon 炭酸水 ラベルレス 500ml ×24本 強炭酸水 ペットボトル 500ミリリットル (Smart Basic)
¥1,409
コカ・コーラ い・ろ・は・す天然水ラベルレス 560ml ×24本
¥2,131
by Amazon 天然水 ラベルレス 500ml ×24本 富士山の天然水 バナジウム含有 水 ミネラルウォーター ペットボトル 静岡県産 500ミリリットル (Smart Basic)
¥1,173
キリン 自然が磨いた天然水 ラベルレス 水 2リットル 9本 国産 天然水 ミネラルウォーター ペットボトル 軟水
¥2,722
い・ろ・は・すラベルレス 2LPET ×8本 【Amazon.co.jp限定】
¥1,168
葬送のフリーレン(14) (少年サンデーコミックス)
¥583
薬屋のひとりごと 15巻 (デジタル版ビッグガンガンコミックス)
¥770
無職転生 ~異世界行ったら本気だす~ 22 (MFコミックス フラッパーシリーズ)
¥733
ブルーロック(33) (週刊少年マガジンコミックス)
¥594
黄泉のツガイ 9巻 (デジタル版ガンガンコミックス)
¥590