2016/08/28

Raspberry Piでサーボモータ(SG90)を制御する

Raspberry Piの入門が一通り終わったので、何かを制御してみたくなった。

そこで、以前使用したことがある安価なサーボモータの角度制御してみた。
使用したサーボモータはみんな大好き「SG90」。
安価で扱いやすく、これで事足りる場合も多い。



今回必要なもの

  1. SG-90
  2. ジャンパワイヤ

SG90は安価で手に入れられるサーボモータ。1個400円程度で、数個まとめて売られていたりする。
それを3本のジャンパワイヤ(オス-メス)でRaspberry Piに接続する。



こいつね。


サーボモータ


サーボモータとは、回転軸の位置や速度を制御できるモータのこと。

サーボモータと言ってもトイ的なものから本格的にロボットの関節に使用されるものまで多種ある。
制御方法は共通の規格に対応しているものが多い。ただ、スペックによっては独自仕様を用意しているものもある。

また、サーボモータは意外と電力食いなので、注意が必要だ。
必要な電源電圧が大きいものが多く、Raspberry Piからの電力供給だけでは動作させるのが難しいものもたくさんある。
今回使用するSG90でも、環境によっては問題が起こる。
(実際に起こったので、それについても後ほど説明する)


PWM信号


制御に関してはPWM(Pulse Width Modulation)という信号制御で行うことが多い。
PWMとは、スイッチのON/OFFを一定時間ごとに繰り返すパルス波において、ONの時とOFFの時の比率によっていろいろな制御を行う手法。
ON/OFFを繰り返すと電圧波はこんな感じになる。



パルス波ですな。
このAの区間とBの区間の時間の比率であるDuty Cycleで制御を行う。

PWMは電源回路の電圧制御やシンセサイザーの倍音生成など、多岐にわたって使用される技術。
サーボではこれを角度制御を行う。


構成


構成は以下のようになっている。



直ざし!
ワイヤピンのオス部分をサーボのソケットに直でさした。意外とフィットしている。

PWM制御のサーボモータは、3線が出ているものが多い。
SG90の仕様を調べると、3線は次の構成となっている。
  • オレンジ線:PWM信号
  • 赤線:電源
  • ブラウン線:GND
となっている。
信号線には50HzのPWM信号で入力する。
また、電源、PWM信号は4.8V〜5.0Vとのこと。

ここでわかるかと思うが、Raspberry Piのピンは電源が5.0Vと3.3V、GPIOは3.3Vなので、電源はまあいいが、PWM信号は電圧が足らない。
本来ならこれは設計段階で信号電圧のために一計を案じるべきだが、信号電圧が足らないだけなので3.3Vあればいけるかな?と思い、とりあえず直ざしでやってみる。

モータ電源には5Vのピンと接続。モータGNDはGNDピンと、モータ信号線にはGPIO4と接続。


プログラム


GPIOからPWM信号を出したいんだが、これまでGPIO出力はON/OFFの方法だけ説明してきた。
ユーザランドのソフトウェアプログラマだったら、ONとOFFを切り替える間にSleepなどを挟んだら...と考えるかもだが、精度のいいSleepでないと高速で正確な周期でON/OFFを切り替えることはできない。
その辺りはライブラリが用意されているので、難しいところはライブラリに頼ろう。
「Raspberry Piのことはじめ」で使用したGPIOライブラリはPWMも実装されているので、これを使用する。

今回書いたプログラムはこんな感じ
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)

gp_out = 4
GPIO.setup(gp_out, GPIO.OUT)
servo = GPIO.PWM(gp_out, 50) 

servo.start(0.0)

servo.ChangeDutyCycle(2.5)
time.sleep(0.5)

servo.ChangeDutyCycle(12.0)
time.sleep(0.5)

servo.ChangeDutyCycle(2.5)
time.sleep(0.5)

GPIO.cleanup()

簡単に解説。

gp_out = 4
GPIO.setup(gp_out, GPIO.OUT)
servo = GPIO.PWM(gp_out, 50) 
まず、gp_out変数はどのGPIOピンを使うかを示す。今回はGPIO4を使用する。
PWM関数は信号制御クラスPWMのインスタンスを作成する関数で、引数でピンの指定番号と周期を指定する。
今回はGPIO4から50Hzの信号なので、上記のように指定する。

servo.start(0.0)
信号出力開始。引数はDuty Cycle。Duty Cycleは0.0 - 100.0 のパーセンテージで指定する。

SG90の制御に使用するパルス幅はいろいろなWeb上の資料で間違って記載されてるらしく、おかげで全然制御できずかなりはまった。
実際は0.5ms-2.4msの間で制御する。パルス全体は50Hzなので20msの幅があるから、2.5% - 12.0%のDuty Cycleで制御する。
対応する角度は-90度-90度なので、Duty Cycleで2.5を指定したら-90度に軸が移動する、というわけ。

角度は後から指定するので、とりあえず0.0を指定しておく。

servo.ChangeDutyCycle(2.5)

ここでDuty Cycleを指定することで、角度指定を行っている。
このプログラムでは、-90度→90度→-90度と角度制御する。

軸が指定の角度に移動するのには時間がかかるので、sleepを忘れずに。


テスト


実際に動かしてみたら、うまく動かなかった。
なんだか陸にあげられた魚みたいな動きをしていた。

こういう電子部品が動かない際に、まず疑うべきは電圧、電流不足。
案の定、Raspberry Piに繋いているアダプタを、電流値の高いものに変更したらちゃんと動作した。
具体的には5V-2Aのものに変更した。(5V-1.2Aなどではうまく動かなかった)

信号電圧は3.3Vでも大丈夫みたい。
信号入力では、ある程度の電圧があれば5Vとみなす、という仕組みが多いので、おそらくそれで大丈夫なんじゃないかと思う。


こんなシンプルなサーボでも電圧に右往左往されるんだから、本格的なサーボをちゃんと使う際には、電源設計はちゃんとやったほうがいいんだろうな。

0 件のコメント:

コメントを投稿