はじめに
ラズパイPicoでサーボを回した時の思い出を残す
参考
ここに書いてた。感謝感謝。
基本的な構成
構造的には電源(VBUS)と1つのGPIOピン(今回のケースではGP15)とつながっていたらOKのようです。
回路図
回路はコチラ。
後で気づいたけど、2つのGNDに配線しているけど、上のGNDにはどこともつながってないので多分いらない。
逆に上のGNDにサーボ側のGNDをつなげるのであれば下のGNDはいらない。
実装コード
これ書くだけでOK。
import machine
import utime
servo = machine.PWM(machine.Pin(15))
servo.freq(50)
def interval_mapping(x, in_min, in_max, out_min, out_max):
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
def servo_write(pin,angle):
pulse_width=interval_mapping(angle, 0, 180, 0.5,2.5)
duty=int(interval_mapping(pulse_width, 0, 20, 0,65535))
pin.duty_u16(duty)
print('angle={}, pulse_width={}, duty={}'.format(angle,pulse_width,duty)) # ←ココはデバグ用なのでなくても動く
while True:
print('forward swinging')
for angle in range(180):
servo_write(servo,angle)
utime.sleep_ms(20)
print('reverse swinging')
for angle in range(180,-1,-1):
servo_write(servo,angle)
utime.sleep_ms(20)
実行結果はコチラ。実際に動いている動画は取れなかったけど、ログが取れたのでよかった。
コードの簡単な解説
servo_write()が実際にサーボを回している箇所。
厳密に言うと、servo_write()内にある、pin.duty_u16()で動いている。
pin(今回のケースでいうとGP15)の情報にduty値を与えたら、サーボは動く。
dutyはどうやって出すの?
dutyは0~65535の範囲で指定してやる必要がある。
じゃあ、duty値をどうやって導くのか?っていうと、
より、↓↓の画像より、サーボは0~180°の範囲で動作する。
で、この動作角度は20msの周期(=50Hz)に対してPulse widthを0.5ms~2.5msの範囲でONにしたときの時間で決まる。
なので、、、50Hzのデューティ比を算出して、これを元に0~65535に置き換えたら、duty値が割り出せるって話。
そこで、↑↑の換算式を関数化したものがinterval_mapping()
このモジュールはホントよくできてるので別の場所でも使わせてもらおう。
で、最終的にはどんな動作をするコード?
関数の説明がおわったのでメイン動作なんだけど、それはこのwhile Trueで無限ループしてるところ。
最初は0→180へ向かって1°ずつ20ms間隔でサーボを動かす。
で、180°まで移動したら、次は180→0へ向かって同様にサーボを動かす。というプログラム。
while True:
print('forward swinging')
for angle in range(180):
servo_write(servo,angle)
utime.sleep_ms(20)
print('reverse swinging')
for angle in range(180,-1,-1):
servo_write(servo,angle)
utime.sleep_ms(20)
おわりに
今回紹介したサイトは、サーボ以外にもほかのモジュールの使用方法についても説明があって
しかもすごいわかりやすいの今後も参考にしていこう。