サーボモーターを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, in 
    factory = 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