PHPでのRaspberry PiのGPIO操作~ ラズベリーパイ研究室

Raspberry Pi は簡単にいうと Linux マシンですから他の言語でも十分な開発が行えるようになっています。raspberry pi で推奨されている開発言語はどうも Pythonですが、 PHP でGPIOを操作するにはどうするか、という方法をざっと纏めてみました。



おススメ!記事
Raspberry Pi 用「HAL」で、
カップラーメン・タイマーを作ってみよう!
ラズパイDIYの決定版! ソケットサーバー「HAL」をご紹介します。

イントロダクション

 raspberry pi で推奨されている開発言語はどうも Python という事のようですね。Python は日本では少しマイナーですが世界的にはとてもメジャーな言語なので、日本と世界との温度差みたいなものが感じられます。

 Raspbian をインストールすれば Python のGPIO操作ライブラリも使えるようになっていて、すぐにLEDを光らせてみるような実験が行えるようになります。

 他のページでも紹介している Raspberry Pi での電子工作の入門書

のプログラムも Python です。

 しかし、Raspberry Pi は簡単にいうと Linux マシンですから他の言語でも十分な開発が行えるようになっています。このページでは PHP でGPIOを操作するにはどうするか、という方法をざっと纏めてみることにします。

ファイルを直接操作する

 一番汎用的な操作方法がこれだと思います。

 Raspberry Pi は /sys/class/gpio 内に決められたファイルを書きだすことでGPIOの操作が行えるようになっています。デフォルトの状態のこのディレクトリの内容を見てみると

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

 このような状態です。GPIO 25番(22番ピン)を利用するケースを考えてみると、まず、

echo 25 > /sys/class/gpio/export

として、使用するピン番号をexportに書き込みます。すると、

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

 このように、gpio25 ディレクトリが生成されます。中身を見てみると、

pi@raspberrypi /sys/class/gpio $ cd gpio25
pi@raspberrypi /sys/class/gpio/gpio25 $ ls
active_low device direction edge subsystem uevent value

 このようなファイルやディレクトリが作成されています。これで、GPIO 25番を利用する準備は整いました。ではLEDのアノード側にGPIO 25番(22番ピン)を接続し、カソード側をGNDに接続してLEDを光らせてみましょう。

ブレッドボード

 LEDを光らせるということは出力を行うということなので、direction に出力を示す“out”を書き込みます。

echo out > /sys/class/gpio/gpio25/direction

 これでGPIO 25は出力用に設定されたので、あとは value に HIGH を示す1を書き込みます。

echo 1 > /sys/class/gpio/gpio25/value

 これでLEDが点灯します。なお、value には HIGHかLOW、つまり1か0を書きこむようにしてください。

 GPIO 25 を使わなくなったら、最後にunexport に25を出力してください。gpio25 ディレクトリがクリーンナップされます。

echo 25 > /sys/class/gpio/unexport

 以上がGPIOのファイルを直接操作する方法です。ちなみに、昔の Raspbian では上記を実行するときには sudo をつける必要があったようですが、現在は gpio を操作するためのグループ gpio がつくられ、pi ユーザーもこのグループに所属するため、sudoをする必要はなくなっています。

 つまり、ファイル操作が行える言語で、Raspberry Pi で動作する言語であればなんであろうと、必ずGPIOを操作できるということになります。

 例えばPHPでの上記の一連の操作は、次のようになります。

sudo vi gpio_test.php
-----------------------------------------
<?php
file_put_contents('/sys/class/gpio/export', 25);
file_put_contents('/sys/class/gpio/gpio25/direction', 'out');
file_put_contents('/sys/class/gpio/gpio25/value', 1);

 上記プログラムを gpio_test.php として保存した後、

sudo php -q gpio_test.php

 とすることで、LEDが点灯することが確認できると思います。

点灯したLED

WiringPiを使ったGPIO操作

 WiringPi は Raspberry Pi のGPIO操作を行うC言語ライブラリです。簡単にGPIOを操作するためのメソッドが多数実装されていて、さらに、この WiringPi を他の言語でも利用できるようにしたラッパーも多数提供されています。

 この WiringPi を利用するのが一番効率が良いかと思います。

 まず、WiringPi のソースコードをgitで入手するための下準備をします。

sudo apt-get install libi2c-dev
sudo apt-get install git-core

 そうしたら、WiringPi のソースを入手してインストールします。インストールは以下のコマンドを順次実行するだけです。

cd ~
git clone git://git.drogon.net/wiringPi
cd wiringPi
./build

 WiringPi がインストールされたか、gpioコマンドでバージョンを確認してみましょう。

pi@raspberrypi ~/wiringPi $ gpio -v
gpio version: 2.26
Copyright (c) 2012-2015 Gordon Henderson
This is free software with ABSOLUTELY NO WARRANTY.
For details type: gpio -warranty

Raspberry Pi Details:
Type: Model 2, Revision: 1.1, Memory: 1024MB, Maker: Sony

 上記の様に gpio のバージョン情報が表示されればインストールは正常に行われています。

 さて、ではこの状態で先程のファイル操作と同じことをしてみます。

gpio -g mode 25 out
gpio -g write 25 1

 これだけです。-g オプションは WiringPi のページ によると、WiringPi のピン番号ではなく、BCM_GPIOのピン番号で指定を行うことを明示するためのオプションだそうです。

 ここで、「WiringPi のピン番号とは?」と思った方は、

gpio readall

 コマンドで各ピン番号の対比を見てみてください。

 そうすると、PHP でこのコマンドを叩けば、やはりGPIOの操作が可能です。

sudo vi gpio_test2.php
------------------------------------
<?php
exec("gpio -g mode 25 out");
exec("gpio -g write 25 1");

 となります。ただ、execコマンドは少し処理が重いので使いどころ次第ですね。

PHP用のライブラリを利用する

 PHP 用の GPIO ライブラリも複数ありますが、最有力なのはWiringPi-PHPでした。ところが、このWiringPi-PHP、どうもまだ Raspberry Pi 2 Model B には対応していないようです。Model B+ で動作したコードが2Bでは動作しませんでした。

 Raspberry Pi 2 は CPU の変更により GPIO のアドレスが変更になったそうで、githubにあるWiringPi-PHP のコードはこれにまだ対応していないようです。 WiringPi の方は対応済みとなっていて、WiringPi-PHP はこのラッパーですから少しコードを読めば対応できると思います。あまり長引くようなら対処法を調べてみたいと思います。

(2016/08/10追記 現在、WiringPi-PHP は Raspberry Pi 2 及び 3 に対応しています。この記事の最後に、利用方法を追記しました。)

(2015/06/14追記 この記事の最後にWiringPi-PHPを使えるようにする方法を追記しました)

(2016/05/07追記 2016年の3月に、新しいWiringPi-PHPのパッケージが GitHub で公開されました。Pi2、及び Pi3 でもコンパイルしてWiringPi のフル機能を使えるようになりました!)

 では別のライブラリですが、php-gpio というのがあります。

 こちらは WiringPi-PHP よりもずっと簡単な作りで、原理としては最初のファイル操作をそのまま行うライブラリのようです。

 インストールは、現在の PHP でスタンダードになりつつある composer を使うようです。

 まず、composer のインストールですが、

cd /var/www
sudo wget http://getcomposer.org/composer.phar

 で、composer.phar をダウンロードします。そうしたら、この composer.phar を使って、php-gpio のパッケージをインストールします。

sudo php composer.phar create-project --stability='dev' ronanguilloux/php-gpio /var/www/php-gpio

 これで、/var/www/ ディレクトリに php-gpioプロジェクトが作成され、パッケージがインストールされました。あとはPHPコードでこのディレクトリのなかの vendor/autoload.php を require すれば GPIO操作が行えるようです。

 実際にやってみましょう。

cd /var/www/html/
sudo vi gpio_test4.php
------------------------------------
<?php
require '/var/www/php-gpio/vendor/autoload.php';
use PhpGpio\Gpio;

$gpio = new GPIO();
$gpio->setup(25, "out");
$gpio->output(25, 1);

となります。

 こちらのライブラリが Raspberry Pi 2 でも問題なく動作したのは、前述したとおり、ファイル操作による GPIO 操作を行っていたからですね。より簡単な実装の物の方が、汎用性が高かったようです。ただ、こちらは PWM 信号のインターフェイスが実装されていません。(PWM信号とは極めて短い間隔でHIGHとLOWを切り替える信号で、アナログ信号のように1と0だけでない中間の値を表現する事等につかわれます)

 ですから、本当にGPIOをフル活用したければ、やはりWiringPi-PHPの対応が待たれます。

別のプログラムでコードを書き、PHPで呼び出す

 極論を言えば、全てを PHP コードで書く必要などありません。WiringPi-PHP がつかえなくても、Pythonのライブラリである WiringPi2-Python は使えるのですから、Python で書いて、それを PHP から呼び出せばよいわけです。

 簡単な例として、以下のようなプログラムを試してみましょう。

sudo vi python.py
-------------------------------------
print "Python"
sudo vi call.php
-------------------------------------
<?php
echo "この文字列は " . exec("sudo python python.py") . "からの文字列です。\n";

 さあ、実行してみましょう。

sudo php -q call.php

pi@raspberrypi /var/www/html $ sudo php -q call.php
この文字列は Pythonからの文字列です。

 この研究室ページの 赤外線リモコン信号受信・送信 で紹介しているプログラムはC言語で書かれていますが、これをPHPから上記と同様に呼び出して動作させることが可能です。(この場合は、C言語のプログラムからの echo を確認するため、system()コマンドを用いた方が良いでしょう)

 冒頭で紹介した「Raspberry Pi で学ぶ電子工作」には Python のコードが沢山ありますので、1からPHPで書き直そうとせずに、必要なところだけそのまま流用する、という使い方も一つの方法かと思います。

WiringPi-PHPを使う

2016/05/07 追記 2016年の3月に、新しいWiringPi-PHPのパッケージが GitHub で公開されました。Pi2、及び Pi3 でもコンパイルしてWiringPi のフル機能を使えるようになりました! 以下の操作は不要です。普通にコンパイルしてインストールしてください。この記事の末尾に簡単なインストール方法の説明と使い方を追記しました。こちらからどうそ

(2015/06/14 追記)

 WiringPi-PHP を使う方法についてですが、github にあるWiringPi-PHP のコードは前述の通り古いもので、Raspberry Pi 2 では正しく動作しないようです。これは、WiringPi-PHP のディレクトリ内にある wiringPi のコードが古いもので、コンパイル時にこれを利用しているからです。

 ですから、WiringPi-PHP ディレクトリ内の wiringPi のソースコードを新しい物に替えれば Raspberry Pi 2 に対応させることができます。

 まず、念のためWiringPi-PHP の中の古い wiringPi を念のためバックアップします。

cd WiringPi-PHP
mv WiringPi WiringPi-back

 次に、この記事の上の方でダウンロードしてあった wiringPi を WiringPi-PHP ディレクトリにコピーします。wiringPi は小文字で始まりますが、WiringPi-PHP 内のwiringPi ディレクトリは大文字で始まっています。コンパイル情報をあまりいじらなくてよいように、コピー時にリネームしてしまいます。

cd ../
cp wiringPi WiringPi-PHP/WiringPi

 これでコンパイルすればよさそうですが、どうやら新しい wiringPi ではいくつかのメソッドが追加されたかあるいは記述場所が移動しているようで、build エラーが発生してしまいます。具体的には、softToneとsoftPwmで、これらをbuild.shに追加する必要があります。( ‘ はバッククオートです)

cd WiringPi-PHP
sudo vi build.sh
--------------------------------
mkdir build
cd build

gcc ‘php-config --includes‘ -fpic -c ../wiringpi_wrap.c ../WiringPi/wiringPi/wiringPi.c ../WiringPi/wiringPi/wiringShift.c ../WiringPi/wiringPi/wiringSerial.c ../WiringPi/wiringPi/piHiPri.c ../WiringPi/wiringPi/softPwm.c ../WiringPi/wiringPi/softTone.c

gcc -shared wiringpi_wrap.o wiringPi.o wiringSerial.o piHiPri.o wiringShift.o softPwm.o softTone.o -o wiringpi.so

 それぞれ、

  • ../WiringPi/wiringPi/softPwm.c ../WiringPi/wiringPi/softTone.c
  • softPwm.o softTone.o

が追加コードです。

 後は github の記述通り、ビルドしてインストールするだけです。

./build.sh
sudo ./install.sh

 ビルドに失敗した場合は、mkdir build で作成されている build ディレクトリを rm -rf build で削除すれば何度でもやり直せます。

 これで、Raspberry Pi 2 でもWiringPi-PHP が利用できるようになります。

 ただし、先ほど追加した softTone と softPwm のラッパーメソッドはWiringPi-PHP には追加されていません。

 このため、これらを利用したい場合には WiringPi-PHP 内の php_wiringpi.h と wiringpi_wrap.c に、softTone と softPwm のラッパーファンクションを別途、追加する必要があります。

WiringPi-PHP の簡単な使い方

2016/08/10追記。

WiringPi-PHP のインストールは GitHub をご覧頂ければわかりますが、非常に簡単です。

(とりあえず、ユーザーのホームディレクトリに戻る)

cd ~

以下で、パッケージを GitHub からクローンしてきます。

git clone --recursive https://github.com/WiringPi/WiringPi-PHP.git

そして、ソースコードをコンパイルするため、ディレクトリ内に入ります。

cd WiringPi-PHP

ディレクトリ内に入ったら make した後、インストールします。

make

make install

インストールしたら、debian 系の Linux では、/etc/php5/mods-available/ 内に PHP の設定ファイルである .ini ファイルを作成します。

sudo vi /etc/php5/mods-available/wiringpi.ini

内容は以下です。

extension=wiringpi.so
wiringpi.pinmaptype=[PINS|GPIO|USER]

あとは、この wiringpi.ini を実際の動作時に読み込むよう /etc/php5/cli/conf.d/ と /etc/php5/apache2/conf.d/ 内にシンボリックリンクを作成するのですが、パッケージで入手した PHP 5.4 以降では、php5enmod という命令を使って自動でこのシンボリックリンクを作成してくれるようです。

sudo php5enmod wiringpi

それぞれの conf.d 内に 30-wiringpi.ini というシンボリックリンクが作成されているのを確認して下さい。(なお、先頭の 30 は読み込む順番のレベルなので、場合によっては別の数字かもしれません)

上記でなくても、次のようにすれば全く同じ意味になります。もし作成されない場合は、次のようにして手動でシンボリックリンクを作成して下さい。

sudo ln -s /etc/php5/mods-available/wiringpi.ini /etc/php5/cli/conf.d/30-wiringpi.ini

sudo ln -s /etc/php5/mods-available/wiringpi.ini /etc/php5/apache2/conf.d/30-wiringpi.ini

なお、GitHub では、apache から GPIO を操作するため、

sudo adduser www-data i2c
sudo adduser www-data spi
sudo adduser www-data gpio

を実行しておくと良いと書いてありますが、visudo を使って www-data(apache2 の debian系でのユーザー名)を sudoers に登録してあればその必要は無いと思います。

このようにシンボリックリンクを作成したら、apache について再起動をおこなって、WiringPi-PHP を有効にして下さい。

sudo service apache2 restart

WiringPi-PHP で Lチカ

さて、では WiringPi-PHP を PHP から使ってみます。今回は CLI(コマンドライン・インターフェイス)で Lチカをしてみましょう。

GPIO 25 番の先に 330Ωくらいの抵抗をつなぎ、その先に LED のアノード(長い脚の方)を繋ぎます。LED のカソード(短い脚の方)は GND に繋いで下さい。

以下のようなプログラム led_on.php を書きます。

sudo vi led_on.php
<?php

// GPIO セットアップ
wiringPiSetupGpio();

// LEDピンのモード設定(0: 入力、1: 出力、2: PWM)
pinMode(25, 1);

// 指定のピンを HIGH に設定(0: LOW、1: HIGH)
digitalWrite(25, 1);

これで保存して閉じた(viエディタでは、Shift + ZZ)ら、実行してみます。-q は、保存してあるPHP プログラムファイルを実行するためのオプションです。

sudo php -q led_on.php

どうでしょう? LED は点灯したでしょうか?

点灯したら消す必要がありますね。

sudo vi led_off.php
<?php

// GPIO セットアップ
wiringPiSetupGpio();

// LEDピンのモード設定(0: 入力、1: 出力、2: PWM)
pinMode(25, 1);

// 指定のピンを LOW に設定(0: LOW、1: HIGH)
digitalWrite(25, 0);

実行して、LED が消えることを確認しましょう。

sudo php -q led_off.php

なお、これらの動作を一つのプログラムで行う場合、wiringPiSetupGpio() と pinMode() については最初に 1回行っておくだけで、出力の HIGH、LOW 毎に行う必要はありません。

WiringPi-PHP で 圧電スピーカーをつかった PWM 信号のテスト

もし圧電スピーカーをお持ちでしたら次のように PWM をためしてみることも出来ます。

PWM とは、極めて短い間隔で HIGH と LOW を繰り返し切り替えることでデジタル信号(HIGH と LOW の2つの状態しか存在しない)でありながらアナログ(無段階の階調が存在する)を表現することができる制御方式です。

新しい Raspberry Pi では PWM 出力を行えるピンは 2 本あり、デフォルトでは GPIO 18 と GPIO 19 となっているようです。(古い Raspberry Pi では GPIO 18 の 1 本のみでした)

ここでは、GPIO 18 と GND を圧電スピーカーに繋ぎました。圧電スピーカーの定格電圧にもよりますが、大抵は抵抗等は特に必要ないでしょう(Rapberry Pi の GPIO は 3.3Vです)。

sudo vi beep.php
<?php

// GPIO セットアップ
wiringPiSetupGpio();

// 圧電スピーカー用ピンのモード設定(0: 入力、1: 出力、2: PWM)
pinMode(18, 2);

// PWM信号を出力(390Hz)
pwmWrite(18, 390);

// 0.5秒待つ(390Hzで鳴り続ける。usleep の単位はマイクロ秒。sleep() メソッドでは単位は秒になる)
usleep(500000);

// beep 音を止める
pwmWrite(18, 0);

では実行してみましょう。

sudo php -q beep.php

0.5秒の間、甲高い音が鳴ったかと思います。この PWM 信号を使うことで、モーターなどの制御を行うことが出来るようになります。

なお、このように PWM 信号を利用すると、アナログスピーカーを併用できないようです。新しい Raspberry Pi では HDMI からの音声出力が使えるのでそちらを利用するようにしても良いですが、HDMI は音の立ち上がりが悪く、当サイトで紹介している 音声合成による発声には向きません。

この場合は USB スピーカーを利用したら良いのではないかと思いますので、後日、USB スピーカーを調達してテストしてみようと思います。

WiringPi-PHP の圧電スピーカーで音楽を奏でる

次は、圧電スピーカーで音楽を奏でてみましょう。WiringPi には softToneWrite() という、プログラム制御で音階用の PWM 信号を出力する命令があります。先ほどの pwmWrite() はハードウェア PWM 信号なので、Raspberry Pi の状態にかかわらず同じ周期の信号が出力できますが、この softToneWrite() は、それを実行する時の Raspberry Pi の CPU 負荷によって、間隔が長くなったりします。ですから、緻密さを要求される場面に利用するべきではありません。

その代わり、プログラムで PWM 信号を出力しているため、どの GPIO ピンからでも出力できます。

さて、プログラムです。

sudo vi tone.php

今回は GPIO 23(Raspberry Pi の16番ピン)から出力してみます。圧電スピーカーの端子を GPIO 23 と GND に繋いで下さい。

まず、softTone を使うピンの設定は softToneCreate() です。

<?php

// GPIO セットアップ
wiringPiSetupGpio();

// 圧電スピーカー用ピンのモード設定
softToneCreate(23);

// PWM信号を出力(ド=262Hz)
softToneWrite(23, 262);

// 0.5秒待つ(262Hzで鳴り続ける。usleep の単位はマイクロ秒。sleep() メソッドでは単位は秒になる)
usleep(500000);

// beep 音を止める
softToneWrite(23, 0);

実行してみましょう。

sudo php -q tone.php

少し低めの beep 音が鳴ったでしょうか?

なお、音階と周波数|MyPRISM さんのページで、他の音の周波数も調べることができます。

WiringPi サイトの Software Tone Library のページの API リファレンスを見ると分かりますが、softToneWrite() の第二引数である周波数は、int型、つまり、整数型のみです。ですから、本来ドは 261.62Hz のようですが、四捨五入して 262Hz として出力を行いました。

音階と周波数|MyPRISM さんのページを見ながら、いろいろな音を奏でてみてください。

なお、WiringPi-PHP は WiringPi のラッパーですので、WiringPi の Function (API) の説明 が、そのまま利用できるはずです。

PHP での GPIO 操作については以上です。

この記事へのコメント

※現在コメントはMarkdown記法が強制です。>>Markdown の書き方


この記事に返信

このコメントに返信