1. 低成本平衡小车硬件选型指南做平衡小车最让人头疼的就是成本控制尤其是学生党或者刚入门的爱好者。我当年第一次做平衡小车的时候光电机就花了好几百结果发现根本没必要。后来摸索出一套性价比超高的方案核心就是STM32F103C8T6俗称蓝莓派和TB6612FNG这对黄金搭档。先说主控芯片STM32F103C8T6这颗芯片简直是学生党的福音。价格只要十几块钱但性能完全够用。它有3个通用定时器每个都能输出4路PWM这意味着我们可以轻松控制两个电机的正反转和速度。我实测过在72MHz主频下跑PID算法完全无压力响应速度能达到毫秒级。电机驱动模块我强烈推荐TB6612FNG比常用的L298N强太多了。这货最大能输出1.2A的连续电流峰值3.2A驱动TT马达绰绰有余。关键是效率高工作时基本不发热不像L298N动不动就烫手。价格也很亲民某宝上模块化的成品也就二十来块。TT马达的选择有讲究建议选6V减速电机。普通3V的扭矩太小根本撑不起小车重量。我试过几种规格最终锁定的是6V/200转的减速电机配合65mm橡胶轮平衡效果最好。注意要买双轴输出的版本方便安装编码器虽然我们这个方案暂时不用。2. 电路连接实战图解拿到元器件后第一步就是正确接线。这里我整理了一张超详细的接线表照着接绝对不会错STM32引脚TB6612FNG引脚功能说明PA6PWMA电机A PWM信号PA7AIN2电机A方向控制PB0AIN1电机A方向控制PB1BIN1电机B方向控制PB6PWMB电机B PWM信号PB7BIN2电机B方向控制3.3VSTBY使能端保持高电平GNDGND共地连接特别注意TB6612FNG的VM电机电源要单独供电千万别和单片机的3.3V混用我建议用两节18650锂电池串联供电电压刚好在7.4V左右经过驱动芯片内部稳压后正好适合6V的TT马达。MPU6050的接线更简单只需要四根线SCL接PB8SDA接PB9VCC接3.3VGND共地第一次通电前一定要用万用表检查所有连接特别是电源正负极不能接反。我当年就因为一个杜邦线接触不良调试了一整天找不到问题所在。3. PWM控制与电机驱动原理要让小车动起来PWM控制是核心。STM32的定时器配置其实没那么复杂我用的是TIM3和TIM4这两个通用定时器。具体配置代码如下void PWM_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; // 开启时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 配置PA6为复用推挽输出 GPIO_InitStructure.GPIO_Pin GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); // 定时器基础设置 TIM_TimeBaseStructure.TIM_Period 999; // 自动重装载值 TIM_TimeBaseStructure.TIM_Prescaler 71; // 72MHz/(711)1MHz TIM_TimeBaseStructure.TIM_ClockDivision 0; TIM_TimeBaseStructure.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, TIM_TimeBaseStructure); // PWM模式配置 TIM_OCInitStructure.TIM_OCMode TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse 0; // 初始占空比0 TIM_OCInitStructure.TIM_OCPolarity TIM_OCPolarity_High; TIM_OC1Init(TIM3, TIM_OCInitStructure); TIM_Cmd(TIM3, ENABLE); TIM_CtrlPWMOutputs(TIM3, ENABLE); }这段代码设置了1kHz的PWM频率实测这个频率下电机运行最平稳没有啸叫声。占空比调节范围0-1000对应0-100%的输出功率。TB6612FNG的方向控制逻辑很有意思AIN11, AIN20 → 正转AIN10, AIN21 → 反转AIN1AIN2 → 刹车实际调试时发现TT马达在PWM占空比低于30%时可能无法启动这是正常现象。解决方法是在代码里设置一个死区当目标速度小于阈值时直接输出0。4. 姿态传感器数据处理技巧MPU6050的数据处理是平衡小车的灵魂。原始数据直接读出来根本没法用需要经过三重处理卡尔曼滤波这个算法听起来高大上其实用现成的库就行。我推荐使用SimpleKalmanFilter这个轻量级库在STM32上跑毫无压力。SimpleKalmanFilter pitch_filter(0.1, 0.1, 0.01); float pitch pitch_filter.updateEstimate(raw_pitch);互补滤波作为卡尔曼滤波的补充可以这样实现float dt 0.01; // 10ms采样周期 float a 0.98; // 加速度计权重 angle a * (angle gyro * dt) (1-a) * accel;数据校准上电后先静止2秒自动校准零偏。我写了个自动校准函数void calibrateMPU6050() { float gyro_sum 0; for(int i0; i200; i){ gyro_sum getGyroY(); delay(10); } gyro_offset gyro_sum / 200; }实测发现MPU6050的温度漂移很严重建议每隔半小时重新校准一次。有个小技巧把传感器用泡沫胶固定在电路板上既能减震又能保温。5. PID控制算法实战调参PID参数调节是平衡小车最难的部分但掌握方法后其实很简单。先理解三个参数的作用P比例好比用手扶自行车把倾斜角度越大你用的力越大I积分解决长期偏差比如地面不平导致的持续倾斜D微分抑制震荡相当于预见小车要倒的速度我的调参步骤是这样的先把I和D设为0逐渐增大P直到小车能勉强立住但剧烈震荡加入D参数从小值开始增加直到震荡明显减弱最后加入I参数解决小车慢慢倒向一边的问题具体参数范围参考P: 20-40I: 0.1-0.5D: 1-5这里有个重要技巧变参数PID。当倾斜角度大于30度时自动增大P值这样小车倒下前会拼命自救if(abs(angle)30){ P default_P * 2; } else { P default_P; }6. 电源管理与低功耗优化平衡小车最烦人的就是电池续航问题。我的方案做了以下优化使用TPS63020升降压芯片效率高达95%电机PWM频率设为1kHz高于人耳听觉范围加入休眠模式当倾斜超过45度持续3秒自动断电实测两节18650可以连续工作4小时以上。电源部分电路特别要注意电机电源必须加1000uF以上的电容单片机电源要加0.1uF去耦电容所有电源线尽量短而粗7. 常见问题排查指南调试过程中我踩过不少坑这里总结几个典型问题问题1小车往一边偏检查MPU6050安装是否水平测量两个电机空载转速是否一致尝试交换电机接线排除硬件问题问题2站立时高频抖动降低P值增加D值检查PWM频率是否在1kHz左右确认电池电压充足低于6V会影响性能问题3响应迟钝检查主循环执行周期是否在10ms以内降低卡尔曼滤波的计算量尝试减少MPU6050的采样间隔最后分享一个实用技巧用蓝牙模块如HC-05实时传输调试数据配合手机APP可以边观察边调参效率提升十倍不止。