IoTで使うPython入門Step0-(3) 定番のLチカ

ピンの呼び方が複数ある

 現在のラズパイのI/O(アイオー、入出力)はGPIOと呼ばれ、40ピンのピンヘッダが利用できます。電源、グラウンドが複数あるので、信号用は2/3ぐらいです。ラズパイのCPUは3.3Vで動作するので、GPIOの信号のHighレベルは3.3Vです。別途USBからの電圧5Vが用意されています。
 センサなどの電源に5Vを使えますが、センサのI/OのHighレベルが5Vであれば、ラズパイと直接つなげてはいけません。電圧レベル変換回路を途中に入れます。  

 GPIOには、めんどうなことに4種類の呼び方があります。

  • 物理的ピン番号xxそのもの
  • wiringPiのGPIOxx
  • BCMのGPIOxx
  • 機能

 C言語でよく使われるwiringPiの中のユーティリティがgpioです。今のラズビアンOSにはインストールされています。
 wiringPiにはPython用もありますが、2017年春ごろ、カーネルがアップデートしたとき動作しないなどのトラブルが多かったので、筆者は使わなくなりました。

gpio readall

 中央の2列が物理的なピン番号です。Nameが機能です。wPiはwiringPiが使っている番号です。機能のGPIOxxはwPiの番号です。BCMはCPUが入ったSOCのパッケージのピン番号です。一般にGPIOxxという表現のときはBCMの数字を使います。

  • GPIOライブラリのRPi.GPIOは、ピンを指定するのに物理的なピン番号もしくはBCMを選ぶ
  • I2Cライブラリのsmbusで、バス番号1を使うときは、物理ピンの3番と5番、つまりSDAとSCLを使う。バス番号0では物理ピンの27番と28番を使う
  • SPIライブラリのspidevで使うバス番号0は、19番ピンのMOSI、21番ピンのMISO、23番ピンのSCLKに加えてチップ・セレクト信号はCE0とCE1の2本が用意されている。バス番号1は、38番ピンのMOSI、35番ピンのMISO、40番ピンのSCLKに加えてチップ・セレクト信号は36番ピンのCE2を使う(dtoverlayの設定などが必要)
  • 1-Wireは7番ピンがデフォルト

 LEDをつなぐのは上記のピンを避けます。機能によっては初期状態がHighになっているピンもあります。それらを除けば初期状態はLowです。

LEDを点灯する

 LEDは電流を流すと点灯します。接続方法は2通りあります。

 (a)であればGPIO17をHighにすると、VccからGPIO17を通してLEDに電流が流れます。(b)であればGPIO17をLowにすると、VccからLEDを通じてGPIO17経由でGNDへ電流が流れます。
 ラズパイの電源を入れた直後、LowになっているGPIOポートを使えば、プログラムを動かす前に、(a)は光らず、(b)は点灯します。
 いずれも、LEDの色と電源電圧にあった電流制限抵抗Rを直列に入れます。白色と青色は順方向電圧Vfが3Vあるので、電流制限抵抗値は100Ω以下になります。少し計算がシビアなので、Vfの低い赤色、黄色、緑色LEDを選び、1kΩの抵抗にすると光ります。電流を計算すると、

  (3.3-1.7) / 1000 = 1.6mA もしくは(3.3-2.0) / 1000 = 1.3mA


とそこそこ少なめですが十分光ると思います。470Ωならばこの倍の電流が流れるので、十分な輝度が得られます。ラズパイのGPIOが流せる電流は8mAらしいです(2~16mAの範囲で2mAステップで設定でき、GPIO合計で最大50mA)。
 計算するのが面倒であれば、電流制限抵抗内蔵か、定電流内蔵LEDを使います。LEDのAnode(アノード)はリード線の長いほうです。
 では、GPIOピンの一番端の40番ピンGPIO21に電流制限抵抗を、直列にLEDのアノードを配線します。LEDのカソードはGND(たとえば39番ピン)へつなぎます。

 配線が正しいかどうかをgpioコマンドで確認します。WiringPiのユーティリティなので、デフォルトだとwPiの数字29です。

gpio mode 29 out
gpio write 29 1


 これで点灯します。消すには、0=Lowにします。

gpio write 29 0


 ピン番号には混乱させられますね。ここからは、wPiの番号は使いません。
 ところで、青色LED(Light Emitting Diode)はちょっと前にノーベル賞を日本人が受賞したので話題になりましたね。光の3原色はRed Green Blueです。赤色が最初に作られ緑色も早かったです。でも、青色が長い間作れなかったのです。半導体は、最初に純度の高くて欠陥のない結晶を作るところから初めて、そのあとに不純物を混ぜます。ところが、明るい青色LEDは、ある一定の結晶の欠陥があることが条件だったのです。

 青色の補色は黄色です。青色が発光する上に黄色の蛍光体をかぶせると、出てくる色は白色です。太陽の光のようにいろいろな色が混じってはいません。

 LEDはダイオードなので、リード線が2本出ています。長いほうがアノード(A)で短いほうがカソード(K)です。アノードを電位の高いほうにつなぎます。

PythonでLチカ

 GPIOを個別に利用するときは、RPi.GPIOのライブラリを使うのが定番です。gpiozeroのライブラリでもLチカができます。
 Muを立ち上げて、次のプログラムを入力します。

 このプログラムは普通に動き、LEDが1秒ごとに点滅します。しかし、実行を停止し、再度実行するとエラーが出ます。

 プログラムを中断するときは、通常キーボードからCTRL-Cを押します。gpio.cleanup()が動かなかったのです。
 この対策をしたのが次のプログラムです。本来、CTRL-Cは強制終了なので、そうしないといけないプログラムに問題があるわけで、例えば、何かのピンがLowになったら停止するような処理があるべきです。

 それぞれの行の働きを説明します。

① RPi.GPIOというライブラリをインポートして、名称が長いうえドットが使われているのでgpioという別名でアクセスする
② timeライブラリの中に定義されている関数sleepをインポートする
③ 1行空ける
④ 21という整数値をLED_pinという変数名に代入。Pythonに定数はない。constとか#defineはない。慣例としてPython で定数(として扱う変数)は全部大文字で書くそうです。なので、LED_PINが正しい書き方かもしれません。
⑤ ピン番号の指定をBCMで行う。ピン番号そのもので指定するときは、gpio.setmode(gpio.BOARD)
⑥ LED_pinを出力用に使う
⑦ 1行空ける
⑧ try:とexcept:がペアになって例外を処理する。プログラムでエラーが起こると、エラー・メッセージをはいて実行が止まる。これを避けるための処置。except:だけだとすべてのエラーに対応するが、except ValueError:、except OSError:、except ZeroDivisionError as err:、except NameError:、except KeyboardInterrupt:などのように個別に対応もできる。
⑨ 永久ループ。⑩、⑪、⑫、⑬が繰り返される。
  ⑩ GPIO21(物理ピンは40番)にHighを出力(Trueは1)
  ⑪ 2秒待つ
  ⑫ GPIO21(物理ピンは40番)にLowを出力(Falseは0)
  ⑬ 2.4秒待つ
⑭  プログラムの実行中にCTRL-Cが押されるとここに処理に移る
⑯ ライブラリRPi.GPIOの終了処理。LEDは消える。

  RPi.GPIOの使用方法は、ここが最新のようです。

コラム 実行権

 本文のプログラムはMuの中で実行し、CTRL-Cを押しても止まりません。エラーをMuが横取りしているのかもしれません。Muを使わないときは、通常ターミナルでpython led.pyとして動かすのですが、動くためには実行権が必要です。

cd mu_code
ls -l

 ファイルのアクセス権限は、「所有者」「所有グループ」「その他」の3種類にそれぞれ、「読む」「書く」「実行」の権限が指定できます。

 led1.pyは、

  • 所有者つまりpiはrwなので、読み書きができるが、xがないので実行できない
  • グループとその他は読み出すだけで、書き込みと実行はできない

 実行できるように変更します。3桁の数字は、それぞれ、所有者、グループ、その他のアクセス権を表しており、rwx=111=7、r--=100=4、r--=100=4です。

chmod 744 led.py


 その結果がled0.pyです。

 誰でも実行できるようにするには、rwx=111=7、r-x=101=5、r-x=101=5に変更します。

chmod 755 led.py


 GUIでも同じことができます。ファイルをマウスで右クリックして出てくるメニューの一番下にあるファイルのプロパティを選びます。

 実行権を変えるので、実行の項目の「なし」から「所有者のみ」を選択しなおします。

 744のアクセス権になりました。

 ここで、二つ疑問があります。

 一つは、744というのはほとんど使われません。それは、GPIOなどはrootが所有していて、このままのアクセス権では利用できないからです。しかし、piユーザに限っては、現在、アクセスできます。ずいぶん昔はだめでした。
 もう一つは、chmodは通常root権限で動かすので、sudo chmod xxxとするのが常識です。しかし、piユーザはsudoを使わないでもこのコマンドを実行できます。

 筆者はその理由がわかりません。調べた結果は次の通りです。

 piユーザはsudoできるグループに属しています。その設定は、/etc/sudoersと/etc/sudoers.d/010_pi-nopasswdにあります。
 piユーザは、マシンが立ち上がったときパスワードなしでログインできます。その設定は、/etc/lightdm/lightdm.conf にあります。 

 ユーザpiの属しているグループはgroups piで調べられます。

 pi : pi adm dialout cdrom sudo audio video plugdev games users input netdev spi i2c gpio

 GPIOなどはUNIXシステムではファイルとしてアクセスします。/devにデバイス・ファイルがあります。通常はttyとかを使うのですが、ラズパイ・ユーザは/dev/serial0 /dev/i2c-1 /dev/spidev0.0などを利用します。

 ls -l /dev/gpio*

を実行すると、所有者はrootで、gpioグループだとわかります。i2cやspiは、デバイスを有効にしていないとデバイス・ファイルは存在しません。gpioは何もしなくても存在しています。

 検索すると、カーネルが4.1に上がったときに/dev/gpiomemが使えるようになり、gpioグループの権限でGPIOにアクセスできるようになったという記述が見つかります。RPi.GPIOは/dev/gpiomemを利用しています(0.6.0a3から)。しかし、筆者は、そのころ(2016年11月25日)から逆にsudoが必要になった経験があるので、変更が頻繁にあったのかもしれません。

 以上からわかることは、

  • piユーザはsudoグループに属しているので、sudoをコマンドの前につければroot権限でコマンドを実行できる。
  • /etc/sudoers.d/010_pi-nopasswdにpi ALL=(ALL) NOPASSWD: ALLが書かれているので、その際にパスワードを聞かれない(2016年ごろから)。
  • piユーザはgpio、i2C、SPIのグループに属しているので、それらになり替わってアクセスできる。

 この推測が正しいのか、これだけが理由でないかもしれません。1年少し前に、modulesなどのファイルにI2Cなどの設定が現在のような形でない記述があったことがありますが、その後、なくなりました。

 長くなりましたが、テキスト・エディタで入力した本文のプログラム名をled.pyとすれば、

chmod 744 led.py
python led.py


で実行できます。chmodで変更しているファイルはpiユーザの所有物なので、sudoを入れる必要はないです。単独で実行できるようにするには、プログラムの先頭に、

#!/usr/bin/env python

を置きます。そうすると、次のように実行できます。

chmod 744 led.py
./led.py

Tips 10番ごとにマーキングを

 マザーボードのメーカで知られているASUSから、ラズパイと形状が同じボードが出ています。GPIOがカラフルです。なんというグッドなセンスでしょう。

 40ピンあると、数えるときに間違いが起こります。10番、20番、30番に白いマーカを付けました。