第1回、第2回でサーボやモーターをRaspberry Piに接続したUSBゲームコントローラーから操作してみました。今回は、Raspberry PiにてTAMIYA1/12RC XBランチボックスのサーボとモーターを同時制御してみましょう。
Groundは適当なピンから、GPIO12をサーボに、GPIO13をモータに接続します。サーボやモーターへの電源は、受信機 (TRU-08)から取り回します。
各種資料
TAMIYA1/12RC XB(完成モデル) ランチボックス (ITEM 57749)
https://d7z22c0gz59ng.cloudfront.net/cms/japan/download/rcmanual/58347.pdf
〇バッテリー:7.2Vニカドバッテリー
https://www.tamiya.com/japan/products/55085/index.html
〇ESC:TBLE-04S
https://d7z22c0gz59ng.cloudfront.net/cms/japan/download/rcmanual/45069.pdf
〇サーボ:TSU-01
https://www.tamiya.com/japan/products/10318/index.html
〇モーター:540
https://www.tamiya.com/japan/products/54358/index.html
〇受信機 (TRU-08)
https://d7z22c0gz59ng.cloudfront.net/cms/japan/download/rcmanual/45053.pdf
前回からのプログラムを改良
第1回、第2回のプログラムを使ってサーボとモーターを同時に制御するようにします。エラーハンドリングと終了処理を追加しています。
sudo nano joystick_controltest.py
import inputs
from gpiozero import PWMOutputDevice
from gpiozero.pins.pigpio import PiGPIOFactory
import time
import sys
# GPIOの設定(PiGPIOFactoryを使って精密制御)
factory = PiGPIOFactory()
# サーボとESCの初期化
try:
# サーボ(GPIOピン12)
servo = PWMOutputDevice(12, pin_factory=factory, frequency=50) # 50HzのPWM信号
# ESC(GPIOピン13)
esc = PWMOutputDevice(13, pin_factory=factory, frequency=50) # 50HzのPWM信号
except Exception as e:
print(f"GPIOの初期化中にエラーが発生しました: {e}")
sys.exit(1)
def set_servo_angle(angle):
"""
サーボの角度を設定します。角度は-90度から90度の範囲です。
"""
# 角度をデューティサイクルに変換
min_pulse_width = 0.5 / 1000
max_pulse_width = 2.4 / 1000
frame_width = 1 / 50 # 50Hzのフレーム幅
pulse_width = ((angle + 90) / 180) * (max_pulse_width - min_pulse_width) + min_pulse_width
duty_cycle = pulse_width / frame_width
servo.value = duty_cycle
def set_esc_speed(pulse_width_ms):
"""
ESCの速度を設定します。パルス幅はミリ秒単位で指定します。
"""
# パルス幅をデューティサイクルに変換
pulse_width_s = pulse_width_ms / 1000 # パルス幅を秒単位に変換
frame_width_s = 1 / 50 # フレーム幅(秒)
duty_cycle = pulse_width_s / frame_width_s # デューティサイクルの計算
esc.value = duty_cycle
def initialize_devices():
"""
サーボとESCを安全な初期状態に設定します。
"""
set_servo_angle(0) # サーボを中央に設定
set_esc_speed(1.5) # ESCを停止状態に設定
time.sleep(1) # 安定するまで待機
def shutdown_devices():
"""
サーボとESCを安全な停止状態に設定します。
"""
set_servo_angle(0) # サーボを中央に設定
set_esc_speed(1.5) # ESCを停止状態に設定
time.sleep(1) # 安定するまで待機
servo.close()
esc.close()
def main():
print("ジョイスティックを監視中...")
# デバイスの初期化
initialize_devices()
# ゲームパッドの取得
try:
gamepad = inputs.devices.gamepads[0]
print(f"ゲームパッドが接続されました: {gamepad}")
except IndexError:
print("エラー: ゲームパッドが接続されていません。プログラムを終了します。")
sys.exit(1)
try:
while True:
# イベントの取得
events = gamepad.read()
for event in events:
if event.ev_type == "Absolute":
if event.code == "ABS_X":
# サーボ操作
axis_value = event.state / 32767 # -1 から 1 の範囲に正規化
angle = axis_value * 90 # -90度から90度の範囲に変換
# 角度を -90 から 90 に制限
angle = max(min(angle, 90), -90)
set_servo_angle(angle)
#print(f"サーボの角度を {angle:.1f} 度に設定")
elif event.code == "ABS_RY":
# モーター操作
axis_value = event.state / 32767 # -1 から 1 の範囲に正規化
# デッドゾーンの設定
dead_zone = 0.05
if abs(axis_value) < dead_zone:
axis_value = 0
# パルス幅を1.4msから1.6msにマッピング
pulse_width = 1.5 + (axis_value * 0.1)
# パルス幅を1.4msから1.6msに制限
pulse_width = max(min(pulse_width, 1.6), 1.4)
set_esc_speed(pulse_width)
#print(f"ESCパルス幅を {pulse_width:.2f} msに設定")
# CPU使用率を下げるための短いスリープ
time.sleep(0.001)
except KeyboardInterrupt:
print("\nプログラムを終了します...")
except OSError:
print("エラー: ゲームパッドが切断されました。プログラムを終了します。")
except Exception as e:
print(f"エラーが発生しました: {e}")
finally:
# デバイスを安全な状態にシャットダウン
shutdown_devices()
print("デバイスを安全な状態に設定しました。")
if __name__ == "__main__":
main()
配線の簡単な説明
Groundは適当なピンから③④から取りました。GPIO12①をサーボに、GPIO13②をモータに接続します。サーボやモーターへの電源は、受信機 (TRU-08)から取り回します。
サーボ側の3ピン(黒、赤、白)も、黒はGround、赤は電源、白はPWMです。
ESC側(モーター)の3ピン(黒、赤、白)は、黒はGround、赤は電源、白はPWMです。
Raspberry PiのGPIO12番①をサーボ側の3ピンの白へ、Raspberry PiのGPIO13番②をESC側の3ピンの白へ、TRU-08の1番の真ん中の電源ピン⑤をサーボ側の3ピンの赤へ、TRU-08の2番の真ん中の電源ピン⑥をESC側の3ピンの赤へ。図にすると複雑で分かりにくいですね。
python3 joystick_controltest.py
よし動いた!