从零到一:STM32自平衡小车的硬件选型与PCB设计实战
1. 项目背景与核心需求自平衡小车是嵌入式开发领域的经典项目它完美融合了传感器技术、控制算法和硬件设计。用STM32实现自平衡小车不仅能深入理解PID控制原理还能掌握电机驱动、姿态解算等实用技能。这个项目特别适合想要进阶嵌入式开发的工程师和学生我从实际开发经验出发分享硬件选型和PCB设计的避坑指南。平衡小车的核心是负反馈控制系统就像人骑独轮车时不断调整身体姿态。系统需要实时获取车身倾斜角度通过MPU-6050、车轮转速通过编码器经过PID算法计算后输出PWM信号驱动电机。整个过程要在10ms内完成这对硬件响应速度和软件效率都提出了严格要求。2. 硬件选型实战2.1 主控芯片选择STM32F103C8T6是性价比极高的选择72MHz主频足够处理姿态解算和PID运算3个通用定时器1个高级定时器可同时处理2路编码器和4路PWM输出内置硬件I2C接口直接连接MPU-6050价格仅15元左右开发资源丰富实测中发现的高级定时器坑点TIM1/TIM8的PWM输出需要额外配置刹车寄存器TIM_CtrlPWMOutputs(TIM1, ENABLE); // 高级定时器专属配置编码器模式只能用通道1和通道2打板时千万别接错引脚2.2 姿态传感器选型MPU-6050是最经济的六轴传感器方案三轴加速度计测量重力方向三轴陀螺仪检测旋转角速度通过DMP库可直接输出融合后的姿态角选购时注意模块的AD0引脚决定I2C地址AD0接地0x68AD0接VCC0x69不要买10元以下的劣质模块我的第一个6050就因为质量问题无法触发中断2.3 电机与驱动方案带编码器的减速电机是关键我选用的是JGA25-370电机6V/300RPM编码器分辨率11线/转经4倍频后每转44脉冲电机轴径D型设计方便安装车轮TB6612驱动芯片比L298N更优效率更高可达95%内置过热保护和短路保护支持1.2A持续电流峰值3.2A接线注意事项VM接7-12V电源需单独供电VCC接5V逻辑电源STBY引脚必须拉高才能启用驱动2.4 电源系统设计推荐使用**2S锂电池7.4V**供电通过AMS1117-3.3给STM32供电电机驱动直接接电池电压增加100μF电解电容0.1μF陶瓷电容滤波实测中遇到的电源问题电机启停时电压跌落会导致STM32复位解决方法在3.3V稳压前端加220μF电容3. PCB设计实战3.1 原理图设计要点核心电路包括STM32最小系统复位电路晶振BOOT选择电机驱动接口PWM信号线串联100Ω电阻防干扰电机输出端加TVS二极管保护传感器接口MPU6050的I2C线上拉4.7k电阻编码器信号线加RC滤波100Ω100nF常见错误忘记连接NRST引脚导致无法下载程序编码器A/B相未接上拉电阻导致信号不稳定3.2 PCB布局布线技巧分层布局原则顶层主控传感器底层电机驱动电源左右分区左侧控制电路右侧功率电路关键布线规范电机走线宽度≥1mm晶振下方禁止走线I2C信号走差分对模拟地和数字地单点连接我的踩坑记录第一次打板忘记做泪滴振动导致焊盘脱落编码器信号线过长引入干扰后改为20mil线宽包地处理3.3 设计验证与打板投板前必做检查DRC规则检查线距≥8mil3D预览确认元件高度生成Gerber文件后用ViewMate检查推荐制板参数板厚1.6mm沉金工艺比喷锡更耐用绿色阻焊白色丝印4. 关键代码实现4.1 编码器速度读取配置TIM2/TIM3为编码器模式TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);速度计算函数int16_t Read_Encoder(uint8_t TIMx) { int16_t cnt; switch(TIMx){ case 2: cnt (int16_t)TIM2-CNT; TIM2-CNT0; break; case 3: cnt (int16_t)TIM3-CNT; TIM3-CNT0; break; default: cnt0; } return cnt; }4.2 PID控制器实现直立环角度PD控制float Vertical_PID(float target_angle, float current_angle, float gyro_y) { static float last_error; float error target_angle - current_angle; float derivative gyro_y; // 陀螺仪直接作为微分项 last_error error; return Kp*error Kd*derivative; }速度环位置式PIfloat Velocity_PID(float target, float current) { static float integral; float error target - current; integral error; if(integral 500) integral 500; // 积分限幅 if(integral -500) integral -500; return Kp*error Ki*integral; }4.3 电机控制函数PWM加载函数void Motor_Output(int16_t pwm1, int16_t pwm2) { // 方向控制 AIN1 (pwm10)? 1:0; AIN2 (pwm10)? 0:1; BIN1 (pwm20)? 1:0; BIN2 (pwm20)? 0:1; // PWM绝对值输出 __HAL_TIM_SET_COMPARE(htim1, TIM_CHANNEL_1, abs(pwm1)); __HAL_TIM_SET_COMPARE(htim1, TIM_CHANNEL_2, abs(pwm2)); }5. 调试经验分享5.1 PID参数整定步骤先调直立环Kp从50开始每次增加20直到小车出现低频抖动Kd从0.5开始抑制高频振荡再加入速度环速度环Kp取直立环Kp的1/10Ki Kp/200经验值转向环调试单独测试转向时先固定车身转向Kp建议在5-15范围内5.2 常见问题排查小车往一边偏检查MPU6050安装是否水平重新校准加速度计零偏电机异响不转测量TB6612的VM电压检查STBY引脚电平角度数据漂移在静止状态下校准陀螺仪零偏尝试调整互补滤波系数这个项目最让我头疼的是电源干扰问题后来通过以下措施解决电机电源与MCU电源完全隔离所有信号线增加磁珠滤波PCB大面积铺地并多点接地硬件设计往往需要多次迭代我的第一版PCB因为编码器接口设计错误不得不重新打板。建议初学者先用洞洞板搭建原型验证关键功能后再设计PCB。