pythonのwiringpiを用いた記事になります。
雑談
以前、ラジコンが完成した!と騒いでいたことがある。
問題のラジコン
コントロール画面
正直に言おう。
このラジコン、ステアリングのタイヤを右に曲げるか、左に曲げるかを制御できるのだが、一度曲げたら最後、タイヤを真っ直ぐに戻すことができないのである。
というのも、サーボモータの制御をほとんど理解しないまま、固定の角度が曲がるようにコントロールしていたから。
なので、そろそろサーボモータの制御に向き合いたいと思う。
サーボモータの制御
この記事を書くにあたっては、以下の記事を参考にさせていただきました。
正直なところ、参考記事のほうがわかりやすいのは内緒。
Raspberry Piでブラウザからサーボモータをちゃんと制御する | MUDAなことをしよう。
コンピュータ | Myブーム & My備忘録
とりあえずコード
まずは、サーボモータをwiringpiで制御するため、未完成ではあるが、NewServoMotorクラスを書いた。
class NewServoMotor:
'''
サーボモータを制御するクラス
少しだけ仕組みを理解した上で、かいてみる
このコードは未完成。
'''
def __init__(self, servo_motor_pin1):
self.motor_pin1 = servo_motor_pin1
pi.wiringPiSetupGpio()
pi.pinMode( self.motor_pin1, pi.GPIO.PWM_OUTPUT )
pi.pwmSetMode( pi.GPIO.PWM_MODE_MS )
pi.pwmSetClock(375)
def handle(self,duty):
pi.pwmWrite(self.motor_pin1, duty)
NewServoMotorクラスのコンストラクタは、wiringpiでGPIO制御をするのに必要な設定をしている。
なので、このへんの説明はとくにない。
ただ、「pwmSetMode」[pwmSetClock」というDCモーターを制御する際には見られない関数が見受けられる。
これは、後述する、PWM(Pulse Width Modulation、パルス幅変調)とよばれる制御をするのに必要な設定。
肝心のサーボモータの角度を制御するための、handleメソッドは、pwmWrite関数を呼ぶシンプルなメソッド。
LEDやDCモータあれば、digitalWrite関数を使っていたけれども、サーボモータではPWMを使って制御することになる。
LEDやDCモーターのときに使ってた関数
pi.digitalWrite(GPIO番号,0 or 1)
サーボモータ制御で使う関数
pwmWrite(GPIO番号、 duty比)
次に、PWMとpwmWrite関数の引数であるduty比というものについて見てみる。
PWMとduty比
PWM(Pulse Width Modulation、パルス幅変調)とは周期的に、電圧がかかっている状態とかかっていない状態を繰り返す、信号方式とのこと。
PWMの特徴を知るためにも、digitalWrite関数と対比してみる。
dititalWrite関数で1を設定した状態
以下の雑な絵をみてほしい。
縦軸に電圧、横軸に時間をおいたグラフである。
digitalWrite関数で1を設定した状態を表している。
pi.digitalWrite(GPIO番号, 1)
dititalWrite関数で0を設定した状態
そして以下は、digitalWrite関数で0を設定した状態を表している。
pi.digitalWrite(GPIO番号, 0)
何が言いたいかというと、digitalWrite関数では、電圧がかかっている状態とかかっていない状態の2値のみの状態のみ表現することができるという点。
pwmWrite関数のイメージ
一方、pwmWrite関数は、以下のイメージになる。
pwmWrite(GPIO番号、 duty比)
上記のように、電圧がかかっている状態とかかっていない状態を繰り返す方式となる。
なんで、こんなことしているの?という点だけれども、本当にやりたいことは以下の微妙に電圧がかかっている状態をつくりたいんだと思う。
でも、電圧がかかっているか、かかっていないか状態しかつくりだすことができないので、擬似的に一定の期間内で電圧をかけたり、やめたりを繰り返して微妙に電圧がかかっている状態を表現しているみたい。
duty比とは
次に、pwmWrite関数のduty比について触れる。
pwmWrite(GPIO番号、 duty比)
duty比とは、とある周期の間に、電圧がかかっている状態がどれくらいあったかを表すものである。
下の図でいえば、周期が20ミリ秒の間に、青線の状態がどれくらいあったのか、ということを表す。
具体的な数字をいれてみると、以下のようになる。
duty比が高くなればなるほど、電圧がかかっている状態が長くなり、逆にduty比が低いということは、電圧がかかっている状態が短いということになる。
(もしかしたら20ミリ秒の間で繰り返すといよりかは、20ミリ秒の間に電圧がかかっている状態が一定期間あって、以降はかからないというイメージの方が正しいかもしれない。)
サーボモータの仕様
ここで、そろそろサーボモータの仕様をみてみる。
参考にするサーボモーターはSG-5010。よく使うSG90も同じ仕様みたいなので、どちらでもいい。
マイクロサーボ SG−5010: サーボ 秋月電子通商 電子部品 ネット通販
秋月電気通商に記載されている仕様をみると、以下を確認することができる。
・PWMサイクル:20mS
・制御パルス:0.5ms~2.4ms
これを、日本語にすると以下の仕様になる。
- 20msの周期の中で、0.5msのパルス信号を送るとサーボモータは-90度になる
- 20msの周期の中で、2.4msのパルス信号を送ると、サーボモーターは90度になる
もしかしたら、0.5msと2.4msのときでサーボモータの向きが逆になることもあるかもしれないけれども、とりあえす仕様としてはこんな感じみたい。
これを図にすると、以下のようなイメージである。
20msの間に青い線の合計が0.5msのとき、サーボモーターは-90度になる。
つまり、duty比は、2.5%のときサーボモータは-90度になる。
0.5ms ÷ 20ms = 0.025 = 2.5%
同様にduty比が12%のときにサーボモーターが90度になる。
2.4ms ÷ 20ms = 0.12 = 12%
角度を0度にしたいときは、0.5msと2.4msの間である1.45msで考えればよい。
1.45ms ÷ 20ms = 0.0725= 7.25%
pwmWrite関数に設定する値
さて、ようやくpwmWrite関数に設定するduty比をなんとなく理解することができた。
ただ残念なことに、サーボモータを-90度にするときは、duty比2.5%だから、こうすればいいんじゃ!と以下のようにするとうまくいかない。
pwmWrite(GPIO番号、 2.5)
というのも、pwmWrite関数のduty比は0〜100という値ではなく、0〜1024の値を取るとのこと。
なので、割合を1024の範囲に合わせてあげる必要がある。
ふとしたときにこの辺の計算ができなくて焦るのけれども、以下のように求めることができる。
2.5 : 100 = 知りたい値 : 1024
知りたい値 = 1024 × 2.5 / 100 = 25.6 ≒ 26
※pwmWriteのduty比はintなので、四捨五入した値を設定する。
まとめると以下のようになる。
サーボの仕様 |
duty比 |
pwmWriteに設定する値 |
-90度 |
2.5 |
26 |
0度 |
7.25 |
74 |
90度 |
12 |
123 |
長くなってしまったので、実際にサーボモーターを動かすのは次回に回したいと思います。
次回
www.tohuandkonsome.site