マイクロビットで動きを制御する、二足歩行ロボットをつくります。
第一回の記事(こちら)で、どのようなロボットにするかを考え、それを踏まえて、マイクロビットで4つのサーボモーターを制御できることを確認し、回路構成を決定しました。
また、第二回の記事(こちら)では、3Dプリンタを使って、実際にロボットの筐体を作り、組み立てました。
今回は、マイクロビット用のプログラムを作成し、実際にロボットを歩かせてみます。
サーボモーターの角度調整用プログラム
まずは、初期状態でロボットがまっすぐ立っている状態になるように、各サーボモーターの角度(初期値)を調整しなければなりません。
そのために、以下のようなスケッチを作りました。
このスケッチでは、マイクロビットとiPhoneを無線接続し、iPhoneのコントロール画面で、各サーボモーターの角度を少しずつ動かします。
ちょうどまっすぐになった時の、サーボモーターの角度をメモしておきます。
画像だと見にくいので、JavaScriptのソースも掲載しておきます。
function move_servo (サーボ番号: number, 角度: number) { if (サーボ番号 == 0) { pins.servoWritePin(AnalogPin.P0, 角度) } if (サーボ番号 == 1) { pins.servoWritePin(AnalogPin.P1, 角度) } if (サーボ番号 == 2) { pins.servoWritePin(AnalogPin.P2, 角度) } if (サーボ番号 == 3) { pins.servoWritePin(AnalogPin.P8, 角度) } } devices.onGamepadButton(MesDpadButtonInfo.ADown, function () { サーボ番号 += 1 if (サーボ番号 > 3) { サーボ番号 = 0 } basic.showNumber(サーボ番号) }) devices.onGamepadButton(MesDpadButtonInfo.BDown, function () { サーボ番号 += -1 if (サーボ番号 < 0) { サーボ番号 = 3 } basic.showNumber(サーボ番号) }) devices.onGamepadButton(MesDpadButtonInfo.CDown, function () { angle[サーボ番号] = angle[サーボ番号] - 1 move_servo(サーボ番号, angle[サーボ番号]) basic.showNumber(angle[サーボ番号]) }) devices.onGamepadButton(MesDpadButtonInfo.DDown, function () { angle[サーボ番号] = angle[サーボ番号] + 1 move_servo(サーボ番号, angle[サーボ番号]) basic.showNumber(angle[サーボ番号]) }) let サーボ番号 = 0 let angle: number[] = [] angle = [60, 60, 60, 60] for (let サーボ番号 = 0; サーボ番号 <= 3; サーボ番号++) { basic.showNumber(3 - サーボ番号) move_servo(サーボ番号, angle[サーボ番号]) basic.pause(1000) } サーボ番号 = 0 basic.showNumber(サーボ番号)
ロボットをまっすぐ歩かせるプログラム
ロボットを歩かせるためのプログラムは以下のとおりです。
そこそこ長いプログラムですが、ただ単にロボットがまっすぐ歩くだけです。
第一回の記事で、ロボットを歩かせるための各サーボモーターの動きを説明しましたが、その動きを繰り返しています。
また、ロボットの動きをなめらかにするために、サーボモーターを動かすときには1度ずつ動くように、関数をつくりました。
なお、「angle」という配列に、各サーボモーターの角度(初期値)を設定していますが、この値は、先ほどのプログラムで調整した値です。
JavaScriptのソースは以下のとおりです。
function move_servo (サーボ番号: number, 角度: number) { if (サーボ番号 == 0) { pins.servoWritePin(AnalogPin.P0, 角度) } if (サーボ番号 == 1) { pins.servoWritePin(AnalogPin.P1, 角度) } if (サーボ番号 == 2) { pins.servoWritePin(AnalogPin.P2, 角度) } if (サーボ番号 == 3) { pins.servoWritePin(AnalogPin.P8, 角度) } } function cnt_servo (サーボ番号: number, 角度1: number, 角度2: number) { if (角度1 < 角度2) { for (let index = 0; index <= 角度2 - 角度1; index++) { move_servo(サーボ番号, angle[サーボ番号] + 角度1 + index) basic.pause(25) } } else { for (let index = 0; index <= 角度1 - 角度2; index++) { move_servo(サーボ番号, angle[サーボ番号] + 角度1 - index) basic.pause(25) } } } function cnt_2servo (サーボ番号1: number, サーボ番号2: number, 角度1: number, 角度2: number) { if (角度1 < 角度2) { for (let index = 0; index <= 角度2 - 角度1; index++) { move_servo(サーボ番号1, angle[サーボ番号1] + 角度1 + index) move_servo(サーボ番号2, angle[サーボ番号2] + 角度1 + index) basic.pause(25) } } else { for (let index = 0; index <= 角度1 - 角度2; index++) { move_servo(サーボ番号1, angle[サーボ番号1] + 角度1 - index) move_servo(サーボ番号2, angle[サーボ番号2] + 角度1 - index) basic.pause(25) } } } function init_angleA () { angle = [85, 92, 69, 89] } function init_angleB () { angle = [54, 66, 59, 58] } let angle: number[] = [] init_angleA() for (let サーボ番号 = 0; サーボ番号 <= 3; サーボ番号++) { basic.showNumber(3 - サーボ番号) move_servo(サーボ番号, angle[サーボ番号]) basic.pause(1000) } basic.showIcon(IconNames.Happy) basic.pause(1000) cnt_servo(2, 0, 30) cnt_servo(0, 0, -25) cnt_2servo(3, 1, 0, -25) cnt_servo(0, -25, 0) cnt_servo(2, 30, 0) basic.forever(function () { cnt_servo(0, 0, -30) cnt_servo(2, 0, 25) cnt_2servo(1, 3, -25, 25) cnt_servo(2, 25, 0) cnt_servo(0, -30, 0) cnt_servo(2, 0, 30) cnt_servo(0, 0, -25) cnt_2servo(3, 1, 25, -25) cnt_servo(0, -25, 0) cnt_servo(2, 30, 0) })
動作結果
このプログラムを動かした結果は以下のとおりです。
かなりあぶなっかしいですが、なんとか歩いています。
もっと安定して歩くようにするためには、筐体の形(特に足)などを、もっと工夫しないといけなさそうです。
最終的には、このロボットをiPhoneから操作できるようにしたいのですが、まだまだ先は長そうです。