はじめに
RaspberryPi Pico / Pico Wで、サーボモーター(ラジコンサーボ)の「SG90」を使う方法を解説したいと思います。言語はMicroPythonを使います。
RaspberryPi Pico / Pico Wともにピン配列は同じなので、どちらのボードを使う場合でも記事の配線方法とプログラムがそのまま使えます。今回の記事ではPico Wを使って解説します。
ノーマルのRaspberryPiで動かす方法も解説しているので、RaspberryPi + PythonでSG90を動かしたい。という方はこちらの記事をご覧ください。
~ この記事の内容 / Contents ~
環境
この記事で使用する環境は以下の通りです。
環境 | バージョンなど | 備考 |
開発用PCのOS | Windows11 | Windows10でもOKです |
言語 | MicroPython | |
開発環境 Thonny | 3.3.13 | |
ボード | RaspberryPi Pico |
サーボモーター(ラジコンサーボ) SG90
今回の記事で使用するサーボーモーター(ラジコンサーボ)「SG90」です。
ラジコンサーボは、モータ・ギアボックス・制御基板などが1つのケースにまとめられたモーターで、ラジコンカーのステアリング・ラジコン飛行機の翼の操作・ホビーロボットの関節軸など、1回転中の特定の範囲を繰り返し動かすために使います。
配線も「電源・GND・PWM信号」の3本だけです。
SG90の電源は4.8Vですが、PWM信号は3.3Vでも反応してくれるので、RaspberryPiシリーズからPWM信号を直接接続できます。
項目 | スペック |
電圧 | 4.8V |
動作範囲 | 180度(±90度) |
トルク | 1.8kgf・cm |
付属品 | サーボホーン3種 |
サーボ固定ねじ×2、ホーン固定ねじ×1 |
RaspberryPiとの接続
RaspberryPi Pico WとSG90を以下のように接続します。
ピン番号 | RaspberryPi Pico 側 | サーボモータ |
34 | GPIO28 | PWM |
38 | GND | GND (電池と共通化します) |
— | 電池+ | 電源 |
— | 電池 − | GND (電池と共通化します) |
Pico W ピンアサイン(Pin-Out)
※ Pico W公式サイトより引用
Picoピンアサイン(Pin-Out)
※ Pico公式サイトより引用
使用する部品
Pico W 本体
Raspberry Pi Pico W本体です。技適対応品かどうか心配…という方は、以下のページで出品者を「共立エレショップAセレクト」(国内の有名ショップ)にして購入してください。
電池ボックス
電源に使う電池用ボックスです。スイッチ付きで何かあってもすぐに電源を切れるので、安心して工作することができます。
記事では単4を使っていますが、容量の大きい単3タイプをお勧めします。単3でも単4でも電圧は変わりません。
電池ボックス(単4)
記事で使っている単4を3本使うタイプはこちらで購入しています。
エネループ
使い捨ての乾電池もいいですが、エネループなら4本充電時の電気代が約1円。モーター・ポンプなどの電池が消耗しやすい実験・工作におすすめです。
※ はじめて使う方は充電器とのセットがおすすめです
ジャンパワイヤ(自作用)
キットだと丁度いい長さや、色がない。という方は以下の配線がおすすめです。ジャンパワイヤとほぼ同じ固さの配線なので、切って曲げるだけで理想のジャンパワイヤが作れます。
プログラム概要
今回のプログラムの概要は以下の通りです。
- PWMの設定をする。
- サーボモータを動かす。
実行結果
後述するプログラムの実行結果です。サーボモータが「-90度」「0度」「+90度」の順で、3回動作します。
全体コード
全体コードは以下の通りです。詳細な内容は後述する「コードのポイント」で解説します。
import machine
import time
from machine import PWM
# GP28をPWMとして使います
pwm = PWM(machine.Pin(28, machine.Pin.OUT))
# サーボが動作可能な範囲です
ANGLE_RANGE = 180
# サーボに指定するPWMの時間の範囲です
TIME_RANGE = 1.9
# サーボに指定できる最小の時間です
MIN_TIME = 0.5
# サーボのPWMの周期時間です
CYCLE_TIME = 20.0
#
# 角度⇒PWM信号に変換する関数です
#
def moveServo(pwm, angle ):
# 入力角度のチェックです。±90以外はエラーにします
if angle < -90 or angle > 90 :
return False
# 指定角度を、0~180の表現に変えます
angle = angle + 90
# 指定角度を、全体(180度)中の割合に変換します
percent = angle / ANGLE_RANGE
# 割合を時間の範囲に適応して、指定角度を動かす時間を計算します
addTime = TIME_RANGE * percent
# 時間範囲は0.5から始まるので0.5に指定角度の時間を足します
time = MIN_TIME + addTime
# 指定角度の時間を、20msecの周期中の割合(%)に変換します
ratio = time / CYCLE_TIME
# 16bit(0~65535)の値(整数)に変換します。
ratio = (int)(65535 * ratio)
# 動作実行します
pwm.duty_u16(ratio)
return True
#
# メイン処理
#
#周期を1秒間に50回(50Hz)に設定します
pwm.freq(50)
# -90度、0度,90度に3回動かします。
for i in range(3):
# -90度
moveServo(pwm,-90 )
print("-90")
time.sleep(2)
# 0度
moveServo(pwm, 0)
print("0")
time.sleep(2)
# 90度
moveServo(pwm, 90)
print("90")
time.sleep(2)
コードのポイント
周期の設定
PWMのピンと周波数を設定します。
秋月電子さんで公開されている「SG90のデータシート」に「50Hz」と記載されているため、PWMの周波数を50Hz(1周期20msec)に設定します。
#周期を1秒間に50回(50Hz)に設定します
pwm.freq(50)
Duty比の作成
サーボ角度はPWMのDuty比を変えることで指定できます。角度の変更は何度も実行する処理のため、関数にまとめてメイン処理側のコードが簡潔にしています。
処理内容は以下の通りです。
① 角度を割合に変換
計算を楽にするため、「SG90」が動作できる範囲である±90度を、90度ずらして、0~180度の範囲(表現)に変換します。
次に、変換後の入力角度を、SG90の動作範囲(180度)で割り、入力角度が動作範囲対してどの程度の割合であるかを計算します。
#
# 角度⇒PWM信号に変換する関数です
#
def moveServo(pwm, angle ):
# 入力角度のチェックです。±90以外はエラーにします
if angle < -90 or angle > 90 :
return False
# 指定角度を、0~180の表現に変えます
angle = angle + 90
# 指定角度を、全体(180度)中の割合に変換します
percent = angle / ANGLE_RANGE
# 割合を時間の範囲に適応して、指定角度を動かす時間を計算します
addTime = TIME_RANGE * percent
# 時間範囲は0.5から始まるので0.5に指定角度の時間を足します
time = MIN_TIME + addTimeGLE_RANGE
② 角度から時間に変換
前述した「入力角度の割合」を使って、PWMのDuty(どれだけの時間、信号をONにすればいいか?)を計算します。
データシートを見ると、ON時間と動作角度は以下のように対応しています。
- 0.5msec ON -90度
- 2.4msec ON +90度
上記の範囲は1.9msecなので、ON時間の幅「1.9msec」に、上で計算した角度の割合を当てはめることで、入力角度を動かすためのON時間が計算できます。
ここで、ON時間は0.5msecから始まっているため、割合で計算した値に0.5を追加します。
# 割合を時間の範囲に適応して、指定角度を動かす時間を計算します
addTime = TIME_RANGE * percent
# 時間範囲は0.5から始まるので0.5に指定角度の時間を足します
time = MIN_TIME + addTime
③ Duty比に変換
前述までの計算で指定角度を動かす場合の、ON時間(1.9msec)が計算できました。
しかし、PWMを設定するduty_u16関数は、初期化時に指定した1周期(20msec)の内、何秒ONにするかの「割合」を「16bit」で指定する必要があるため、ON時間を割合に変換後、16bit(0~65535)の値に変換して指定します。
# 指定角度の時間を、20msecの周期中の割合(%)に変換します
ratio = time / CYCLE_TIME
# 16bit(0~65535)の値(整数)に変換します。
ratio = (int)(65535 * ratio)
# 動作実行します
pwm.duty_u16(ratio)
return True
まとめ
RaspberryPi Pico / Pico Wで、サーボモータ(ラジコンサーボ)SG90を使う方法を解説しました
SG90は簡単に使えて値段もお手軽、「ちょっと動く何かを作ってみたいな」「初めてモーターを触ってみたい」という方にピッタリなモーターです。
動く工作も簡単に作れるので、興味を持ったかたはぜひ遊んでみてください。参考になればうれしいです。
お知らせ
MicroPythonのプログラミングガイドブックが遂に発売!
「MicroPython」の本が遂にでました。
この一冊で、MicroPythonの言語仕様から、プログラミングの仕方まで”ガッツリ”学べます!。
内容は、普段別言語で開発している人や、これからマイコンを始める(工学系の)学生を対象としているので「初心者向け」ではありません。しかし、「自前のライブラリの作成」が目標なので、これ一冊で「ガッツリ」とMicroPythonを学ぶことができます。
全ての内容はここでは紹介しきれないので、詳細は以下のAmazonページをご覧ください。目次だけでも”ガッツリ”なのが確認できると思います。
Pico/Pico W関連のおすすめ本
RaspberryPi Pico / Pico W関連のおすすめ本を独断と偏見で3つ選んでみました。Picoやるならとりあえずこれ買っとけ的な本や、電子工作全般で使える本などを厳選しています。
質問・要望 大歓迎です
「こんな解説記事作って」「こんなことがしたいけど、〇〇で困ってる」など、コメント欄で教えてください。 質問・要望に、中の人ができる限り対応します。
使えたよ・設定できたよの一言コメントも大歓迎。気軽に足跡を残してみてください。記事を紹介したい方はブログ、SNSにバシバシ貼ってもらってOKです。