# マイクロマックイーン プラス (micro:Maqueen Plus) 自動運転(ライントラッキング)
# 10.1. 目標
黒い路線が書かれているマップの上で、マイクロマックイーン プラス (micro:Maqueen Plus)を自律的にライントラッキングしながら、運転させるためのプログラミング方法を学習します。
# 10.2. 必要な機材
# PC利用時に必要な機材
No. | 名称 | 個数 | HW/SW | 用途 | 補足 |
---|---|---|---|---|---|
01 | micro:bit(v2)本体 | 1 | HW | マイクロマックイーン プラス (micro:Maqueen Plus)のコントロール用。 プログラミングはmicro:biに対して行う | - |
02 | micro:bit用 ケース | 1 | HW | micro:bit保護 | ※ 必須ではない |
03 | micro:bit用 USBケーブル | 1 | HW | micro:bitとPCの接続 | Type-AとType-C両方対応できると様々な端末で利用しやすい |
04 | マイクロマックイーン プラス (micro:Maqueen Plus) | 1 | HW | 車体本体 | - |
05 | 単3型乾電池 | 4 | HW | マイクロマックイーン プラスとmicro:bitへの電源供給 | - |
06 | Chromebook、MacOS、WindowsのPC | 1 | HW | MakeCode操作用 | - |
07 | Google Chrome | 1 | SW | MakeCodeアクセス用 | - |
08 | トラッキング用マップ | 1 | - | ライントラッキングテスト用 | - |
# タブレット・スマートフォン利用時に必要な機材
No. | 名称 | 個数 | HW/SW | 用途 | 補足 |
---|---|---|---|---|---|
01 | micro:bit(v2)本体 | 1 | HW | マイクロマックイーン プラスのコントロール用。 プログラミングはmicro:biに対して行う | - |
02 | micro:bit用 ケース | 1 | HW | micro:bit保護 | ※ 必須ではない |
03 | マイクロマックイーン プラス (micro:Maqueen Plus) | 1 | HW | 車体本体 | - |
04 | 単3型乾電池 | 4 | HW | マイクロマックイーン プラスとmicro:bitへの電源供給 | - |
05 | タブレット・スマートフォン | 1 | HW | micro:bitアプリ操作用 | - |
06 | micro:bit アプリ | 1 | SW | micro:bitアプリ操作用 | - |
07 | トラッキング用マップ | 1 | - | ライントラッキングテスト用 | - |
# 10.3. MakeCodeブロックの概要
マイクロマックイーン プラス (micro:Maqueen Plus)の底部には、5つのグレースケールセンサーがあり、グレースケールセンサーは近距離で物体表面のグレースケールを検知することが可能です。
センサーに二つの球体があり、透明な球体から赤外線を発光し、黒い球体で物体で反射された赤外線を受光し、暗い色は光(赤外線を含む)を吸収するため、暗い色の場合反射される光の量が少なくなり、それによってグレースケールを検知します。
No. | ブロック | 概要 | 機能 |
---|---|---|---|
01 | ![]() | ライントラッキング用ブロック | ・ センサーの選択:車体底部の5つのグレースケールセンサー(L2, L1, M, R1, R2) ・ 黒線検出時の戻り値:1 ・ 黒線非検出時の戻り値:0 |
01 | ![]() | グレースケールセンサー用ブロック | ・ センサーの選択:車体底部の5つのグレースケールセンサー(L2, L1, M, R1, R2) ・ 戻り値:検出されたグレースケール値 |
# 10.4. 動作イメージ
黒い路線に沿って、マイクロマクイーン (micro:Maqueen)が自動運転します。
参考情報
- マップを自作することも可能です。黒いテープなどである程度太い線を作ることが必要です。
# 10.5. プログラミング例 1
車体を円形の黒線マップに配置すると、車体は底部に設定された 3つのグレースケールセンサーを使用して、車体が黒線上を走行しているかどうかを検出します。黒線から外れた場合、進行方向を修正し、黒線に戻ります。
マイクロマックイーン プラス V2(micro:Maqueen Plus V2)には5つのグレースケールセンサーがあります。このプログラムでは、3つのセンサー、L1、M、R1を使用して黒い線を検出します。L2とR2はまだ使用されていません。
# MakeCodeプログラミング例(ブロック)
# MakeCodeプログラミング例(JavaScript)
function line_tracking() {
if (DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eL1) == 0 && DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eM) == 1 && DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eR1) == 0) {
DFRobotMaqueenPlusV2.controlMotor(MyEnumMotor.eAllMotor, MyEnumDir.eForward, 100)
} else if (DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eL1) == 1 && DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eM) == 1 && DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eR1) == 0) {
DFRobotMaqueenPlusV2.controlMotor(MyEnumMotor.eLeftMotor, MyEnumDir.eForward, 40)
DFRobotMaqueenPlusV2.controlMotor(MyEnumMotor.eRightMotor, MyEnumDir.eForward, 100)
} else if (DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eL1) == 1 && DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eM) == 0 && DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eR1) == 0) {
DFRobotMaqueenPlusV2.controlMotor(MyEnumMotor.eLeftMotor, MyEnumDir.eForward, 0)
DFRobotMaqueenPlusV2.controlMotor(MyEnumMotor.eRightMotor, MyEnumDir.eForward, 100)
} else if (DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eL1) == 0 && DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eM) == 1 && DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eR1) == 1) {
DFRobotMaqueenPlusV2.controlMotor(MyEnumMotor.eLeftMotor, MyEnumDir.eForward, 100)
DFRobotMaqueenPlusV2.controlMotor(MyEnumMotor.eRightMotor, MyEnumDir.eForward, 40)
} else if (DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eL1) == 0 && DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eM) == 0 && DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eR1) == 1) {
DFRobotMaqueenPlusV2.controlMotor(MyEnumMotor.eLeftMotor, MyEnumDir.eForward, 100)
DFRobotMaqueenPlusV2.controlMotor(MyEnumMotor.eRightMotor, MyEnumDir.eForward, 0)
}
}
DFRobotMaqueenPlusV2.I2CInit()
basic.forever(function on_forever() {
while (DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eL1) == 0 || DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eM) == 0 || DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eR1) == 0) {
line_tracking()
}
})
# MakeCodeプログラミング例(python)
def line_tracking():
if DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_L1) == 0 and DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_M) == 1 and DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_R1) == 0:
DFRobotMaqueenPlusV2.control_motor(MyEnumMotor.E_ALL_MOTOR, MyEnumDir.E_FORWARD, 100)
elif DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_L1) == 1 and DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_M) == 1 and DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_R1) == 0:
DFRobotMaqueenPlusV2.control_motor(MyEnumMotor.E_LEFT_MOTOR, MyEnumDir.E_FORWARD, 40)
DFRobotMaqueenPlusV2.control_motor(MyEnumMotor.E_RIGHT_MOTOR, MyEnumDir.E_FORWARD, 100)
elif DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_L1) == 1 and DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_M) == 0 and DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_R1) == 0:
DFRobotMaqueenPlusV2.control_motor(MyEnumMotor.E_LEFT_MOTOR, MyEnumDir.E_FORWARD, 0)
DFRobotMaqueenPlusV2.control_motor(MyEnumMotor.E_RIGHT_MOTOR, MyEnumDir.E_FORWARD, 100)
elif DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_L1) == 0 and DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_M) == 1 and DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_R1) == 1:
DFRobotMaqueenPlusV2.control_motor(MyEnumMotor.E_LEFT_MOTOR, MyEnumDir.E_FORWARD, 100)
DFRobotMaqueenPlusV2.control_motor(MyEnumMotor.E_RIGHT_MOTOR, MyEnumDir.E_FORWARD, 40)
elif DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_L1) == 0 and DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_M) == 0 and DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_R1) == 1:
DFRobotMaqueenPlusV2.control_motor(MyEnumMotor.E_LEFT_MOTOR, MyEnumDir.E_FORWARD, 100)
DFRobotMaqueenPlusV2.control_motor(MyEnumMotor.E_RIGHT_MOTOR, MyEnumDir.E_FORWARD, 0)
DFRobotMaqueenPlusV2.i2c_init()
def on_forever():
while DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_L1) == 0 or DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_M) == 0 or DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_R1) == 0:
line_tracking()
basic.forever(on_forever)
# MakeCodeプログラミング例のQRコード
# 10.6. プログラミング例 2
上記のプログラミングの例では、両側で2つのセンサーL2とR2を使用してなく、誤って車体が大きく黒線から外れた場合、黒線を見つけて走り続けることが難しくなります。
次の例では、プログラミングを改良し、5つのセンサーを使用し、車体が間違った経路にあることを検知した時、ラインに戻ることができるようにします。
# MakeCodeプログラミング例(ブロック)
# MakeCodeプログラミング例(JavaScript)
function line_tracking () {
if (DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eL1) == 0 && DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eM) == 1 && DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eR1) == 0) {
DFRobotMaqueenPlusV2.controlMotor(MyEnumMotor.eAllMotor, MyEnumDir.eForward, 100)
} else if (DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eL1) == 1 && DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eM) == 1 && DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eR1) == 0) {
DFRobotMaqueenPlusV2.controlMotor(MyEnumMotor.eLeftMotor, MyEnumDir.eForward, 40)
DFRobotMaqueenPlusV2.controlMotor(MyEnumMotor.eRightMotor, MyEnumDir.eForward, 100)
} else if (DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eL1) == 1 && DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eM) == 0 && DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eR1) == 0) {
DFRobotMaqueenPlusV2.controlMotor(MyEnumMotor.eLeftMotor, MyEnumDir.eForward, 0)
DFRobotMaqueenPlusV2.controlMotor(MyEnumMotor.eRightMotor, MyEnumDir.eForward, 100)
} else if (DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eL1) == 0 && DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eM) == 1 && DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eR1) == 1) {
DFRobotMaqueenPlusV2.controlMotor(MyEnumMotor.eLeftMotor, MyEnumDir.eForward, 100)
DFRobotMaqueenPlusV2.controlMotor(MyEnumMotor.eRightMotor, MyEnumDir.eForward, 40)
} else if (DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eL1) == 0 && DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eM) == 0 && DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eR1) == 1) {
DFRobotMaqueenPlusV2.controlMotor(MyEnumMotor.eLeftMotor, MyEnumDir.eForward, 100)
DFRobotMaqueenPlusV2.controlMotor(MyEnumMotor.eRightMotor, MyEnumDir.eForward, 0)
}
}
DFRobotMaqueenPlusV2.I2CInit()
basic.forever(function () {
while (DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eL2) == 0 && DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eR2) == 0) {
if (DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eL2) == 1 && DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eR2) == 0) {
DFRobotMaqueenPlusV2.controlMotor(MyEnumMotor.eLeftMotor, MyEnumDir.eForward, 0)
DFRobotMaqueenPlusV2.controlMotor(MyEnumMotor.eRightMotor, MyEnumDir.eForward, 100)
if (DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eL1) == 1 || DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eM) == 1 || DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eR1) == 1) {
line_tracking()
}
} else if (DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eL2) == 0 && DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eR2) == 1) {
DFRobotMaqueenPlusV2.controlMotor(MyEnumMotor.eLeftMotor, MyEnumDir.eForward, 100)
DFRobotMaqueenPlusV2.controlMotor(MyEnumMotor.eRightMotor, MyEnumDir.eForward, 10)
if (DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eL1) == 1 || DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eM) == 1 || DFRobotMaqueenPlusV2.readLineSensorState(MyEnumLineSensor.eR1) == 1) {
line_tracking()
}
}
line_tracking()
}
})
# MakeCodeプログラミング例(python)
def line_tracking():
if DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_L1) == 0 and DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_M) == 1 and DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_R1) == 0:
DFRobotMaqueenPlusV2.control_motor(MyEnumMotor.E_ALL_MOTOR, MyEnumDir.E_FORWARD, 100)
elif DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_L1) == 1 and DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_M) == 1 and DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_R1) == 0:
DFRobotMaqueenPlusV2.control_motor(MyEnumMotor.E_LEFT_MOTOR, MyEnumDir.E_FORWARD, 40)
DFRobotMaqueenPlusV2.control_motor(MyEnumMotor.E_RIGHT_MOTOR, MyEnumDir.E_FORWARD, 100)
elif DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_L1) == 1 and DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_M) == 0 and DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_R1) == 0:
DFRobotMaqueenPlusV2.control_motor(MyEnumMotor.E_LEFT_MOTOR, MyEnumDir.E_FORWARD, 0)
DFRobotMaqueenPlusV2.control_motor(MyEnumMotor.E_RIGHT_MOTOR, MyEnumDir.E_FORWARD, 100)
elif DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_L1) == 0 and DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_M) == 1 and DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_R1) == 1:
DFRobotMaqueenPlusV2.control_motor(MyEnumMotor.E_LEFT_MOTOR, MyEnumDir.E_FORWARD, 100)
DFRobotMaqueenPlusV2.control_motor(MyEnumMotor.E_RIGHT_MOTOR, MyEnumDir.E_FORWARD, 40)
elif DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_L1) == 0 and DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_M) == 0 and DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_R1) == 1:
DFRobotMaqueenPlusV2.control_motor(MyEnumMotor.E_LEFT_MOTOR, MyEnumDir.E_FORWARD, 100)
DFRobotMaqueenPlusV2.control_motor(MyEnumMotor.E_RIGHT_MOTOR, MyEnumDir.E_FORWARD, 0)
DFRobotMaqueenPlusV2.i2c_init()
def on_forever():
while DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_L2) == 0 and DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_R2) == 0:
if DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_L2) == 1 and DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_R2) == 0:
DFRobotMaqueenPlusV2.control_motor(MyEnumMotor.E_LEFT_MOTOR, MyEnumDir.E_FORWARD, 0)
DFRobotMaqueenPlusV2.control_motor(MyEnumMotor.E_RIGHT_MOTOR, MyEnumDir.E_FORWARD, 100)
if DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_L1) == 1 or DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_M) == 1 or DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_R1) == 1:
line_tracking()
elif DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_L2) == 0 and DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_R2) == 1:
DFRobotMaqueenPlusV2.control_motor(MyEnumMotor.E_LEFT_MOTOR, MyEnumDir.E_FORWARD, 100)
DFRobotMaqueenPlusV2.control_motor(MyEnumMotor.E_RIGHT_MOTOR, MyEnumDir.E_FORWARD, 10)
if DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_L1) == 1 or DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_M) == 1 or DFRobotMaqueenPlusV2.read_line_sensor_state(MyEnumLineSensor.E_R1) == 1:
line_tracking()
line_tracking()
basic.forever(on_forever)
# MakeCodeプログラミング例のQRコード