ここでは「Raspberry Pi」を使って「複数のサーボモータ」をPythonを使って制御する方法を紹介します。
この記事を読むことで
複数のサーボモータを制御するのに必要なもの
ラズパイで複数サーボモータを制御する知識
複数のサーボモータ制御プログラム
を知ることができます。
サーボモータを1つではなく、複数のサーボモータを使ってロボットを作りたい方などに役立てて頂ければ幸いです。
それではさっそく始めていきましょう。
ラズパイで複数サーボを制御するための準備
まずはラズパイで複数のサーボモータを制御するための部品や、基礎知識を確認していきます。
PWMサーボモータと基礎知識
今回使用するサーボモータは「JR SERVO:DS3401」になります。
ラズパイでサーボモータをPWM制御するときに
という点に注意する必要があり、各社サーボの仕様書をよく読んでおく必要があります。
ささっと調べてみると、下記のPDFに各メーカーごとのサーボモータ駆動パルスがまとめてあったので、今回はこちらの駆動パルス値を参考にプログラムを記述していこうと思います。
始めてサーボモータを扱うときに使うことが多い「サーボモータ:SG90」の制御を行う場合も、仕様書が転がっているので必ず調べておきましょう。
サーボを制御するためのその他部品
サーボモータ以外の部品は以下の通りです。
使用する部品等
Raspberry Pi 4
電池:6V ( 1.5 × 4 )
ブレッドボード
ジャンパー線
PWMサーボ並列接続用回路
複数のサーボモータを並列で接続する回路は、VinとGNDを並列にし、信号線は個別で取り出せるように組んであります。
ラズパイで複数のサーボを制御する
使用する準備、基礎知識を確認したら、実際にラズパイで複数のサーボモータを制御していきましょう。
ラズパイと複数サーボの配線
まずは、ラズパイと複数のサーボモータの配線の様子です。
5~6V電源は複数のサーボモータすべてに加わるように並列回路でつなげます。
各サーボモータの信号線は、ラズパイのGPIOピンにオスメスジャンパー線で配線をしました。
ブレッドボードは、ラズパイとサーボモータのGNDを共有するために使用しています。
複数のサーボモータを制御するための配線といっても難しくはなく、VinとGNDを並列回路となるように配線すればOKですよ。
複数サーボの制御プログラム
続いて、ラズパイで複数サーボモータを制御するためのプログラムになります。
GPIOピンを使用するので
のライブラリをインストールしておきましょう。
pwm_test.py
import RPi.GPIO as GPIO import time import sys pin = [5, 6, 13, 19, 26] servo = [] # 使用する各社サーボの駆動パルス T = 22 # パルス周期 [mSec] f = round( 1/T * 1000 ,1) # 周波数 neutral = 1500 / 1000 # ニュートラル1500 [μSec → mSec] variable = 600 / 1000 # 可変範囲±600 [μSec → mSec] # GPIOの設定 GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) for num in range(5): GPIO.setup(pin[num], GPIO.OUT) servo.append(GPIO.PWM(pin[num], f)) servo[num].start(0) # Duty = τ/T * 100 より角度からDuty比を算出 def servo_angle(angle, pin): duty = ( (neutral + (angle * variable / 90) ) / T ) * 100 # Duty = τ/T * 100 servo[pin].ChangeDutyCycle(duty) #デューティ比を変更 while True: try: print("\n" + "angle: -90") for num in range(5): servo_angle(-90, num) time.sleep(0.5) print("\n" + "angle: -45") for num in range(5): servo_angle(-45, num) time.sleep(0.5) print("\n" + "angle: 0") for num in range(5): servo_angle(0, num) time.sleep(0.5) print("\n" + "angle: -45") for num in range(5): servo_angle(-45, num) time.sleep(0.5) except KeyboardInterrupt: for num in range(5): servo[num].stop() GPIO.cleanup() print("\n" + "PWMサーボのテストプログラムを終了します。") sys.exit()
はGPIOピンの各ピン番号を配列として格納しています。
# 使用する各社サーボの駆動パルス T = 22 # パルス周期 [mSec] f = round( 1/T * 1000 ,1) # 周波数 neutral = 1500 / 1000 # ニュートラル1500 [μSec → mSec] variable = 600 / 1000 # 可変範囲±600 [μSec → mSec]
は上記で述べた、各社サーボモータの駆動パルスを定数として宣言した箇所です。
使用しているJRサーボモータは
パルス周期:22 [mSec]
ニュートラル:1500 [μSec]
可変範囲:±600 [μSec]
と上記URLのPDFから分かるので、単位を揃えて定義しています。
# Duty = τ/T * 100 より角度からDuty比を算出 def servo_angle(angle, pin): duty = ( (neutral + (angle * variable / 90) ) / T ) * 100 # Duty = τ/T * 100 servo[pin].ChangeDutyCycle(duty) #デューティ比を変更
は与えた角度から、各社サーボモータに適したDuty比に変換する関数になります。
Duty比は
で表すことができるので、分子の「パルス幅:τ」を各社サーボモータごとに調整をします。
JRサーボモータの場合、ニュートラル:1500[μSec]、可変範囲:±600[μSec]なので、パルス幅が
900[μSec](1500-600[μSec])のとき、角度-90°
1500[μSec](ニュートラル)のとき、角度0°
2100[μSec](1500+600[μSec])のとき、角度90°
となれば良いということです。
この関係を式でまとめると
となるので、上記のような式と関数になります。
あとは、print()文、作成したservo_angle()関数をtry except文で記述してあげれば完成です。
複数サーボの制御をラズパイで実行する
複数のサーボモータを制御するPythonプログラムが完成したら、実際に動作確認をしてみます。
とTeraTerm等で打ち込んで、実行します。
PWMサーボの動作角度はタイムラインで確認できるようにしておくと、サーボモータが指定角度になっているかを確認しやすいですよ。
実際に複数のサーボモータをラズパイで制御してみても、指定した角度になっていることが分かりますね。
ここまでできれば、あとはロボットの機構を考えて形にしてしまえばMyrobotの完成です!
以上、ラズパイで複数のサーボモータをPythonで制御する方法でした。
お疲れ様でした。