第1回:RCカーをリモート操作、Raspberry PiにてGPIOでサーボを動かしてみよう

TAMIYA 1/12RC XB ランチボックスカーをリモート操作するまえに、Raspberry Pi 4にUSBゲームパットを接続してPythonでサーボモーターを操作してみます。

サーボモーターはSG90です。安価なサーボモーターです。USBゲームパット、Raspberry Pi 4、Python、サーボモーターを使うことで全体の検証ができます。

データシートを見ると茶色がGND、赤が電源、オレンジがPWMです。TAMIYA 1/12RC XB ランチボックスカーのサーボも似たようなものです。SG90を上手く動かせばランチボックスのサーボも制御できるでしょう。

 

USBゲームパットは、Logitech Gamepad F310です。安価なタイプです。XBOXタイプの共通コントローラーです。どれでも大体一緒です。

GPIOは以下を使います。縦ですが、実機と比べるときは左に回転して比較してください。①3.3V、②GPIO12、③GNDです。

細いケーブルのオスメスをいくつか揃えておくと便利です。

本環境はRaspberry Pi 4(ubuntu22.04)です。アップデート、ssh接続、22番ポートを開けました。ご自身の使いやすい形で実行ください。最近ではstart sshやinstall ufwやufw enableは不要ですね。初期設定で入っているはずです。

sudo apt update && sudo apt upgrade
sudo apt install openssh-server
sudo systemctl start ssh
sudo apt install ufw
sudo ufw enable
sudo ufw allow 22
sudo apt install nano

ubuntu24.04ではpipやpigpioでいろんな注意やエラーがでます。Python環境がより厳密になったからです。本環境はubuntu22.04ですが仮想環境で構築します。ubuntu24.04でも実行できるでしょう。

Pythonのパッケージマネージャーpipを入れます。aptみたいなものです。Pythonのインストールを管理してくれます。python3-venvはもっとも標準的なPythonの仮想環境パッケージです。開発環境用にbuild-essentialとgitです。

sudo apt install python3-pip python3-venv build-essential git

venvを使ってmyenvという仮想環境を作ります。myenvは自由な名称でつくれますが定番の書き方がmyenvです。source myenv/bin/activateで、仮想環境を実行します。

python3 -m venv myenv
source myenv/bin/activate

仮想環境でpipを使うことでpip install によるシステム全体への影響を防ぎます。wheelは何やらインストールの高速化、inputsは入力デバイスのライブラリ、piozeroとpigpioはGPIOピンの制御のパッケージです。

pip3 install wheel
pip3 install inputs
pip3 install gpiozero
pip3 install pigpio

pigpio及びpigpiodがすごく分かりにくいのですが、上記pip3でインストールしたpigpioはPythonからGPIOピンの制御で、pigpiodはシステムからのGPIOピンの制御のためのようです。pip3 install pigpioだけでは、pigpiodが動かないので仮想環境ではなく以下でインストールします。

※Raspberry Pi 5(ubuntu2x.04)では、pigpioがRaspberryとしてはハードウェアを認識せずに上手く行きませんでした。ubuntuを使ったのがいけないのか素直にRaspiOSを使うべきなのだと思います。

git clone https://github.com/joan2937/pigpio
cd pigpio
make
sudo make install
sudo usermod -aG input $USER

いったん再起動して上手く動作するか試してみましょう。

sudo reboot

再起動したら仮想環境を立ち上げてpigpiodデーモンを起動します。問題なくpigpiodが動けばOKです。エラーが起きたらGPTにエラーを見せれば解決するはずです。

source myenv/bin/activate
sudo pigpiod

次は、Pythonのプログラムを準備をします。get_gamepad関数はゲームパッドのイベントの取得につかいます。AngularServoクラスはサーボモータを制御に使います。PiGPIOFactoryはGPIOピンのPWM制御精度を高めるために使います。それらを使うために環境を準備します。

sudo nano joystick_test.py

以下内容です。GPIOピン12に接続されたAngularServoオブジェクトを作成します。サーボモータの角度範囲を-90度から90度に設定し、パルス幅の最小値と最大値を指定します。frame_widthはパルスの間隔を指定し、pin_factoryにfactoryオブジェクトを指定して、精密制御を実現します。

from inputs import get_gamepad
from gpiozero import AngularServo
from gpiozero.pins.pigpio import PiGPIOFactory
import time

# GPIOの設定(PiGPIOFactoryを使って精密制御)
factory = PiGPIOFactory()
servo = AngularServo(
    12,
    min_angle=-90,
    max_angle=90,
    min_pulse_width=0.5 / 1000,
    max_pulse_width=2.4 / 1000,
    frame_width=1 / 50,
    pin_factory=factory
)

def main():
    print("ジョイスティックを監視中...")
    while True:
        events = get_gamepad()
        for event in events:
            print(event.ev_type, event.code, event.state)
            if event.code == "ABS_Y":
                # ジョイスティックのY軸が動いた場合
                # 状態は -32768 から 32767 の範囲; 中央が0
                axis_value = event.state / 32767  # -1 から 1 の範囲に正規化
                angle = axis_value * 90  # 軸の値を角度に変換(-90度から90度)

                # 角度を -90 から 90 に制限
                if angle < -90: angle = -90 elif angle > 90:
                    angle = 90

                servo.angle = angle
                print(f"サーボの角度を {angle:.1f} 度に設定")

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("\nプログラムを終了します...")

忘れない内にファイルに実行権限をつけて、python3 joystick_test.pyをテストします。

sudo chmod +x joystick_test.py
python3 joystick_test.py

inputsライブラリではなくPygameを使う方法もありますがビデオシステム関連でエラーが起きました。Raspberry Pi5(ubuntu24.04)ではPygameの方が上手く動作しました。このあたりもう少し検証する時間を作りたいところです。

inputsライブラリは、ハードウェア入力(ジョイスティックやゲームパッドなど)を扱い役立ちます。ヘッドレス(ディスプレイのない)設定でも正常に動きます。低レベルなハードウェアアクセスが可能です。依存関係が少ないです。リアルタイム入力に優れています。

 

仮想環境やsudo pigpiodを自動化

仮想環境やsudo pigpiodは毎回実行が必要です。自動起動させるには少し手間が必要です。pigpiodのSystemd サービスファイルは多分存在しないので自分で作る必要があります。

sudo nano /etc/systemd/system/pigpiod.service
[Unit]
Description=Pigpio daemon
After=network.target

[Service]
ExecStart=/usr/local/bin/pigpiod
ExecStop=/bin/systemctl kill pigpiod
Type=forking
PIDFile=/var/run/pigpio.pid

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload

サービスを有効化して起動します。状態が正常であれば成功です。

sudo systemctl enable pigpiod
sudo systemctl start pigpiod
sudo systemctl status pigpiod

仮想環境の方は、最終的なjoystick_test.pyが完成したらExecStartで仮想環境を指定してあげればよいはずです。

ExecStart=/path/to/myenv/bin/python /path/to/joystick_test.py

 

ハードウェアPWMをサポート

サーボをなめらに操作するには、PWMがよいです。PWMはソフトウェアとハードウェア制御があります。ハードウェア制御の方がより安定して負荷が少ないそうです。Raspberry Pi4では一部のピンだけハードウェアPWMをサポートしています。

GPIO 12 PWM0
GPIO 13 PWM1

ハードウェアPWMをサポートしているようで、PWM0とPWM1の二つのチャンネルにマップされています。2チャンネルの制御になるため、同時に使えるのは2つのピンになるようです。2つのサーボモータを異なる角度で独立して制御したい場合は、一つをPWM0チャンネル(例:GPIO 12)、もう一つをPWM1チャンネル(例:GPIO 13)に接続するという考え方になります。

GPIO 12とGPIO 13を使うことで、サーボとモーターを同時に制御できます。さて実行してゲームパットでサーボを操作してみましょう。いい感じにサクサク動きました。

 

TAMIYA 1/12RC XB ランチボックスカーのサーボに繋いでみる

問題なく動いたらTAMIYA 1/12RC XB ランチボックスカーのサーボに繋いてみましょう。①のサーボの3ピンは②に接続されています。

これを引き抜きます。①がGND、①が電源、③がPWMです。ここにRaspberry Pi 4のGPIOピンをさします。

サーボの3ピンに同じように①GND、②電源、③PWMがくるようにピンを接続します。

はい。このようにTAMIYA 1/12RC XB ランチボックスカーのサーボを操作できました。

簡単ですね。電源が3.3Vは正しくないようで、動作はぎこちないです。これも最終的にはRCカー側のバッテリーで動作させるので問題はなくなります。

 

USBコントローラとラズパイで、GPIOピンからハードウェアPWMを出力することで操作できるということがなんとなく理解できました。

次回に続く