Arduino PID 巡线机器人:Android App 无线调参与手动控制
项目概述
本项目构建一个经典的 5 路红外巡线机器人,核心亮点在于:
- 实现完整 PID 闭环控制 (可选 P/PI/PD/PID),实现平滑、高速巡线
- 集成 HC-06 蓝牙模块 + MIT App Inventor 2 开发 Android App,支持:
— 实时无线修改 Kp/Ki/Kd 参数 (无需重新烧录)
— 手动遥控 (前进/后退/左转/右转/停止)
— 一键启动/停止巡线任务 - 模块化代码结构,易于扩展为迷宫求解机器人 (作者后续项目)
- 低成本 (~$75) 自制底盘:木板 + 360°连续旋转舵机 + 万向轮
硬件清单 (BOM)
| 组件 | 规格/型号 | 数量 | 备注 |
|---|---|---|---|
| Arduino Nano R3 | ATmega328P | 1 | 主控,体积小适合小车 |
| TCRT5000 4 路巡线模块 | 数字输出,板载电位器调阈值 | 1 | 提供 4 路传感器 |
| 单路 TCRT5000 模块 | 数字输出 | 1 | 第 5 路传感器,组成 5 路阵列 |
| HC-06 蓝牙模块 | 从机模式,9600/38400 波特率 | 1 | 与 Android 通信 |
| SM-S4303R 360°连续旋转舵机 | 5V, 1.0-2.0ms 脉宽对应正反转 | 2 | 左/右轮驱动 |
| 万向球轮 | 第三支撑点 | 1 | 灵活转向 |
| 4×AA 电池盒 (NiMH 推荐) | 5V/6V 供电 | 2 | 分离供电:一组给舵机,一组给 Arduino (Vin) |
| 木板底盘 | 80×80mm ×2 + 3M 命令贴/夹子固定 | 1 套 | 简易 DIY 结构 |
| LED + 按钮 | 指示灯 + 启动/校准按键 | 各 1 | Pin 13 / Pin 9 |
机械组装要点
- 舵机对齐:两舵机背靠背用 3M 命令贴/双面胶固成一体,输出轴同轴线
- 零点校准:上传测试代码发送 1500μs 脉宽,调整舵机底部黄色电位器直到车轮完全停转
- 脉宽映射:
- 右轮前进:1500μs (停) → 2000μs (全速)
- 左轮前进:1500μs (停) → 1000μs (全速) (安装方向相反)
- 传感器阵列安装:5 个传感器等间距排列 (约 1.5-2cm 间距),使任意时刻 1-2 个传感器覆盖黑线 (宽 1.5-2cm)
- 传感器编号:最左 0 → 最右 4,接线对应 Arduino Pin 12, 18(A4), 17(A3), 16(A2), 19(A5)
- 蓝牙模块:TX→Pin 10 (SoftwareSerial RX),RX→Pin 11 (TX),VCC/GND 接 5V/GND
核心算法:5 路传感器 → 误差值 → PID → 舵机脉宽
传感器状态编码与误差计算
传感器输出:HIGH (1) = 黑线,LOW (0) = 白底。理想居中时仅中间传感器 (S2) 检测到黑线:0 0 1 0 0
// 5 传感器状态 → 误差 error (-4 到 +4)
0 0 0 0 1 -> error = +4 (大幅右偏)
0 0 0 1 1 -> error = +3
0 0 0 1 0 -> error = +2
0 0 1 1 0 -> error = +1
0 0 1 0 0 -> error = 0 (完美居中)
0 1 1 0 0 -> error = -1
0 1 0 0 0 -> error = -2
1 1 0 0 0 -> error = -3
1 0 0 0 0 -> error = -4 (大幅左偏)
0 0 0 0 0 -> NO_LINE (丢线)
1 1 1 1 1 -> STOPPED (十字线/终点)
PID 控制器实现
float Kp = 50, Ki = 0, Kd = 0; // 可通过 App 无线修改
float P, I, D, PIDvalue, previousError = 0;
void calculatePID() {
P = error;
I = I + error; // 积分项 (小车通常置 0 避免超调)
D = error - previousError;
PIDvalue = (Kp * P) + (Ki * I) + (Kd * D);
previousError = error;
}
void motorPIDcontrol() {
// iniMotorPower = 250 (半速基准)
int leftSpeed = 1500 - iniMotorPower - PIDvalue; // 左轮:减去 PIDvalue 加速/减速
int rightSpeed = 1500 + iniMotorPower - PIDvalue; // 右轮:减去 PIDvalue
// 限幅保护
leftSpeed = constrain(leftSpeed, 1000, 2000);
rightSpeed = constrain(rightSpeed, 1000, 2000);
leftServo.writeMicroseconds(leftSpeed);
rightServo.writeMicroseconds(rightSpeed);
}
主循环状态机
#define STOPPED 0
#define FOLLOWING_LINE 1
#define NO_LINE 2
void loop() {
readLFSensors(); // 读取 5 路传感器 → 计算 error
// 特殊状态检测
if (allSensorsHigh()) mode = STOPPED; // 十字线/终点
else if (allSensorsLow()) mode = NO_LINE; // 丢线
switch (mode) {
case STOPPED: motorStop(); break;
case NO_LINE: motorStop(); motorTurn(LEFT, 180); break; // 原地掉头找线
case FOLLOWING_LINE:
calculatePID();
motorPIDcontrol();
break;
}
// 蓝牙指令处理 (非阻塞)
checkBTcmd();
manualCmd();
}
Android App (MIT App Inventor 2)
界面功能
- 手动控制区:前进(F)、后退(B)、左转(L)、右转(R)、停止(S) 按钮 → 发送字符
f/b/l/r/s - PID 滑块:Kp/Ki/Kd 三个滑块 (0-100) → 发送
p/XXi/XXd/XX - 启动巡线:按钮
g(Go) → 切换模式为 FOLLOWING_LINE - 虚拟启动键:复用硬件按钮功能
通信协议 (Arduino 端解析)
void checkBTcmd() {
while (BTSerial.available()) {
char c = BTSerial.read();
if (c == '\n') { commandComplete = true; break; }
command += c;
}
}
void manualCmd() {
if (!commandComplete) return;
switch (command[0]) {
case 'g': mode = FOLLOWING_LINE; break;
case 's': motorStop(); break;
case 'f': motorForward(); break;
case 'b': motorBackward(); break;
case 'l': motorTurn(LEFT, 30); motorStop(); break;
case 'r': motorTurn(RIGHT, 30); motorStop(); break;
case 'p': Kp = command.substring(2).toFloat(); break; // "p/50"
case 'i': Ki = command.substring(2).toFloat(); break;
case 'd': Kd = command.substring(2).toFloat(); break;
}
command = ""; commandComplete = false;
}
PID 调参实战指南
- 仅调 P:设 Ki=Kd=0,Kp 从 25 开始。过小→跟不上弯道;过大→左右剧烈振荡。找到临界振荡值再减半。
- 引入 D:Kd = Kp/2 起步。增加 D 抑制超调,减少振荡。若变不稳定则减小 D。
- 引入 I (可选):小车通常不需要 I 项 (稳态误差小),且会增加调试难度。如需消除长直道微小偏移,Ki 设极小值 (0.1-1)。
- 循环周期:主循环
delay影响采样率。建议 10-20ms 周期 (50-100Hz),通过逻辑分析仪或示波器观测 PWM 波形微调。
代码仓库与文件结构
GitHub: Mjrovai/MJRoBot-Line-Follower
项目包含多个 .ino 标签页:
robotDefines.h:引脚定义、常量、全局变量motorControl.ino:舵机脉宽封装、前进/后退/转向/停止lineSensor.ino:读取传感器、计算 errorpidControl.ino:PID 计算与电机输出bluetooth.ino:SoftwareSerial 通信、指令解析main.ino:setup/loop、状态机、启动等待逻辑
App 源文件:.aia (App Inventor 可编辑) 与 .apk (直接安装)。
常见问题与调试技巧
| 问题 | 排查步骤 |
|---|---|
| 车轮不转/单边转 | 检查舵机信号线、共地、1500μs 零点校准、电池电压 |
| 巡线跑偏/甩尾 | 传感器间距/黑线宽度不匹配 → 调整安装高度/间距;Kp 过大 → 减小 |
| 直线震荡 | 增加 Kd,减小 Kp;检查电源纹波 (舵机启动电流大 → 分离供电+大电容) |
| 十字路口不停 | 确认 5 路全 HIGH 触发 STOPPED;传感器灵敏度过高 → 调模块电位器 |
| 蓝牙收不到数据 | HC-06 波特率 (AT+BAUD8=115200) 与代码一致;TX/RX 交叉连接;Android 权限 |
| App 滑块无效 | 协议格式必须 "p/数值\n";检查 command.substring(2) 解析逻辑 |
扩展路线图:从巡线到迷宫求解
作者规划的第二阶段项目 Maze Solver Robot 将在本项目基础上增加:
- 超声波/TOF 测距传感器检测墙壁
- 左手/右手法则或 A* 算法实现自主探索建图
- 编码器 (或舵机内部电位器改装) 实现里程计定位
- 更强 MCU (ESP32/STM32) 运行微型 SLAM
结语
这个项目以"低成本、高教学价值"为核心,完整展示了从机械搭建、电路接线、传感器信号处理、PID 控制理论到无线调试界面的全栈开发流程。模块化代码与 App Inventor 开源 App 让初学者能快速上手体验闭环控制的魅力,也为进阶迷宫机器人奠定坚实基础。祝你调参顺利,巡线无忧!
制造工艺
- 树莓派接 KY‑033 循迹/门状态传感器:简易 Python 实现
- 树莓派传感器与执行器控制实战:加速度计、舵机与数据流
- 树莓派WiFi机器人:手机App远程控制实战
- 基于 Arduino、1Sheeld 与红外控制的万能安卓遥控器
- 工业级循线搬运机器人 — 物料自动化传输方案
- V4 版高速循迹机器人:Arduino Nano + 定制 PCB + PID 算法
- Arduino UNO 自制循迹小车:从零构建自主巡线机器人
- 在MATLAB/Simulink中掌握3D机器人夹爪的PID控制
- Wittmann Battenfeld发布WX153:面向大吨位注塑自动化的先进机器人线
- FANUC 扩充 SCARA 机器人阵容:六款新品,3-20 kg 负载,400-1100 mm 作业半径
- 利用先进自动化控制系统优化包装质量保障
- 21世纪机器人技术:分布式系统、远程呈现与太空探索