サーボモーターを指定した角度に動かす (Raspberry Pi + RPZ-RC-Servo)

サーボモーターは、モーターシャフトの角度(位置)を電気的に指示することが可能なモーターで、ものやアームを動かしたり、カメラを回転させたりすることが可能です。本記事ではRPZ-RC-ServoとRaspberry Pi(ラズパイ)を使ってサーボモーターを指定した角度へ回転させる方法を解説しています。Pythonで動作する制御ソフトウェアcgservoを使うことで簡単かつ直感的にモーターを制御することができます。

更新日 : 2024年10月5日

RCサーボモーターについて

RCサーボモーターは、モーターシャフトの角度(位置)を電気的に指示することが可能なモーターで、以下のような応用が可能です。

  • ものや自機を決まった位置に移動させる
  • カメラ動かして撮影角度を変える
  • ロボットアームでものを仕分ける
  • スイッチを押したり離したりする
  • 移動体の舵を操作する

プログラムでRCサーボモーターの角度を制御することができ、カメラやセンサー、ネットワークなどとの連携も可能なRaspberry Piは、RCサーボモーターとの相性が良いといえるでしょう。

本記事ではラズパイ、サーボモーター制御基板「RPZ-RC-Servo」、制御ソフトウェア「cgservo」を使うことでサーボモーターを制御する方法を解説しています。

RPZ-RC-Servoにサーボモーターを接続した例

ハードウェアの準備

本記事ではサーボモータードライバー基板「RPZ-RC-Servo」を使用してサーボモーターを制御します。モーターや電源の接続、推奨モーターについては製品ページを参照してください。

ここからはPythonプログラムで実際に制御する方法について解説していきます。

I2C有効化

基板とはI2Cで通信します。こちらの記事を参考にRaspberry PiのI2Cを有効化して下さい。




制御ソフトウェアのインストール

Indoor Corgiが開発したPythonライブラリをインストールします。本ソフトウェアを使うことで、簡単かつ直感的にサーボモーターを制御することができます。

最新版へのアップグレードも同じコマンドで可能です。

$ sudo python3 -m pip install -U cgservo --break-system-packages

エラーが出る場合は最後のオプションを指定せずにお試しください。

$ sudo python3 -m pip install -U cgservo

PWM制御の仕組み

まず、RCサーボモーターで使われているPWM制御の仕組みについて解説します。

モーターの3本の配線のうちの1つである制御信号(S/PWMなどと呼ぶ場合もあります)を使い、以下のような波形をモーターへ出力します。

ここで、電圧が高くなっている部分の時間(パルス幅)の長さによって、モーターの角度(位置)が決まる仕組みになっています。パルス幅と角度の関係は使用するモーターによって異なりますが、パルス幅0.5[ms]〜2.5[ms]程度の範囲で角度を指定するものが一般的です。

以下は180°の回転範囲を持つCLS3850MEDのパルス幅と角度の関係です。パルス幅0.5[ms]の時は時計回り90°、1.5[ms]の時は中間点、2.5[ms]の時は半時計回り90°の位置へ回転します。

パルス幅と角度の関係(CLS3850MED商品ページより引用)

上記のパルスは一定周期でモーターへ送信し続けます。この周期で最もよく使われているのは20[ms] (周波数50Hz)です。周波数については厳密に調整する必要はなく、100Hzや200Hzでも動作するものが多いです。

モーターをパルス幅で制御する

ここからは実際にモーターを制御していきます。モーターが回転しますので、安全に注意して進めて下さい

モーター制御にはPythonプログラムを使用します。Pythonの基本的な使い方についてはこちらを参照して下さい。

モーターをM1端子に接続して下さい。パルス幅で制御するサンプルコードをダウンロードし、ターミナルで以下のコマンドを実行して下さい。3秒おきにモーターが3つの角度に回転すれば成功です!

python3 servo_basic.py

ここからはコードの解説です。

10行目
servo = Servo(
    i2c_addr=0x40,
    pwm_freq_target=50,
)

cgservoパッケージのサーボモーター制御機能を使う準備です。

i2c_addrは通常は0x40で問題ありません。基板のI2Cアドレスを0x41にしている場合は0x41に変更して下さい。

pwm_freq_targetは周波数を指定するものです。モーターの仕様に明記されている場合はその値に変更します。ほとんどの場合50Hzに対応しています。50Hzで動作できた場合、100Hz〜200Hzに上げることを推奨しています。パルス幅をより細かく制御できるためです。

15行目
servo.init()

RPZ-RC-Servo基板上のコントローラーICをリセットして周波数などを設定しています。モーター制御開始前に1度実行して下さい。

17行目
servo.m1p = 1.5
time.sleep(3)
servo.m1p = 1.0
time.sleep(3)
servo.m1p = 2.0
time.sleep(3)
servo.m1p = 0

m1p変数にパルス幅[ms]を代入することで、モーターM1へ指定したパルス幅を出力し続けます。この例では3秒間隔で1.5[ms]、1.0[ms]、2.0[ms]にパルス幅を変化させています。うまく動作していれば、モーターが反応して角度が変わります。

他のモーターのパルス幅を変えたい場合、m2pに代入すればM2が、m6pに代入すればM6が変わります。

最後にm1pに0を代入しています。0を設定するとPWM出力が停止します。逆に0を設定しない場合、電源が印加されている間信号を出力し続けます。動作を終了してモーターを取り外す場合は出力を停止することを推奨します。また、servo.init() を実行することで全てのモーターへの出力を停止できますので、こちらでも構いません。

モーターの角度を指定する

先程の例ではパルス幅を直接指定してモーターを操作しました。しかし、パルス幅だと実際にどの程度の角度になるのかわかりにくいと思います。そこで、cgservoには角度を指定することで自動的にパルス幅を計算してくれる機能を用意しています。これにより、直感的なプログラムが可能になります。

モーターをM1端子に接続して下さい。角度を指定するサンプルコードをダウンロードし、以下の解説に沿ってお使いのモーターに合った設定に書き換えて下さい。

13行目
    m1_param=MotorParam(
        min_pulse_width=0.5,
        max_pulse_width=2.5,
        input_start=-90,
        input_end=90,
    ),

m1_paramにモーター1に関する設定を記述しています。設定にはMotorParamクラスを使用して下さい。

min_pulse_widthとmax_pulse_widthにモーターが対応しているパルス幅の範囲(最小値と最大値)を指定します。値はモーターの仕様を参照して下さい。0.5〜2.5ms程度のものが多いです。

input_startとinput_endにモーターの回転角度の範囲(最小値と最大値)を指定します。この例では180°回転するモーターを想定しているため、−90〜90としています。0〜180のような指定もできるほか、正負を反転した90〜−90のような指定も可能です。また、必ずしも角度である必要はなく、0〜100でも構いません。プログラムを作成する上で使いやすい値を指定します。

23行目
servo.m1 = 0
time.sleep(3)
servo.m1 = -90
time.sleep(3)
servo.m1 = 90
time.sleep(3)

m1に角度を指定すると、自動的にパルス幅を計算してモーターへ出力します。

今回の例では、m1に−90を設定すると最小パルス幅0.5ms、m1に90を設定すると最大パルス幅2.5ms、m1に0を設定すると中間のパルス幅の1.5msになります。

角度がずれる場合

モーターの仕様が0.5ms〜2.5ms、回転角度180°となっていても、実際には遊びがあったりして若干角度がずれる場合があります。その場合は、角度計で実際の回転角度を測定してパラメーターを調整してください。




複数のモーターを制御する

複数のモーターを制御するサンプルコードを解説します。この例ではM1とM2の2つのモーターを操作しています。RPZ-RC-Servoでは6台のサーボモーターを制御できます。

プログラムはこれまでとほぼ同じです。これまでと同じM1の設定の下に、M2の設定を追加します。(23行目)

m2に値を設定すればモーターM2が指定した角度へ回転します。34行目のようにm1、m2を連続して設定した場合、両方のモーターが同時に回転を開始します。(M1の回転終了は待たない)

servo.m1 = 0
servo.m2 = 0

複数の基板を制御する

RPZ-RC-Servoは基板2枚使うことで、最大12台のサーボモーターを制御できます。7台以上のモーターをを使いたい場合、異なる電圧のモーターを使いたい、消費電流が多いので2枚の基板に分けたい場合などにご検討下さい。

基板1枚目のモーターM1と基板2枚目のモーターM1を制御するサンプルコードを解説します。

あらかじめ1枚目の基板のADRスイッチをOFF(I2Cアドレス0x40)、2枚目の基板のADRスイッチをON(I2Cアドレス0x41)に設定しておきます。

10行目
servo1 = Servo(
    i2c_addr=0x40,
    ...(周波数、モーターの設定)...
)

servo2 = Servo(
    i2c_addr=0x41,
    ...(周波数、モーターの設定)...
)

基板1を制御するservo1と基板2を制御するservo2の2つ使用しています。i2c_addrが異なっていることに注意して下さい。モーターの設定などはこれまでと同じです。

37行目
servo1.init()
servo2.init(reset=False)

基板2枚使用時の注意点として、2枚目の基板(servo2)でinitを実行する際はreset=Falseを指定して下さい。仕組み上、どちらかの基板でinit()を実行すると両方の基板のICがリセットされます。そのため、2枚目の基板ではでリセットを行わずに初期化処理のみ実行するようにします。

モーターを回転させるにはservo1.m1やservo2.m1に角度を指定すればOKです。

まとめ

RPZ-RC-ServoとRaspberry Pi(ラズパイ)を使ってサーボモーターを指定角度へ回転させる手順を解説しました。制御ソフトウェアcgservoを使うことで、簡単にサーボモーターを回転させることができ、ものを動かしたり回転させるといった応用が可能です。また、RCサーボモーターより高精度な位置合わせがしたい、回転数の調整がしたい場合、ステッピングモーターもご検討下さい。

サーボモーターを指定した角度に動かす (Raspberry Pi + RPZ-RC-Servo)

サーボモーターは、モーターシャフトの角度(位置)を電気的に指示することが可能なモーターで、ものやアームを動かしたり、カメラを回転させたりすることが可能です。本記事ではRPZ-RC-ServoとRaspberry Pi(ラズパイ)を使ってサーボモーターを指定した角度へ回転させる方法を解説しています。Pythonで動作する制御ソフトウェアcgservoを使うことで簡単かつ直感的にモーターを制御することができます。

指定時刻にラズパイ/Jetsonの電源をON/OFF (RPZ-PowerMGR)

RPZ-PowerMGRを使って、指定時刻にRaspberry Pi(ラズパイ)やJetson Nanoの電源ON/OFFする方法の解説です。決まった時間だけ起動して消費電力を抑えることが可能で、モバイルバッテリーやソーラーシステムでの運用に最適です。

RPi TPH Monitor Rev2 (Raspberry Pi用 温度/湿度/気圧/赤外線 ホームIoT拡張ボード)

動作をプログラミング可能な、Raspberry Pi(ラズパイ)用ホームIoT拡張ボードです。温度、湿度、気圧センサー、赤外線送信、受信機能を搭載。温度が上がったらエアコンをオンにする、外出先から家電の操作をする、気温や湿度を記録する、といった使い方が可能です。ディスプレイやLEDに情報表示、スイッチを押したら特定の処理をすることもできます。