1. 项目概述:自平衡小车的魅力与挑战
第一次看到自平衡小车时,那种违反直觉的稳定性总让人着迷。这种通过传感器和电机不断微调保持直立的机器人,背后蕴含着经典的控制理论。作为创客圈经久不衰的项目,它既是PID算法的绝佳教学案例,也是硬件集成的综合实践平台。
我制作的这款壁障自平衡小车在基础功能上增加了超声波避障模块,当检测到前方障碍时会自动停车并鸣笛警示。整套系统成本控制在200元以内,主控采用常见的Arduino Nano,核心传感器包括MPU6050六轴陀螺仪和HC-SR04超声波模块。电机选用N20减速电机配合编码器,既保证扭矩又便于速度检测。
关键提示:自平衡项目对传感器精度要求极高,MPU6050建议购买正版模块,山寨货的零点漂移可能导致系统无法稳定
2. 硬件系统深度解析
2.1 核心部件选型对比
主控芯片的选择经历了三次迭代:最初尝试用STM32F103C8T6,虽然性能强劲但开发门槛较高;后来测试ESP8266,发现WiFi信号干扰导致控制周期不稳定;最终选定Arduino Nano,其16MHz主频和丰富的库支持完全满足需求。以下是关键部件参数对比表:
| 部件 | 型号 | 关键参数 | 成本 |
|---|---|---|---|
| 主控 | Arduino Nano | ATmega328P, 16MHz, 32KB Flash | ¥35 |
| 陀螺仪 | MPU6050 | ±2000°/s, I2C接口 | ¥18 |
| 电机 | N20减速电机 | 6V 200RPM 1:30减速比 | ¥25/个 |
| 驱动 | TB6612FNG | 1.2A持续电流, 双路输出 | ¥15 |
| 电池 | 18650锂电 | 3.7V 2600mAh 两节串联 | ¥30 |
2.2 机械结构设计要点
车体采用3D打印的镂空结构,重量控制在200g以内。重心高度经过精确计算:当重心距轮轴垂直距离为h,车轮半径为r时,理论最大加速度a需满足a < g*r/h(g为重力加速度)。我们设定h=8cm,r=3cm,得出a < 3.67m/s²,这意味着电机需要能在0.5秒内将车速从0加速到1.8m/s。
电机安装采用弹性联轴器连接轮轴,有效吸收微小振动。实测发现刚性连接会导致MPU6050持续收到高频振动干扰,使卡尔曼滤波失效。车轮表面包裹1mm厚硅胶套,摩擦系数μ≈0.6,确保急停时不会打滑。
3. 控制系统实现细节
3.1 传感器数据融合算法
MPU6050输出的原始数据包含严重噪声,我们采用互补滤波结合卡尔曼滤波的方案。具体实现时发现,单纯卡尔曼滤波在Arduino上计算耗时达8ms,严重影响控制频率。最终方案是:
cpp复制void updateAngle() {
// 加速度计角度计算(低频精确)
accAngle = atan2(ay, az) * RAD_TO_DEG;
// 陀螺仪积分(高频但漂移)
gyroRate = gx / 131.0;
gyroAngle += gyroRate * dt;
// 互补滤波
angle = 0.98*(angle + gyroRate*dt) + 0.02*accAngle;
}
这个5ms内完成的算法使控制周期稳定在100Hz。实测表明,滤波系数0.98/0.02的组合在静态时误差<0.5°,动态响应延迟<50ms。
3.2 PID参数整定实战
平衡控制采用串级PID结构:外环角度环(输入角度误差,输出目标速度),内环速度环(输入速度误差,输出PWM占空比)。调试时发现几个关键现象:
- 仅P控制时会出现等幅振荡,加入D项后系统趋于稳定但响应变慢
- I项可消除稳态误差,但过大会导致"积分饱和"
- 电机死区电压需单独补偿,我们测得N20电机启动电压为3.2V
最终参数通过齐格勒-尼科尔斯法整定:
cpp复制// 角度环PID
float anglePID(float error) {
static float integral = 0;
integral += error * dt;
integral = constrain(integral, -50, 50); // 抗饱和
float derivative = (error - lastError) / dt;
lastError = error;
return 15.0*error + 0.05*integral + 8.0*derivative; // Kp=15, Ki=0.05, Kd=8
}
4. 避障功能实现与优化
4.1 超声波模块的软件抗干扰
HC-SR04在近距离(<10cm)测量时容易出现40cm的跳变值。我们通过三次测量取中值,并增加以下校验逻辑:
cpp复制float getDistance() {
float d1 = pulseIn(echo, HIGH) / 58.0;
float d2 = pulseIn(echo, HIGH) / 58.0;
float d3 = pulseIn(echo, HIGH) / 58.0;
// 剔除异常值
if(abs(d1-d2)>20) return d3;
if(abs(d2-d3)>20) return d1;
return (d1+d2+d3)/3;
}
同时发现电机PWM噪声会影响超声波模块,解决方法是在测量时短暂关闭PWM输出,通过电机惯性维持短暂运行。
4.2 动态避障策略
当检测到30cm内障碍物时,系统分三个阶段响应:
- 减速阶段:以-1m/s²减速度制动,同时保持平衡
- 停止阶段:完全刹停,蜂鸣器鸣响0.5秒
- 绕行阶段:左轮后退、右轮前进,实现原地90°转向
实测避障响应时间从检测到完全停止约需300ms,制动距离与初速度关系如下:
| 速度(m/s) | 理论制动距离(cm) | 实测距离(cm) |
|---|---|---|
| 0.5 | 12.5 | 14.3 |
| 1.0 | 50.0 | 55.7 |
| 1.5 | 112.5 | 125.4 |
5. 常见问题与解决方案
5.1 小车持续单方向偏移
可能原因及排查步骤:
- 检查MPU6050安装是否水平:放置于水平面,测量X/Y轴加速度计输出应接近0g
- 校准陀螺仪零偏:静止状态下记录100次采样取平均值作为偏移量
- 测量电机转速一致性:给相同PWM值,测量两轮转速差应<5%
5.2 直立时出现高频抖动
典型解决方案:
- 降低角度环的D项系数(过大的D会放大传感器噪声)
- 在电机电源端并联1000μF电容消除电压波动
- 检查轮胎是否圆整,我的案例中发现3D打印轮毂有0.3mm偏心量导致周期性振动
5.3 电池电压下降后失控
锂电池电压从8.4V降到7V时会出现的问题:
- 电机扭矩下降导致平衡失效
- 部分型号MPU6050在<3.3V时数据异常
解决方案:
- 增加电压检测电路,低于7.2V时LED报警
- 选用LDO稳压芯片给MPU6050单独供电
- 程序中对PWM输出做电压补偿:PWM_actual = PWM_set * (8.4/Vbat)
6. 进阶改进方向
给想进一步提升的开发者几个实测有效的方案:
- 改用ESP32主控,利用其双核特性将控制算法和通信任务分离
- 增加BLE遥控功能,通过PID参数实时调整观察系统响应
- 改用IMU传感器如BMI160,其内置的FIFO可降低主控负担
- 尝试LQR控制算法,需要建立精确的动力学模型
我在第二版中尝试了方案1和3,控制周期提升到200Hz后,小车甚至能在5°斜坡上保持稳定。不过要注意ESP32的ADC线性度较差,需要软件校准或外接ADC芯片。
