サーボモーターをPan and Tilt マウンターに取り付け、Raspberry Pi 4でPan and Tilt マウンターを動かします。
Raspberry Piとサーボモーターの接続
使用するサーボモーターの仕様を次に示します。
- 重量: 55グラム
- 動作速度: 0.17sec/60度(4.8ボルト無負荷)
- 動作速度: 0.13sec/60度(6.0ボルト無負荷)
- ストールトルク: 4.8ボルトで13キログラム-センチメートル
- ストールトルク: 6ボルトで15キログラム-センチメートル
- 動作電圧: 4.8~7.2ボルト
- ギアタイプ:すべての金属歯車
- サイズ:40x20x43mm
- 動作範囲 : 約180度
Raspberry Piとサーボモーターは次のように接続します。「+6V」は単三電池を使用します。
Raspberry Pi | サーボモーター |
---|---|
GPIO12/GPIO13 | オレンジ |
GND | ブラウン |
+6V | レッド |
Raspberry Piとサーボモーターの接続画像を次に示します。サーボモーターはPan and Tilt マウンターに取り付けています。
Pan and Tilt マウンターは、「Fusion 360のジョイント機能を使ってサーボモータにより3Dモデルを回す」でモデル化したマウンターを使用します。
サーボモーターアプリの作成
サーボモーターアプリ「jitter.py」を次のように作成します。ライブラリはgpiozeroの「14.1.8. Servo」を使用します。
- 「wiringpi」のソフトウェアPWMを使用すると、サーボモータがかなりガタガタ(ジッター)するので、「pigpio」のハードウェアPWMを使用して揺れ(ジッター)を無くします。
- 使用するサーボモーターの周期は20ms(50Hz)で、パルス幅を0.5〜2.4ms(500~2400μs)の範囲で変化させて、0〜180°までの角度で回転させます。
jitter.py
#!/usr/bin/python # -*- coding: utf-8 -*- from gpiozero import Servo from time import sleep from gpiozero.pins.pigpio import PiGPIOFactory factory = PiGPIOFactory() servo = Servo(12, min_pulse_width=0.5/1000, max_pulse_width=2.5/1000, pin_factory=factory) servo.mid() sleep(5) servo.min() sleep(5) servo.max() sleep(5) servo.mid() sleep(5) servo.value = None
一般的にサーボモータに与えるPWM波の周期は10~20msで、モータが真ん中で停止するようなパルス幅は1.5ms前後のようです。そしてプラスマイナス0.5msの範囲で左右に動きます。つまりサーボモータは1~2ms程度のパルス幅を10~20msの周期で与えることで、停止させたい位置に停止できるようになります。
class gpiozero.Servo(pin, *, initial_value=0, min_pulse_width=1/1000, max_pulse_width=2/1000, frame_width=20/1000, pin_factory=None)
パラメータ;
pin (int or str) – サーボが接続されているGPIOピン
initial_value (float) – 0(デフォルト)の場合、デバイスの中間点が最初に設定される
min_pulse_width (float) – サーボの最小位置に対応するパルス幅。 デフォルトは1ms
max_pulse_width (float) – サーボの最大位置に対応するパルス幅。 デフォルトは2ms
frame_width (float) – 秒単位で測定されたサーボ制御パルス間の時間の長さ。 デフォルトは20msであり、これはサーボの一般的な値
pin_factory (Factory or None)value
サーボの位置を-1(最小位置)から1(最大位置)までの値で表す。これは、サーボが現在「制御されていない」こと、つまり制御信号が送信されていないことを示す特別な値Noneにもできる。
サーボモーターアプリの実行
次のコマンドでサーボモーターアプリ「jitter.py」を実行します。Pan and Tilt マウンターの角度が、90°、0°、180°、90°に変化します。
$ sudo pigpiod $ python3 jitter.py
「 pigpiod」が起動していないと次のエラーメッセージが表示されます。
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Can't connect to pigpio at localhost(8888) Did you start the pigpio daemon? E.g. sudo pigpiod Did you specify the correct Pi host/port in the environment variables PIGPIO_ADDR/PIGPIO_PORT? E.g. export PIGPIO_ADDR=soft, export PIGPIO_PORT=8888 Did you specify the correct Pi host/port in the pigpio.pi() function? E.g. pigpio.pi('soft', 8888) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Traceback (most recent call last): File "jitter.py", line 8, infactory = PiGPIOFactory() File "/usr/lib/python3/dist-packages/gpiozero/pins/pigpio.py", line 126, in __init__ raise IOError('failed to connect to %s:%s' % (host, port)) OSError: failed to connect to localhost:8888
スキャンアプリの作成
スキャンアプリ「scan.py」はPan and Tilt マウンターを方位角/仰角方向に変化させます。
scan.py
#!/usr/bin/python # -*- coding: utf-8 -*- from gpiozero import Servo import math from time import sleep from gpiozero.pins.pigpio import PiGPIOFactory factory = PiGPIOFactory() # 方位角 servo_az = Servo(12, min_pulse_width=0.5 / 1000, max_pulse_width=2.4 / 1000, pin_factory=factory) #仰角 servo_ele = Servo(13, min_pulse_width=0.5 / 1000, max_pulse_width=2.4 / 1000, pin_factory=factory) servo_az.value = -1 servo_ele.value = 0 sleep(3.5) for i in range(0, 21): angle =( i-10)/10 print(angle) servo_az.value = angle for k in range(0, 11): angle = k / -10 print(angle) servo_ele.value = angle if angle == 0: sleep(1) else: sleep(0.4)
スキャンアプリの実行
次のコマンドでスキャンアプリ「scan.py」を実行します。
$ sudo pigpiod $ python3 scan.py
Pan and Tilt マウンターが方位角/仰角方向に変化します。
<参考>連続回転のサーボモータ
次のような連続回転するサーボモータを入手しました。サーボモーターの周期は20ms(50Hz)で、パルス幅を0.5〜2.4ms(500~2400μs)の範囲で変化させて、サーボモーターの回転する速度と方向が手動で変化できます。
次のPythonスクリプト「rotate.py」で動作を確認できます。servo.max()で最高速の右回転、servo.min()で最高速の左回転、servo.mid()で停止、servo.valueで「-1」から「1」までを変化すると回転する速度と方向が手動で変化できます。
rotate.py
#!/usr/bin/python # -*- coding: utf-8 -*- from gpiozero import Servo from time import sleep from gpiozero.pins.pigpio import PiGPIOFactory factory = PiGPIOFactory() servo = Servo(12, min_pulse_width=0.5/1000, max_pulse_width=2.5/1000, pin_factory=factory) #servo.mid() #sleep(5) #servo.min() #sleep(5) #servo.max() #sleep(5) #servo.mid() #sleep(5) servo.value = 0.5