■サーボを動かす
サーボを動かしてみましょう。サーボの出力軸(白いギザギザのところ)は通常0°~180°ぐらいの範囲で回転しますが、その位置はサーボの容器に対して絶対的に決まっています。そのため出力軸の回転位置を気にせずに適当にロボットを組み立ててしまうと、出力に取り付けられた部品が思い通りに動いてくれません。まずはサーボの出力軸を90°(センター)の位置に停止させるプログラムを作ります。
USBケーブルがつながったPicoを基板に装着し、サーボ1個を0番サーボ用コネクタに挿してください。サーボ数個ぐらいはUSBの電源で駆動できますので、今はまだバッテリーは使いません。サーボのコネクターは逆向きに挿しても動きませんが壊れることはありません。中央のピンがプラス電源となっているためです。一方、バッテリーのコネクターは逆に取り付けるとマイコンが壊れますので間違えないでください。
電源スイッチはOFF側にしておきます。
*サーボを取り扱う際の注意
サーボは非常に精密なギアで構成されています。出力軸を回そうとして(「バックドライブ」と言います。)引っ掛かりがある場合に無理に回そうとするとギアを破損します。
ハードウェアの準備ができましたらプログラムを作っていきます。サーボを駆動するには信号線に連続的にパルスを与えてそのパルス幅(時間)で角度を指定します。PWMがそのパルスを発生する仕組みです。ファイル名は「servo1.py」とします。
リスト3-1 servo1.py
from machine import Pin, PWM
SV_FREQ = 50.0 # サーボ信号周波数
MAX_DUTY = 65025.0 # 周期内の分割数
MIN_SV_PULSE = 0.6 # 最小パルス幅 msec at 0°
MAX_SV_PULSE = 2.4 # 最大パルス幅 msec at 180°
# パルス幅を計算する関数
def get_pulse_width(angle):
pulse_ms= MIN_SV_PULSE + (MAX_SV_PULSE - MIN_SV_PULSE) * angle /180.0
x = (int)(MAX_DUTY * (pulse_ms * SV_FREQ /1000.0))
return x
servo0 = PWM(Pin(0)) # 0ピンにPWMを出す機能 servo0という名前
servo0.freq(50) # PWMの周波数は50Hz
servo0.duty_u16(get_pulse_width(90)) # 90度のPWMを出力
行のなかの「#」以下はコメントとなり、プログラム上無視されます。コメント以外のところで全角スペースなどを入れないように注意してください。
再生ボタンでプログラムを書き込むとサーボが動いて90°の位置(センター位置)で停止します。(新品のサーボを用いた場合はもともと90°の位置になっていて動かない場合があります。)
●プログラムの説明
通常のサーボ(アナログサーボ)では、10~20ミリ秒ごとに数ミリ秒幅のパルス信号を受けて制御されます。目標角度はパルスの幅で決まります。プログラムの最初で、パルス幅を計算するときに使う定数を定義しています。SV_FREQは周波数(1秒間に何回パルスを出すか)で、50Hzなので周期は20ミリ秒です。MAX_DUTYは1周期の時間分割数、MIN_SV_PULSE、MAX_SV_PULSEは最小、最大角度のときのパルス幅(ミリ秒)で、これは実測値です。
SV_FREQ = 50.0 # サーボ信号周波数
MAX_DUTY = 65025.0 # 周期内の分割数
MIN_SV_PULSE = 0.6 # 最小パルス幅 msec at 0°
MAX_SV_PULSE = 2.4 # 最大パルス幅 msec at 180°
「get_pulse_width()」はパルス幅を計算するための自作の関数です。最小値と最大値を用いて所定の角度のときのパルス幅を比例計算しています。
def get_pulse_width(angle):
pulse_ms= MIN_SV_PULSE + (MAX_SV_PULSE - MIN_SV_PULSE) * angle /180.0
x = (int)(MAX_DUTY * (pulse_ms * SV_FREQ /1000.0))
return x
最後の3行はサーボを使うための設定をしています。0番ピンにPWMを出力して「servo0」と名付け、その周波数は50、get_pulse_width()で計算したパルス幅(16ビットの値)を設定、となります。
servo0 = PWM(Pin(0)) # 0ピンにPWMを出す機能 servo0という名前
servo0.freq(50) # PWMの周波数は50Hz
servo0.duty_u16(get_pulse_width(90)) # 90度のPWMを出力
PWMの書式については
でPWMと入れて検索してみてください。
●練習問題
サーボを往復運動させてください。
リスト3-2 servo2.py
from machine import Pin, PWM
import time
SV_FREQ = 50.0 # サーボ信号周波数
# *** 省略(リスト4-3と同じ)***
servo0.duty_u16(get_pulse_width(60)) # 60度のPWMを出力
while True:# 繰り返し
servo0.duty_u16(get_pulse_width(60))# 60度のPWMを出力
time.sleep(1)# 1秒待ち
servo0.duty_u16(get_pulse_width(120))# 120度のPWMを出力
time.sleep(1)# 1秒待ち
「while True:」はその中身が繰り返し実行されます。
・サーボを60度の位置に設定
・1秒間停止
・サーボを120度の位置に設定
・1秒間停止
を永遠に繰り返します。
■デバッグの方法
サーボとは直接関係ありませんが、プログラムが思い通りに動かない時などに原因を調べる方法のひとつを紹介しておきます。先のプログラムに少し追加します。
リスト3-3 servo3.py
while True: # 繰り返し
servo0.duty_u16(get_pulse_width(60)) # 60度のPWMを出力
print('angle=60')
time.sleep(1) # 1秒待ち
servo0.duty_u16(get_pulse_width(120)) # 120度のPWMを出力
print('angle=120')
time.sleep(1) # 1秒待ち
このプログラムをメインボードに転送して実行すると、Thonnyのshellのボックスにprint( )に書いた内容が1秒ごとに出てくると思います。このように実行中のプログラムの状況を調べることができます。
以上で一応基板の動作確認はできたということにして、次からメカの組み立てを行います。
■オートスタート
現状ですと、USBケーブルを抜き挿ししてしまうとプログラムを実行するためにはもう一度実行ボタンをクリックする必要があることに気づかれたかもしれません。パワーオンでプログラムを実行するには、プログラムを「main.py」という名前でPicoに保存(新しいファイルを開いてプログラムの内容をコピーしてから)してください。
■バッテリー動作確認
ここでロボットを組み立てる前にバッテリーでの動作を確認しておきます。Picoに「main.py」を書き込んだ状態でバッテリーを接続(向きを間違えないでください 黒がGNDです)、電源スイッチを入れてサーボが動作することを確認してください。おかしいと感じたらすぐにスイッチを切って接続を調べます。バッテリーは初期状態で充電されています。
コメント