はじめに
RaspberryPiで、サーボモータ(ラジコンサーボ)を使う方法について質問をいただいたので、電子工作でよく使われる「SG90」使う方法を解説します。
プログラム言語は「Python」ライブラリは「RPi.GPIO」を使います。
カンパチさんご質問ありがとうございます。
~ この記事の内容 / Contents ~
環境
この記事で使用する環境は以下の通りです。
環境 | 備考 | |
RaspberryPi | 4 Model B | Pi3でもOKです。 |
OS | RaspberryPi OS (bullseye) | 64bit版です |
言語 | Python 3.9.2 | |
ライブラリ | RPi.GPIO |
RaspberryPi2や3も使用できます。ピン配置は同じなので、記事と同じように接続してください。
サーボモーター(ラジコンサーボ) SG90
今回の記事で使用するサーボーモーター(ラジコンサーボ)「SG90」です。
ラジコンサーボは、モータ・ギアボックス・制御基板などが1つのケースにまとめられたモーターで、±90度など、ある特定の範囲を動かすことに特化しています。
ラジコンカーのステアリング・ラジコン飛行機の翼の操作・ホビーロボットの関節軸などによく使われており、「電源・GND・PWM信号」の3本だけで動かすことができます。
SG90の電源は4.8Vですが、PWM信号は3.3Vでも反応してくれるので、RaspberryPiシリーズでも簡単に使うことができます。
項目 | スペック |
電圧 | 4.8V |
動作範囲 | 180度(±90度) |
トルク | 1.8kgf・cm |
付属品 | サーボホーン3種 |
サーボ固定ねじ×2、ホーン固定ねじ×1 |
RaspberryPiとの接続
RaspberryPi4・SG90・充電池(エネループ)を以下のようにつなぎます。
RaspberryPi本体の5Vピンをつないでも動きますが、電流が不足しそうなので、エネループをサーボ用の電源に使っています。
なお、別電源を使う際は、RaspberryPiと電源のGNDをつないで使用してください、GNDの共通化を行わないと、動作が不安定になったり、動かないことがあります。
(間違って単4の電池ケースを購入したので単4を使っていますが、単3でもOKです)
ピン番号 | RaspberryPi側 | サーボモータ |
33 | GPIO13(PWM1) | PWM |
39 | GND | GND (電池と共通化します) |
— | 電池+ | 電源 |
— | 電池 − | GND (電池と共通化します) |
ピンアサイン
※ RaspberryPi 公式のGitHubより引用
使用する部品
RaspberryPi 4 (4GBモデル)
やっと価格が適正値に戻ってきました。国内代理店であるスイッチサイエンスさんやKSYさんでも在庫が復活しているようなので、そちらで購入するのもありです。
サーボモータ(ラジコンサーボ) SG90
冒頭でも紹介した、RaspberryPiシリーズで使えるサーボモータ(ラジコンサーボ)です。 人気のため、コピー品も多いようです。私は以下の正規販売元のページから購入しました。
ブレッドボード
国内サンハヤト製のブレッドボードです。少々堅めの指し心地ですが、海外製と違ってピン穴の番号がすべて印刷されており、品質も高いのでおすすめです。
電池ボックス
電源に使う電池用ボックスです。スイッチ付きで何かあってもすぐに電源を切れるので、安心して工作することができます。
記事では単4を使っていますが、容量の大きい単3タイプをお勧めします。単3でも単4でも電圧は変わりません。
電池ボックス(単4)
記事で使っている単4を3本使うタイプはこちらで購入しています。
ジャンプワイヤ (オス-メス タイプ)
RaspberryPiで使う場合は、以下のオスーメスタイプがおすすめです。
エネループ
使い捨ての乾電池もいいですが、エネループなら4本充電時の電気代が約1円。モーター・ポンプなどの電池が消耗しやすい実験・工作におすすめです。
※ はじめて使う方は充電器とのセットがおすすめです
電池ボックス
電源に使用する乾電池用のボックスとスナップです。記事では単4を使っていますが、容量の大きい単3タイプをお勧めします。単3でも単4でも電圧は変わりません。
プログラム概要
今回のプログラムの概要は以下の通りです。
- PWMの設定をする。
- サーボモータを動かす。
実行結果
後述するプログラムの実行結果です。サーボモータが「-90度」「0度」「+90度」の順で、3回動作します。
全体コード
全体コードは以下の通りです。詳細な内容は後述する「コードのポイント」で解説します。
# RPi.GPIOのライブラリを「GPIO」という名前で使います
import RPi.GPIO as GPIO
import time
# サーボが動作可能な範囲です
ANGLE_RANGE = 180
# サーボに指定するPWMの時間の範囲です
TIME_RANGE = 1.9
# サーボに指定できる最小の時間です
MIN_TIME = 0.5
# サーボのPWMの周期時間です
CYCLE_TIME = 20.0
# GPIOのピン番号指定を「BCM」に設定します
GPIO.setmode(GPIO.BCM)
# 設定を確認。BCMの場合は「11」が返ります
mode = GPIO.getmode()
print(mode)
# PWMに使うピンに名前をつけます
PWM = 13
# PWMに使うピンを「Out」に設定します
GPIO.setup(PWM,GPIO.OUT)
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 ) * 100
# 動作実行します
pwm.ChangeDutyCycle(ratio)
return True
# PWMのピンと周波数を設定します。
# 周波数は、SG90の仕様の50Hz(20msec)に設定します
pwm = GPIO.PWM(PWM,50)
# PWMを開始します
pwm.start(0)
# 同じ動作を3回繰り返します
for i in range(3):
# -90度に動作
moveServo(pwm, -90)
time.sleep(2)
# 0度に動作
moveServo(pwm, 0)
time.sleep(2)
# +90度
moveServo(pwm, 90)
time.sleep(2)
# GPIOの設定を解除します
GPIO.cleanup(PWM)
コードのポイント
周期の設定
PWMのピンと周波数を設定します。
秋月電子さんで公開されている「SG90のデータシート」に「50Hz」と記載されているため、PWMの周波数を50Hz(1周期20msec)に設定します。
# PWMのピンと周波数を設定します。
# 周波数は、SG90の仕様の50Hz(20msec)に設定します
pwm = GPIO.PWM(PWM,50)
# PWMを開始します
pwm.start(0)
Duty比の作成
サーボ角度はPWMのDuty比を変えることで指定できます。角度の変更は何度も実行する処理のため、関数にまとめてメイン処理側のコードが簡潔にしています。
処理内容は以下の通りです。
① 角度を割合に変換
計算を楽にするため、「SG90」が動作できる範囲である±90度を、90度ずらして、0~180度の範囲(表現)に変換します。
次に、変換後の入力角度を、SG90の動作範囲(180度)で割り、入力角度が動作範囲対してどの程度の割合であるかを計算します。
def moveServo(pwm,angle ):
# 入力角度のチェックです。±90以外はエラーにします
if angle < -90 or angle > 90 :
return False
# 指定角度を、0~180の表現に変えます
angle = angle + 90
# 指定角度を、全体(180度)中の割合に変換します
percent = angle / ANGLE_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を設定するChangeDutyCycle関数は、初期化時に指定した1周期(20msec)の内、何秒ONにするかを、「割合」を「パーセント」で指定する必要があるため、ON時間を割合に変換します。
# 指定角度の時間を、20msecの周期中の割合(%)に変換します
ratio = ( time / CYCLE_TIME ) * 100
# 動作実行します
pwm.ChangeDutyCycle(ratio)
return True
まとめ
RaspberryPi(ラズパイ) でサーボモータ(ラジコンサーボ)を使う方法を解説しました
SG90はRaspberryPiと簡単につなげて値段もお手軽、「ちょっと動く何かを作ってみたいな」「初めてモーターを触ってみたい」という方にピッタリなモーターです。
動く工作も簡単に作れるので、興味を持ったかたはぜひ遊んでみてください。参考になればうれしいです。
おすすめの最新書籍
今月号の日経Interfaceは「Linuxチューニング術50」
今月号のInterfaceは『Linux チューニング術 50』です。
Linuxを組み込んだ機器を”本格的”に作ろうとすると「起動を早くしたい」「いきなり電源を切られてもデータを守りたい」など、対応が必要なチューニングはおおいですよね。
今回の記事は、「カーネルをいじらない」方法でチューニングを行う方法が解説されています。
こういった”実用的”な特集はレアですし、知っておいても損はない情報だと思います。
私も仕事でこの手の問題に何度も遭遇していますが、こういったOSレベルの難しそうな設定を、さらっとできちゃう人はかっこいいですよね。
興味のある方は、以下のリンクから確認できます。
質問・要望 大歓迎です
「こんな解説記事作って」「こんなことがしたいけど、〇〇で困ってる」など、コメント欄で教えてください。 質問・要望に、中の人ができる限り対応します。
使えたよ・設定できたよの一言コメントも大歓迎。気軽に足跡を残してみてください。記事を紹介したい方はブログ、SNSにバシバシ貼ってもらってOKです。