第 31 章 プロジェクト A:ライントレースカーを作る¶
本書の 卒業課題 です。これまで学んだすべての章 — 第 1 章の安全意識、Part II-IV の電気技術、Part V-VII の機械技術、Part III と Part VI のワークフロー — を 1 台のロボットに統合 します。
ここまで独立して学んできた要素が、「床に引いた黒い線に沿って自律走行する車」という 1 つの動くモノに結実します。完走したときに「自分で動くロボットを作れた」という成果が手元に残るのが、本書のゴールです。
この章で壊しやすいもの(統合ならではのリスク)
1. 完成イメージとブロック図¶
1.1 作るもの¶
- 大きさ:手のひらに乗るサイズ(約 180 × 140 × 60 mm、重量 200 g 前後)
- 走行方式:左右独立駆動の 2 輪差動駆動(後輪 2 + 前輪ボール 1 の 3 点接地)
- ライン検出:反射型フォトセンサ 2 個で床面の黒白を検知
- 制御:比例制御(P 制御) で、ラインからのズレ量に応じてモータ速度を補正
- 電源:単 3 × 4 本(6 V)で自走。マイコンは USB 給電(調整時)→ 単独走行時は同じ電池から 5V LDO 経由で給電
1.2 システム構成¶
2. 設計フェーズ(第 5 章 と 第 21 章 の統合)¶
2.1 電気要件(第 5 章 §2 の 4 分類)¶
| 分類 | 内容 |
|---|---|
| 入力 | 反射型フォトセンサ 2 個(アナログ出力、A0/A1) |
| 出力 | DC モータ 2 個(モータドライバ経由で PWM) |
| 通信 | なし(単独動作) |
| 電源 | 単 3 × 4 本(6V)を モータ用。ロジックは 5V LDO 経由 or USB |
2.2 機械要件(第 21 章 §2 の 5 分類)¶
| 項目 | 内容 |
|---|---|
| 可動部 | 左右車輪の独立駆動(2 輪)+ 前方ボールキャスター |
| 搭載物 | Arduino Uno、DRV8835、モータ 2、センサ 2、電池 4 本 = 合計 約 200 g |
| 外形 | 180 × 140 × 60 mm 以内 |
| 環境 | 室内フロア(硬い板、黒テープで引いた線) |
| 耐久 | デモ用途、1 日数回走らせる程度 |
2.3 BOM(第 5 章 §5、第 21 章 §6 の統合)¶
| カテゴリ | 型番 | 入手先 | 数量 | 小計 |
|---|---|---|---|---|
| マイコン | Arduino Uno R3(公式品) | Switch Science | 1 | 3,300 円 |
| モータドライバ | DRV8835 モジュール | Switch Science / Pololu | 1 | 650 円 |
| DC モータ | FA-130 相当 + ギアボックス | タミヤ ツインモーターギアボックス | 1 | 1,200 円 |
| 車輪 | タミヤ トラック&ホイールセット | タミヤ | 1 | 700 円 |
| 反射型センサ | TCRT5000 ブレークアウトモジュール | Amazon(中華、数個セット) | 2 | 600 円 |
| 電池ボックス | 単 3 × 4 本、スイッチ付き | 秋月 | 1 | 150 円 |
| 電池 | 単 3 アルカリ × 4 本 | 100 円ショップ | 1 | 200 円 |
| ブレッドボード | EIC-801 | 秋月 | 1 | 350 円 |
| ジャンパワイヤ | オス-オス・オス-メス | Amazon | 1 セット | 500 円 |
| 抵抗 | 330 Ω(センサ LED 用)、10 kΩ(プルアップ) | 秋月(セット品から) | 各数本 | — |
| 5V LDO(自立走行用) | AMS1117-5 モジュール | 秋月 or Amazon | 1 | 200 円 |
| シャシー材料 | アクリル板 3 mm、180 × 140 mm | レーザーカット外注 | 1 | 800 円 |
| モータマウント | 3D プリント(PLA) | 自家プリント or 外注 | 1 式 | 500 円 |
| ねじ・ナット類 | M3 × 8、M3 ナット、M3 スペーサ | 秋月/モノタロウ | 各数個 | 400 円 |
| 合計(目安) | 約 9,550 円 |
タミヤのキットで機械部品を省略できる
タミヤの 「カムプログラムロボット工作セット」 や 「ライントレーサー工作セット」 を買うと、シャシー・モータ・車輪・ボールキャスターが一式揃います。「機械設計からやりたい」読者は本書の設計フェーズで自作、「電気と制御に集中したい」読者はタミヤキットのシャシーを流用、と選べます。
3. 機械の製作・組立(Part VI の流れ)¶
3.1 シャシーのレイアウト¶
底板(180 × 140 mm アクリル)に以下を配置:
- 前方(端から 20 mm):TCRT5000 センサ 2 個を左右に並べる(中心間距離 30 mm)
- 中央:Arduino Uno と DRV8835 を重ねて配置
- 後方(端から 40 mm):モータ 2 個と車輪、その後ろに電池ボックス
- 前方中央下面:ボールキャスター(車体を 3 点で支える)
重心を低く(第 29 章 §4)保つため、電池は底板直上に配置。マイコンは中層、センサは底板前方の裏面に取り付けます。
3.2 製作手順(第 22 章)¶
- 底板をレーザーカット外注(DXF データ作成 → 業者発注 → 3〜7 日で納品)
- モータマウントを 3D プリント(積層方向は底板と平行になる向きで PLA、壁 3 周、充填 30%)
- ねじ穴・センサ穴のバリ取り(カッター or ヤスリ)
3.3 組立前チェック(第 23 章)¶
- BOM 突き合わせ(ねじの長さ M3 × 8 と M3 × 10 を混同していないか)
- 底板の寸法をノギスで実測(レーザーカット品、±0.2 mm 以内)
- モータマウントと底板のねじ穴が揃う
- 車輪がモータ軸に入る(D カット軸 + イモねじで固定、第 27 章)
3.4 組立(第 24 章)¶
順序:
- センサを底板裏面に取り付け(配線は底板の穴を通して上面に出す)
- モータを 3D プリントマウントに固定、マウントごと底板に取り付け
- 車輪をモータ軸に装着(D カット面にイモねじ先端が当たる向き、第 27 章 §4)
- 前方ボールキャスターを取り付け(底板裏面、前方中央)
- Arduino とブレッドボードを底板中央に固定(M3 スペーサー)
- 電池ボックスを底板後方に配置(両面テープ or ねじ)
- 手で各車輪を回してみる(スムーズに回る、引っかかりなし)
4. 電気の組立(第 6 章 + 第 13 章 の実装)¶
4.1 配線(DRV8835 の IN/IN モード、MODE ピンを GND)¶
【ロジック系】
Arduino 5V ─┬─ DRV8835 V_CC
├─ TCRT5000(L) VCC
└─ TCRT5000(R) VCC
Arduino D5 ── DRV8835 AIN1(左モータ PWM)
Arduino D6 ── DRV8835 AIN2(左モータ方向)
Arduino D9 ── DRV8835 BIN1(右モータ PWM)
Arduino D8 ── DRV8835 BIN2(右モータ方向)
Arduino A0 ── TCRT5000(L) OUT
Arduino A1 ── TCRT5000(R) OUT
DRV8835 MODE ── GND(IN/IN モード)
【モータ系・別電源】
電池ボックス V+ ── DRV8835 V_M
DRV8835 AOUT1, AOUT2 ── 左モータの 2 端子
DRV8835 BOUT1, BOUT2 ── 右モータの 2 端子
【GND 共通】
Arduino GND ─┬─ DRV8835 GND(ロジック側)
├─ TCRT5000(L) GND
├─ TCRT5000(R) GND
└─ 電池ボックス GND
4.2 配線の色分け(第 6 章 §4)¶
- 赤:5V(ロジック)
- オレンジ or 濃い赤:6V(モータ電源)
- 黒:GND
- 黄:PWM / 方向信号
- 緑:センサ信号
5. テスト前・テスト中チェック(第 7 章 + 第 8 章)¶
5.1 電源投入前(第 7 章 (A)〜(E) 全項目)¶
- (A) 配線シートと実機の目視照合
- (B) VCC-GND 間ショートチェック:Arduino 5V ⇔ GND、電池 V+ ⇔ GND、各 IC の VCC ⇔ GND、すべて鳴らない
- (C) ロジック電圧一致:全部品が 5V レール上にある(3.3V センサは未使用)
- (D) 電源分離:Arduino VCC(USB)と電池 V+ が 非導通、GND 同士が 導通(第 4 章 §5 の V 分離/GND 共通)
- (E) 極性:センサの LED、電解コンデンサ(使う場合)、ダイオードの向き
5.2 電源投入後(第 8 章)¶
- 投入直後 2 秒:煙・焦げ臭・音なし
- 2〜10 秒:VCC 5V ±5%、Arduino の電源 LED 点灯
- 10〜30 秒:モータドライバ・モータ温度 OK(触って 10 秒耐えられる)
- 30 秒〜1 分:Arduino IDE でスケッチ書き込み成功、シリアルモニタ出力
6. ソフトウェア:段階的に実装¶
6.1 ステップ 1:センサ読み取りだけ¶
まず、走らせずに センサが線を検知しているかを確認 します。
const int LEFT_SENSOR = A0;
const int RIGHT_SENSOR = A1;
void setup() {
Serial.begin(9600);
pinMode(LEFT_SENSOR, INPUT);
pinMode(RIGHT_SENSOR, INPUT);
}
void loop() {
int left = analogRead(LEFT_SENSOR);
int right = analogRead(RIGHT_SENSOR);
Serial.print("L=");
Serial.print(left);
Serial.print(" R=");
Serial.println(right);
delay(200);
}
期待される動作:
- センサを 白い紙 の上にかざす → 値が小さい(反射が多い → トランジスタが ON → A0 電圧が低い、100〜300)
- センサを 黒い線 の上にかざす → 値が大きい(反射が少ない → トランジスタが OFF → A0 電圧が高い、700〜950)
- 値の差が 300 以上あれば検知 OK
センサのバラツキを見て、しきい値(例:白黒の中間値 500)を決めます。
6.2 ステップ 2:モータの直進テスト¶
センサを無視して、両モータを同じ PWM で回して 直進するか を確認します。
const int AIN1 = 5; // 左 PWM
const int AIN2 = 6; // 左 方向
const int BIN1 = 9; // 右 PWM
const int BIN2 = 8; // 右 方向
const int BASE_SPEED = 130; // 0-255
void setMotor(int pwm_pin, int dir_pin, int speed) {
if (speed >= 0) {
analogWrite(pwm_pin, speed);
digitalWrite(dir_pin, LOW);
} else {
analogWrite(pwm_pin, -speed);
digitalWrite(dir_pin, HIGH);
}
}
void setup() {
pinMode(AIN1, OUTPUT); pinMode(AIN2, OUTPUT);
pinMode(BIN1, OUTPUT); pinMode(BIN2, OUTPUT);
delay(2000); // 起動後 2 秒待機(いきなり動き出さない)
}
void loop() {
setMotor(AIN1, AIN2, BASE_SPEED); // 左 前進
setMotor(BIN1, BIN2, BASE_SPEED); // 右 前進
}
期待される動作:
- 両輪が同じ速度で回り、車体が直進する
- 曲がってしまう場合 → 左右のモータ特性差、車輪径の差、または左右非対称の重量バランス
- 左右の PWM 値を微調整(例:左 130、右 125)
- または 第 25 章 §4.2 の「直進させているつもりが曲がる」で切り分け
6.3 ステップ 3:ON/OFF 制御(単純な方式)¶
センサの片方が線に乗ったら、その側を減速して曲げる単純なロジック。
const int THRESHOLD = 500; // 白黒の中間値
void loop() {
int left = analogRead(LEFT_SENSOR);
int right = analogRead(RIGHT_SENSOR);
bool leftOnLine = left > THRESHOLD;
bool rightOnLine = right > THRESHOLD;
if (leftOnLine && rightOnLine) {
// 両方が線上 → 直進(交差点 or 線の上)
setMotor(AIN1, AIN2, BASE_SPEED);
setMotor(BIN1, BIN2, BASE_SPEED);
} else if (leftOnLine) {
// 左が線上 → 左に曲がる
setMotor(AIN1, AIN2, 0);
setMotor(BIN1, BIN2, BASE_SPEED);
} else if (rightOnLine) {
// 右が線上 → 右に曲がる
setMotor(AIN1, AIN2, BASE_SPEED);
setMotor(BIN1, BIN2, 0);
} else {
// どちらも白 → 直進
setMotor(AIN1, AIN2, BASE_SPEED);
setMotor(BIN1, BIN2, BASE_SPEED);
}
delay(10);
}
期待される動作:
- ゆっくりしたライン(半径 200 mm 以上のカーブ)なら追従する
- 急カーブで 線から外れて戻ってくるのを繰り返す(ジグザグ走行)→ P 制御へ
6.4 ステップ 4:P 制御で滑らか走行¶
ON/OFF の「線から外れるまで真っ直ぐ、外れたら 90 度曲がる」をやめて、ズレ量に比例した補正 を加えます。
const int BASE_SPEED = 120; // 基準速度
const int Kp = 40; // 比例ゲイン(要調整、最初は 40 前後)
void loop() {
int left = analogRead(LEFT_SENSOR);
int right = analogRead(RIGHT_SENSOR);
// 誤差:ライン上の位置ズレ
// 両方 白(line なし)→ error = 0
// 左が黒 右が白 → error = 負(= 車体が右にズレている)
// 右が黒 左が白 → error = 正(= 車体が左にズレている)
int error = right - left;
// 比例補正(Kp を掛けて、255 を超えないように調整)
int adjust = (Kp * error) / 100;
int leftSpeed = BASE_SPEED + adjust; // 左にズレたら左を速く
int rightSpeed = BASE_SPEED - adjust;
// 飽和させる
leftSpeed = constrain(leftSpeed, 0, 255);
rightSpeed = constrain(rightSpeed, 0, 255);
setMotor(AIN1, AIN2, leftSpeed);
setMotor(BIN1, BIN2, rightSpeed);
delay(5);
}
7. 調整:ゲインとしきい値¶
7.1 Kp の調整¶
- Kp が小さすぎる(10〜20):反応が鈍く、急カーブで線から外れる
- Kp がちょうど良い(30〜60):滑らかに線を追従
- Kp が大きすぎる(100 以上):ジグザグに振動しながら走る(オーバーシュート)
Kp を 小さい値から徐々に上げて、「線を外れなくなる最小のゲイン」を探します。
7.2 BASE_SPEED の調整¶
- 速すぎる(200 以上):急カーブで慣性に負けて外れる → 速度を下げる or Kp を上げる
- 遅すぎる(80 以下):デッドバンドで回らない → BASE_SPEED を 100 以上に
7.3 センサしきい値の調整¶
走行する床面の色で値が変わります。走行前に §6.1 のコードで毎回確認 し、その場の THRESHOLD を決めると安定します。
7.4 ライン幅¶
- ライン幅 10〜20 mm が扱いやすい
- センサ間距離(30 mm)と同じくらいのラインが最も追従性が良い
8. トラブルシュート(よくある失敗)¶
モータが全く回らない
- 電池残量を確認(新品でも 5V 以下に落ちていないか)
- DRV8835 の MODE ピンが GND に繋がっているか(IN/IN モード)
- モータ単体を電池に直接繋いで回るか確認(第 25 章 §3 駆動系分離テスト)
モータは回るが線に追従しない
- センサ値の確認(§6.1 のコード)で白黒の差が 300 以上出ているか
- しきい値 THRESHOLD を白黒の中間に設定したか
- センサを 床面から 3〜5 mm の位置に取り付けているか(離れすぎると反射が弱まる)
線の上をジグザグに走る
- Kp が大きすぎる → 半分に下げる
- BASE_SPEED が速すぎる → 20 ほど下げる
- センサ間距離が ライン幅より狭すぎる → センサ間を広げる
直進させているつもりが曲がる
- 左右のモータ特性差、車輪径の差、重量バランス → 第 25 章 §4.2
- 左右 PWM 値のオフセット補正で暫定対処
モータ駆動中にマイコンがリセットする
- ブラウンアウト(第 4 章 §7)
- 電池分離(ロジック用 USB、モータ用 電池)で解決
- 自立走行させるなら 5V LDO で電池から安定した 5V を作る
センサが全部同じ値しか返さない
- TCRT5000 の LED 側(VCC + 電流制限抵抗 330 Ω) が正しく配線されているか
- 照明条件(強い蛍光灯下だと床の反射が変わる)
- センサモジュールの配線順(VCC / GND / OUT の順序、モジュールで違う)
走行中に電池が急に切れる
- モータ用電池(アルカリ)は 30 分程度で電圧が下がる → エネループ(Ni-MH)に変更
- 長時間運用なら リポ 2S(7.4V)+ 降圧 DCDC で 6V を作る(第 4 章 §4)
ラインが床に見えない/反応しない
- 黒マスキングテープの色が薄い(暗い灰色だとセンサが見分けない)→ 純黒の「電工用ビニルテープ」 が最も確実
- 床が模様入り → 無地の紙 or 白ボードの上にラインを引く
- 光沢のあるフローリング → センサ前面の LED が鏡面反射で飽和 → 走行面に紙を敷く
自分の影がラインセンサに写って誤検知
直上の蛍光灯と自分の立ち位置の関係で、ロボットの上に影が落ちてセンサが黒と誤認 → 急に曲がる・止まる。デモ時は 照明条件を一定に、または センサに遮光フード を 3D プリントで被せる。
モータを左右逆に配線していて、進みたいのに後退する
「前進のつもり」でスケッチ書いたが、実機は 逆に回って後退。配線を入れ替えるか、setMotor(BIN1, BIN2, -speed) のように符号を反転。最初のテストで確認すべき最初の項目。
センサの左右を入れ違えて配線した
LEFT_SENSOR = A0 だけど、A0 には物理的に右のセンサが繋がっている → ラインのズレ方向と補正方向が一致せず、ロボットがラインから遠ざかる(発散)。走行前に「左のセンサを手で隠して値の変化」を確認。
走行テスト中に机から落下
テーブルの端を認識しないので普通に落ちます。床でテスト するか、テーブルの端にブロック を置いて堤防にする。落下破損の修理は手間がかかるので、最初から床で走らせる。
Kp を調整している間に記憶が飛んで最適値を忘れる
「動いてる動いてる、次は Kp=50 か…、あれ、Kp=30 のときのほうが良かった気がする、値どこだっけ」あるある。試行ごとに Kp と感想を紙 or スマホメモに記録 する。5 回試したら最良の 2 つを絞ってさらに試す。
Arduino IDE を閉じたらスケッチが消えた
スケッチは ファイルとして保存されている はずだが、名前なしスケッチ(untitled)は IDE を閉じると消える。作業開始前に一度 Ctrl+S で名前を付けて保存。作業ごとにプロジェクトフォルダを分けると後日追跡できる。
充電式電池の電圧が公称より低くてドライバが動かない
Ni-MH(エネループ)は 1.2 V × 4 本 = 4.8 V(アルカリの 1.5 × 4 = 6.0 V より低い)。DRV8835 の V_M 最低 2 V は満たすが、モータのトルクは弱くなる。床のグリップが悪いと進まないこともある。Ni-MH × 6 本(7.2 V)に増やす選択肢。
ライン幅が広すぎて両センサが常に黒を読む
幅 40 mm 以上のラインだと、センサ間距離 30 mm では 両方が同時に黒に乗る → 誤差ゼロで直進するだけ。カーブに気付かず直進して外れる。ライン幅は 10〜20 mm が基本。
モータドライバ DRV8835 の MODE ピンを GND に繋ぎ忘れた
MODE ピンがオープン(浮き)のとき、DRV8835 の挙動は不定。必ず GND に繋ぐ(IN/IN モード)か VCC に繋ぐ(PHASE/ENABLE モード)。忘れると「動いたり止まったり」「正転しかしない」等の症状。
デモ当日にプログラムが書き込めない
- Arduino IDE のドライバが更新でリセットされた → 再インストール
- USB ケーブルが現場で見当たらない → 予備を常に持参
- デモ前日にすべて動作確認、本番用 USB ケーブルも確認。本番で「あれ?」が最大の恥ずかしさ
9. 発展課題¶
本書の範囲を超える、次のステップ:
9.1 PID 制御¶
P 制御に I(積分)と D(微分)を加えると、定常偏差の解消と振動の抑制ができます。ライブラリ:PID_v1(Arduino 定番)。
9.2 エンコーダ追加¶
モータ軸にエンコーダを付けて、車輪の回転数をフィードバック することで、PWM Duty ではなく「車輪速度」を直接制御できます。モータドライバ入れ替えは最小限で済みます。
9.3 複数センサ化¶
センサを 3〜5 個に増やして、ライン中央からのズレ量を細かく検出。アナログ値の重み付けで「位置誤差」をより正確に測れます。
9.4 無線制御の追加¶
ESP32 や Raspberry Pi Pico W に載せ替えて、スマートフォンや PC から Wi-Fi 経由で起動/停止 できるようにする。
9.5 交差点の識別¶
T 字路・十字路を検出して、進む方向を事前プログラムで指示するライントレーサー競技向けの応用。
10. 卒業の言葉¶
本書を通じて、あなたは次のスキルを獲得しました:
- 電気の基礎:オームの法則、絶対最大定格、データシート読解(Part I-II)
- 電気のワークフロー:設計 → 組立 → テスト前 → テスト中 → デバッグ(Part III)
- 電気系部品の扱い:LED、スイッチ、トランジスタ/MOSFET、モータ、PWM、サーボ、センサ、ステッピング(Part IV)
- 機械の基礎:材料、工具、公差(Part V)
- 機械のワークフロー:設計 → 製作 → 組立前 → 組立 → デバッグ(Part VI)
- 機械系部品の扱い:筐体、駆動部、マウント、バランス、配線管理(Part VII)
- AI エージェントとの協働:AI に任せる場所と、人間が判断する場所の切り分け
そして何より、「焼損事故を未然に防ぐ」 思考法 — NG 例をデータシート根拠で理解し、正しい設計へ繋げる — を身につけました。ここから先は、どんなロボットも 自分で設計できる 土台ができています。
次に作りたいロボットのアイデアを紙に書き出し、本書の設計フェーズ章(第 5 章・第 21 章)から、また始めてください。
This is the end of the tutorial. Good luck with your future robot projects!