Raspberry Piでサーボ制御

Raspberry Piでサーボを動かす方法は色々ある。ArduioやPICなどのマイコンを介して制御する方法もあるだろが、今回は、直接サーボを制御してみた。Raspbery PiのGPIOを操作できるモジュールが利用できる、Pyson、Javaなどを使ってもいいだろうし、WiringPi は、ArduinoのようにC言語からスマートにRaspbery PiのGPIOを操作できる。しかし、今回は、できるだけ生のBCM2835に触れたかったので、非生産的(?)なのは承知の上で、あえてこれらの既存のソフトは使わなかった。ただし、最初に紹介する方法では、BCM2835ライブラリだけ使わせてもらった。

方法1

最初の方法は、ソフトウェアでGPIOの出力を上げ下げする単純な方法である。サーボパックとは次のように接続した。

まず、ここからBCM2835ライブラリをダウンロード

http://www.open.com.au/mikem/bcm2835/

次の手順でインストール

  1. $ cd
  2. $ tar zxvf bcm2835-1.12.tar.gz
  3. $ cd bcm2835-1.12
  4. $ ./configure
  5. $ make
  6. $ sudo -i
  7. # cd /home/pi/bcm2835-1.12
  8. # make check
  9. # make install
  10. # exit

Cソース servo.c

コンパイル

  1. $ gcc -o servo servo.c -l bcm2835 -l rt

実行(中立位置を指定)

  1. $ sudo ./servo 50

サーボをロック状態(一定位置に保持する)にしようとしても、モータがガタつく。ps axと打つと更にガタつく。信号を見ると、次のように、時には定格の2msを超えるジッタ(jitter)である。(映像

 

予想はしていたが、この方法はカーネルモードではないし、そもそもリアルタイムOSではないので、当然デバイスドライバの活動や他のプロセスの挙動に影響される。実際には、このパルス幅の乱れは一瞬で単発的なので、サーボがそれに追従できず、モータのガタつきは信号で見るほどではない。サーボをロックしない用途など、許容できる用途はあるとは思う。

方法2

一方、PWMを使えばこのjitterの問題は解決できる。つまり、パルス生成をMPUのハードウェアに任せるわけである。BCM2835のGPIO18はALT5でPWM0の出力となる。PWM0はプルダウンされているので、絶縁も兼ねて、サーボとのインターフェースをフォトカプラ(TLP521)に変更した。

Cソース pwm.c

コンパイル

  1. $ gcc pwm.c -o pwm
実行(中立位置を指定)
  1. $ sudo ./pwm 50

上の図のように、他でどんなプロセスが動こうがパルス幅は微動だにしない。当然、サーボは完全にロックし、モーターの音は全く出なくなった。位置決めが重要な用途なら、こちらの方法がいいだろう。Raspberry Pi の回路図によると、PWMは、BCM2835自体には2チャンネルあるが、残念ながらピンヘッダには、今回使ったPWM0しか配線されていない。また、今回使ったPWM0ともう1つのPWM1は、それぞれヘッドフォン出力の左右のチャンネルに接続されている。Praspberry Piのヘッドフォン出力は、DACではなくて、簡易的にPWMとCRローパスフィルタによって構成しているのだ。ちなみに、BCM2835にはDACがあるのだが、Raspbery Piでは、それはコンポジット映像出力に使っている。

2012年11月10日