今ある機材にメカナムホイールを足せば、以前から気になってた全方位移動ラジコンカーが作れるので、思い切ってホイールを買って作ってみた。
材料
車体側
- micro:bit
- Yahboom Super:bit(micro:bit拡張ボード)
- geek moter?(geek servoと書かれたレゴに接続できる赤いモーター) 4つ
- メカナムホイール 4つ
- レゴブロック
メカナムホイールはスイッチサイエンスで試験的に取り扱っているLEGOに接続できるプラスチックメカナムホイールを選択。
リモコン側
完成した結果
こんな感じ。
コントローラーにアナログスティックがあるので、全方向に緩急をつけて移動できるようにしてみた。
メカナムホイール固有の車っぽくないSFチックな動きが面白い。
灰色のギアがたまーに外れるのが玉にキズだけど、十分満足な出来栄え。(自画自賛)
基板は子供が直接に触れにくいように簡単にブロックで囲ってる。
下から見た写真。
モータとギア1セットの詳細。
モータはレゴブロックに直接つながるのは大変ありがたいけど、0.5ポッチ単位の調整がいるので正直少し扱いづらい。
失敗した点
その1
この形にたどり着くまでに2台作ってボツにした。
1台目はモーターにメカナムホイールを直付けしたけど、スピードが遅すぎて物足りなかったのでボツ。
2台目は複数のギアを組み込み、タイヤの回転を早くしたけど、パワーが弱すぎてほとんど横移動ができなかったのでボツ。
3台目でやっと納得のいくものが作れた。
レゴをベースにしているので、気楽に作ったり壊したりできるのがいいところ。
その2
前進/後退はできる。左右の旋回もできる。けど、横移動は左右逆向きに移動する。
原因はホイールの取り付けミスだった。
メカナムホイールには取り付けの向きがあるが、裏表を勘違いして全部逆に取り付けてしまった。
前後方向は問題がなかったので、最初、何を間違えたのかわからなかった。
その3
後日、次は前進/後退はできる。左右の旋回もできる。けど、横移動しようとすると移動せずにガタガタ震えるという現象に遭遇した。
ホイールの取り付けは問題ない。
原因は左側前後のホイールと基板との配線ミス。
あとからだったらホイールの動きを見たらわかるけど、最初、何を間違えたのか、またわからなかった。
プログラムの作成
次のページを参考に適当に作成。
toioでメカナムホイール制御を楽しむ
How a Mecanum Drive Works
コントローラー側のMakeCode用プログラム(python)
無線機能で左右スティックのXYとABボタンの押下状況を送信するプログラム。
XとYの範囲は-100〜100で、0が中央、-100が左の端(もしくは上の端)
ニュートラルでもキレイに0にはならないが、10以下くらいにはなる。
joy_b = 0 joy_a = 0 joy_ry = 0 joy_rx = 0 joy_ly = 0 joy_lx = 0 ch = 9 radio.set_group(ch) basic.show_number(ch) def on_forever(): global joy_lx, joy_ly, joy_rx, joy_ry, joy_a, joy_b # micro:bit用ジョイスティック付きコントローラーキット の仕様 # https://www.switch-science.com/catalog/5308/ # P2に0書き込み:左ジョイスティック選択 # P2に1書き込み:右ジョイスティック選択 # P0読み込み:ジョイスティックのアナログ値X方向(0〜1023) 0:左端 1023:右端 # P1読み込み:ジョイスティックのアナログ値Y方向(0〜1023) 0:下端 1023:上端 pins.digital_write_pin(DigitalPin.P2, 0) joy_lx = Math.map(pins.analog_read_pin(AnalogPin.P0), 0, 1023, -100, 100) joy_ly = Math.map(pins.analog_read_pin(AnalogPin.P1), 0, 1023, -100, 100) pins.digital_write_pin(DigitalPin.P2, 1) joy_rx = Math.map(pins.analog_read_pin(AnalogPin.P0), 0, 1023, -100, 100) joy_ry = Math.map(pins.analog_read_pin(AnalogPin.P1), 0, 1023, -100, 100) if input.button_is_pressed(Button.A): joy_a = 1 else: joy_a = 0 if input.button_is_pressed(Button.B): joy_b = 1 else: joy_b = 0 radio.send_value("LX", joy_lx) radio.send_value("LY", joy_ly) radio.send_value("RX", joy_rx) radio.send_value("RY", joy_ry) radio.send_value("A", joy_a) radio.send_value("B", joy_b) basic.forever(on_forever) def on_forever2(): basic.pause(1000) serial.write_value("LX", joy_lx) serial.write_value("LY", joy_ly) serial.write_value("RX", joy_rx) serial.write_value("RY", joy_ry) serial.write_value("A", joy_a) serial.write_value("B", joy_b) basic.forever(on_forever2)
車体側のMakeCode用プログラム(python) 通常版
基本的には無線機能で受け取った左スティックの方向に合わせて、モータを制御するだけ。
Super:bitを扱うので、予め拡張機能 https://github.com/lzty634158/SuperBit の追加が必要。
def update_servo_value(): magnitude = Math.sqrt((joy_lx/100.0)**2 + (joy_ly/100.0)**2) magnitude = Math.min(magnitude, 1.0) base_angle = Math.atan2(joy_ly, joy_lx) angle = base_angle - Math.PI / 4 rightX = joy_rx / 100.0 v1 = magnitude * Math.cos(angle) + rightX v2 = magnitude * Math.sin(angle) - rightX v3 = magnitude * Math.sin(angle) + rightX v4 = magnitude * Math.cos(angle) - rightX # 計算確認用のため日頃はコメントアウト # serial.write_value("joy_lx", joy_lx) # serial.write_value("joy_ly", joy_ly) # serial.write_value("joy_rx", joy_rx) # serial.write_value("magnitude", magnitude) # serial.write_value("base_angle", base_angle) # serial.write_value("angle", angle) # serial.write_value("v1", v1) # serial.write_value("v2", v2) # serial.write_value("v3", v3) # serial.write_value("v4", v4) # left front SuperBit.motor_run(SuperBit.enMotors.M1, v1 * 255) # right front SuperBit.motor_run(SuperBit.enMotors.M3, v2 * 255) # left rear SuperBit.motor_run(SuperBit.enMotors.M2, v3 * 255) # right rear SuperBit.motor_run(SuperBit.enMotors.M4, v4 * 255) def on_received_value(name, value): global joy_lx, joy_ly, joy_rx, joy_ry, joy_a, joy_b if name == "LX": joy_lx = value if name == "LY": joy_ly = value if name == "RX": joy_rx = value if name == "RY": joy_ry = value if name == "A": joy_a = value if name == "B": joy_b = value update_servo_value() radio.on_received_value(on_received_value) joy_ry = 0 joy_rx = 0 joy_ly = 0 joy_lx = 0 joy_a = 0 joy_b = 0 radio_ch = 9 radio.set_group(radio_ch) basic.show_string(str(radio_ch)) def on_forever(): basic.pause(1000) serial.write_value("LX", joy_lx) serial.write_value("LY", joy_ly) serial.write_value("RX", joy_rx) serial.write_value("RY", joy_ry) serial.write_value("A", joy_a) serial.write_value("B", joy_b) basic.forever(on_forever) number = 0 def test(): basic.pause(1000) dummy_lx = 0 dummy_ly = 0 dummy_rx = 0 dummy_ry = 0 dummy_a = 0 dummy_b = 0 global number if number % 5 == 0: dummy_lx = 100 elif number % 5 == 1: dummy_lx = -100 if number % 4 == 0: dummy_ly = 100 elif number % 4 == 1: dummy_ly = -100 number = number + 1 on_received_value("LX", dummy_lx) on_received_value("LY", dummy_ly) on_received_value("RX", dummy_rx) on_received_value("RY", dummy_ry) on_received_value("A", dummy_a) on_received_value("B", dummy_b) # 疑似受信テスト用のため日頃はコメントアウト # basic.forever(test)
車体側のMakeCode用プログラム(python) メンテナンス版
2つのアナログスティックでメカナムホイールを直接操作したかったので作成した誰得プログラム。自分用。
Super:bitを扱うので、予め拡張機能 https://github.com/lzty634158/SuperBit の追加が必要。
左スティック
上:左前輪(正回転) 下:左前輪(逆回転)
右:左後輪(正回転) 左:左後輪(逆回転)
右スティック
上:右前輪(正回転) 下:右前輪(逆回転)
右:右後輪(正回転) 左:右後輪(逆回転)
def update_servo_value(): # left front SuperBit.motor_run(SuperBit.enMotors.M1, joy_ly / 100.0 * 255) # right front SuperBit.motor_run(SuperBit.enMotors.M3, joy_ry / 100.0 * 255) # left rear SuperBit.motor_run(SuperBit.enMotors.M2, joy_lx / 100.0 * 255) # right rear SuperBit.motor_run(SuperBit.enMotors.M4, joy_rx / 100.0 * 255) def on_received_value(name, value): global joy_lx, joy_ly, joy_rx, joy_ry, joy_a, joy_b if name == "LX": joy_lx = value if name == "LY": joy_ly = value if name == "RX": joy_rx = value if name == "RY": joy_ry = value if name == "A": joy_a = value if name == "B": joy_b = value update_servo_value() radio.on_received_value(on_received_value) joy_ry = 0 joy_rx = 0 joy_ly = 0 joy_lx = 0 joy_a = 0 joy_b = 0 radio_ch = 9 radio.set_group(radio_ch) basic.show_string(str(radio_ch))