なんとなくRaspberry Pi Build HATを使ってラジコンカーを作りたくなったので、次はラジコンカーを作成。そのときの備忘録です。
作ったラジコンカー↓
まあまあシンプルに作れたので満足。 もっと部品点数を減らすことはできそうだけど、モーターをしっかり固定しないと簡単に動かなくなるし、ギアを使わないと遅すぎる。
主な材料、環境
ハード: Raspberry Pi 3 model B、Raspberry Pi Build HAT、F710ワイヤレス ゲームパッド 、レゴ、 ラズパイを固定するメイカープレート(3Dプリンタ出力)、バッテリー、バッテリーとBuild HATをつなぐケーブル
OS: Raspberry Pi OS (32bit)
レゴ組み立て方メモ
①黄色いプレートにモーターを固定
ギアは2ポッチの長さの棒でモーターに付ける。

②後輪を組み立てて、さっきの①と接続

③補強用のパーツを組み立てる
↓これを2つ

モーターにセット

④反対側にもセットして、後輪完成

⑤次は前輪部分を作成。
写真は黒いパーツの位置を間違えてる。本当は一つ内側。

⑥前輪の補強パーツ作成

⑦さっき作った⑥を黄色いプレートにセット、その後、補強パーツ⑥をセット

⑧モーターと⑤を水色のブロックで接続

ここまでで前輪と後輪周辺は完成

⑨ラズパイをメイカーブレードに固定して、適当に組み立て


上段の青枠を作成

中段と下段の青枠も作成

⑩先ほど作った⑨を⑧に接続

⑪黒いパーツで左右後ろを補強

完成

Build HATとモーターの接続
| ポート | 接続するモーター |
|---|---|
| A | 後輪用 Mアンギュラーモータ |
| B | 前輪用 Mアンギュラーモーター |
ゲームパッドでの動かし方
| ボタン | 内容 |
|---|---|
| 左スティック | 上で前進、下で後退。どのくらい押し込むかで速度が変わる |
| X | 前輪を左に向ける |
| B | 前輪を右に向ける |
プログラム
car.pyと名前を付けて保存し、実行。
run_to_positionを非同期で高頻度で呼ぶと例外が発生するので、ボタンを押したときだけ呼び出すようにした。
モーターに対して、plimit, biasを呼び出すことで反応が悪さを改善している。
import os
import pygame
from buildhat import Motor, Hat
from pygame.locals import *
def get_joy_axes_data():
axis_lx = round(joy.get_axis(0), 3)
axis_ly = round(joy.get_axis(1), 3)
axis_rx = round(joy.get_axis(3), 3)
axis_ry = round(joy.get_axis(4), 3)
hat_x = joy.get_hat(0)[0]
hat_y = joy.get_hat(0)[1]
axes_data = {
"L": (axis_lx, axis_ly),
"R": (axis_rx, axis_ry),
"HAT_X": hat_x,
"HAT_Y": hat_y,
}
print(axes_data)
return axis_lx, axis_ly, axis_rx, axis_ry, hat_x, hat_y
def init_motor(motor):
motor.release = False
motor.set_default_speed(100)
motor.plimit(1.0)
motor.bias(0.4)
os.environ["SDL_VIDEODRIVER"] = "dummy"
pygame.init()
pygame.joystick.init()
joy = pygame.joystick.Joystick(0)
joy.init()
hat = Hat()
print('Hat voltage = %f' % hat.get_vin())
motor_a = Motor('A')
motor_b = Motor('B')
init_motor(motor_a)
init_motor(motor_b)
while True:
pygame.time.wait(30)
for e in pygame.event.get():
if e.type == pygame.locals.JOYAXISMOTION or e.type == pygame.locals.JOYHATMOTION:
(axis_lx, axis_ly, axis_rx, axis_ry, hat_x, hat_y) = get_joy_axes_data()
if axis_ly < -0.2:
motor_a.start(-100 * -axis_ly)
elif axis_ly > 0.2:
motor_a.start(100 * axis_ly)
else:
motor_a.stop()
if e.type == pygame.locals.JOYBUTTONDOWN:
print('BUTTON %d DOWN' % e.button)
if e.button == 1:
motor_b.run_to_position(-60, blocking=False)
if e.button == 2:
motor_b.run_to_position(60, blocking=False)
elif e.type == pygame.locals.JOYBUTTONUP:
print('BUTTON %d UP ' % e.button)
if e.button == 1 or e.button == 2:
motor_b.run_to_position(0, blocking=False)