CircuitPython 10行プログラミング Step2 (7) サーボ・モータ①

 二足走行ロボットが電子工作の分野で登場するまで、サーボ・モータには2種類の製品がありました。一つは製造業などの機器で使われていたACサーボ・モータです。もう一つは、ラジコン用のサーボ・モータです。飛行機のラダーなどを動かすために使われていました。軽量なのが特徴です。

 二足走行ロボットが登場した直後はそれまでのラジコン用のサーボ・モータが流用されていましたが、トルクを上げたり、コマンドをシリアル通信で行うような改良が行われました。ラジコン用もディジタル通信が採用されるようになり、各社独自の規格をアピールしています。

Arduinoなどで使われるサーボ・モータは3線式

 古くから使われているラジコン用サーボ・モータは、3本のケーブルで接続します。最近よく見るのは下記の色です。

ケーブルの色 信号
茶色 GND
オレンジに近い赤色 V+
オレンジに近い黄色 信号(PWM)

 信号のPWMは次の波形をしています。周期は約20ms、HIGHの時間によって、回転する角度が決まりますが、製品によって統一されていなく、ほぼ1500us付近が中央値の値が多いようです。
 回転角度は120~160°が多く、360°に対応した製品もあります。
 電源電圧はカタログに書かれていないことが多いのですが、4.8~6Vが多いようです。

 モータの回転は内部のギアで減速されます。外に出ている軸にホーンを挿しこみます。ホーンにはピアノ線をひっかける穴が複数開いています。ピアノ線が動くと、その先についている方向舵(ラダー)やエルロンを動かし、飛んでいく方向などを変えられます。

接続

サーボ・モータ マイコン・ポード
Grand Central
茶色 GND
オレンジに近い赤色 5V
オレンジに近い黄色 A2

プログラム

 こちらの解説ページにあるCircuitPython_Servo.pyをMuエディタに貼り付け、main.pyで保存し、実行します。

import time
import board
import pulseio
from adafruit_motor import servo

# create a PWMOut object on Pin A2.
pwm = pulseio.PWMOut(board.A2, duty_cycle=2 ** 15, frequency=50)

# Create a servo object, my_servo.
my_servo = servo.Servo(pwm)

while True:
for angle in range(0, 180, 5): # 0 - 180 degrees, 5 degrees at a time.
my_servo.angle = angle
time.sleep(0.05)
for angle in range(180, 0, -5): # 180 - 0 degrees, 5 degrees at a time.
my_servo.angle = angle
time.sleep(0.05)

 while文以下を my_servo.angle = 90 に変更して保存します。このときの波形をPicoScopeで観測します。

 サーボ・ホーンは一度動いて静止しますが、波形は一度パルスを出した以後、観測できません。

while True:
    my_servo.angle = 90
    time.sleep(1)

 上記のようにangleを繰り返すように修正すると、上記と同じくサーボ・ホーンは一度動いて静止し、継続して次の波形になります。

 周期は20.02ms、パルス幅は1500usです。

 my_servo.angle = 180にするとパルス幅は2251us、0にすると750usになりました。ホーンの回転は次のようになりました。

パルスの出る条件

my_servo.angle = 90


 では、一度パルスが出るだけです。

my_servo.angle = 90
time.sleep(1)
my_servo.angle = 120


 最初のパルスは1秒間連続して出ていて、120のパルスは一度だけ出て、あとはなくなります。

my_servo.angle = 120
time.sleep(5)
my_servo.angle = 0
time.sleep(5)

 120のパルスが5秒、0のパルスが5秒出て、止まります。したがって、一度パルスを出せばホーンは指定の角度分回るが、パルスの出力は停止する。sleepさせると、その間同じパルスを出し続けるということがわかりました。

2個のサーボ・モータをつなげる

 上記の実験はサーボ・モータの信号線をA2につなぎました。もう一つのサーボ・モータの信号線をA3につなぎ、次のプログラムを動かします。

 A3ポートはだめだと言われたので、D14につなぎ直しました。

import time
import board
import pulseio
from adafruit_motor import servo

# create a PWMOut object on Pin A2.
pwm0 = pulseio.PWMOut(board.A2, duty_cycle=2 ** 15, frequency=50)
pwm1 = pulseio.PWMOut(board.D14, duty_cycle=2 ** 15, frequency=50)

# Create a servo object, my_servo.
my_servo0 = servo.Servo(pwm0)
my_servo1 = servo.Servo(pwm1)

while True:
my_servo0.angle = 180
time.sleep(1)
my_servo1.angle = 180
print("ok")
my_servo0.angle = 10
time.sleep(1)
my_servo1.angle = 80
print("ok")

 三つ目をD15につなぎました。

import time
import board
import pulseio
from adafruit_motor import servo

# create a PWMOut object on Pin A2.
pwm0 = pulseio.PWMOut(board.A2, duty_cycle=2 ** 15, frequency=50)
pwm1 = pulseio.PWMOut(board.D14, duty_cycle=2 ** 15, frequency=50)
pwm2 = pulseio.PWMOut(board.D15, duty_cycle=2 ** 15, frequency=50)

# Create a servo object, my_servo.
my_servo0 = servo.Servo(pwm0)
my_servo1 = servo.Servo(pwm1)
my_servo2 = servo.Servo(pwm2)

while True:
my_servo0.angle = 180
time.sleep(1)
my_servo1.angle = 180
my_servo2.angle = 180
print("ok")
my_servo0.angle = 10
time.sleep(1)
my_servo1.angle = 80
my_servo2.angle = 80
print("ok2")

 問題なく動作しました。

たくさんのサーボ・モータをつなぐ

 このマイコン・ボードGrand CentralでPWM出力に使えるのは、下記のピンです。したがって、サーボ・モータは同時にたくさんつなげられますが、配線が煩雑になります。

  • A1、A2、A12、A15
  • D2~D9、D11、D13~D45、D48、D50~D53
  • MISO、MOSI、SCK、SCL、SDA

クラスContinuousServo

 ContinuousServoは連続的にパルスを出し続けてくれる関数かと思いましたが、配給電力?を制御する関数のようです。throttleは-1~1の範囲で指定します。

my_servo1 = servo.ContinuousServo(pwm1)

my_servo1.throttle = 0.8
time.sleep(1)