Raspberry Piでサーボを動かす方法は色々ある。ArduioやPICなどのマイコンを介して制御する方法もあるだろが、今回は、直接サーボを制御してみた。Raspbery PiのGPIOを操作できるモジュールが利用できる、Pyson、Javaなどを使ってもいいだろうし、WiringPi は、ArduinoのようにC言語からスマートにRaspbery PiのGPIOを操作できる。しかし、今回は、できるだけ生のBCM2835に触れたかったので、非生産的(?)なのは承知の上で、あえてこれらの既存のソフトは使わなかった。ただし、最初に紹介する方法では、BCM2835ライブラリだけ使わせてもらった。
最初の方法は、ソフトウェアでGPIOの出力を上げ下げする単純な方法である。サーボパックとは次のように接続した。
まず、ここからBCM2835ライブラリをダウンロード
http://www.open.com.au/mikem/bcm2835/次の手順でインストール
$ cd
$ tar zxvf bcm2835-1.12.tar.gz
$ cd bcm2835-1.12
$ ./configure
$ make
$ sudo -i
# cd /home/pi/bcm2835-1.12
# make check
# make install
# exit
Cソース servo.c
コンパイル
$ gcc -o servo servo.c -l bcm2835 -l rt
実行(中立位置を指定)
$ sudo ./servo 50
サーボをロック状態(一定位置に保持する)にしようとしても、モータがガタつく。ps axと打つと更にガタつく。信号を見ると、次のように、時には定格の2msを超えるジッタ(jitter)である。(映像)
予想はしていたが、この方法はカーネルモードではないし、そもそもリアルタイムOSではないので、当然デバイスドライバの活動や他のプロセスの挙動に影響される。実際には、このパルス幅の乱れは一瞬で単発的なので、サーボがそれに追従できず、モータのガタつきは信号で見るほどではない。サーボをロックしない用途など、許容できる用途はあるとは思う。
一方、PWMを使えばこのjitterの問題は解決できる。つまり、パルス生成をMPUのハードウェアに任せるわけである。BCM2835のGPIO18はALT5でPWM0の出力となる。PWM0はプルダウンされているので、絶縁も兼ねて、サーボとのインターフェースをフォトカプラ(TLP521)に変更した。
Cソース pwm.c
コンパイル
$ gcc pwm.c -o pwm
$ sudo ./pwm 50
上の図のように、他でどんなプロセスが動こうがパルス幅は微動だにしない。当然、サーボは完全にロックし、モーターの音は全く出なくなった。位置決めが重要な用途なら、こちらの方法がいいだろう。Raspberry Pi の回路図によると、PWMは、BCM2835自体には2チャンネルあるが、残念ながらピンヘッダには、今回使ったPWM0しか配線されていない。また、今回使ったPWM0ともう1つのPWM1は、それぞれヘッドフォン出力の左右のチャンネルに接続されている。Praspberry Piのヘッドフォン出力は、DACではなくて、簡易的にPWMとCRローパスフィルタによって構成しているのだ。ちなみに、BCM2835にはDACがあるのだが、Raspbery Piでは、それはコンポジット映像出力に使っている。