STM32F103C8T6 + TB6612 + HC-05:手把手教你调一个不跑偏的蓝牙小车(附PID参数整定心得)

张开发
2026/4/14 5:35:21 15 分钟阅读

分享文章

STM32F103C8T6 + TB6612 + HC-05:手把手教你调一个不跑偏的蓝牙小车(附PID参数整定心得)
STM32F103C8T6蓝牙小车PID调参实战从抖动到丝滑的进阶之路实验室里的小车又开始了它的魔鬼步伐——明明发送了直行指令却像喝醉酒一样左右摇摆最后歪歪扭扭地撞上墙角。这场景对于刚完成硬件组装的嵌入式开发者来说再熟悉不过。本文将带你深入PID参数整定的核心逻辑用系统化的调试方法驯服这匹野马。1. 从开环到闭环理解控制逻辑的本质当TB6612驱动电机开始转动时大多数初学者会直接进入PWM占空比调参的误区。实际上在开始PID调试前需要先建立完整的控制认知框架。电机转速控制存在三个关键层级开环控制PWM占空比→电机转速无反馈半闭环控制PWM占空比→编码器反馈→速度校准全闭环控制目标速度→PID计算→PWM输出→编码器反馈→动态调整// 典型开环控制代码示例 void Motor_SetSpeed(int speed) { int abs_speed (speed 0) ? -speed : speed; __HAL_TIM_SET_COMPARE(htim8, TIM_CHANNEL_1, abs_speed); if(speed 0) { HAL_GPIO_WritePin(AIN1_GPIO_Port, AIN1_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(AIN2_GPIO_Port, AIN2_Pin, GPIO_PIN_RESET); } else { HAL_GPIO_WritePin(AIN1_GPIO_Port, AIN1_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(AIN2_GPIO_Port, AIN2_Pin, GPIO_PIN_SET); } }调试提示在进入PID调试前先用开环控制确认电机转向和编码器计数方向一致。常见错误是正转时编码器值递减导致后续PID计算完全相反。2. PID三兄弟拆解参数调节的底层逻辑2.1 比例项(Kp)系统的肌肉记忆Kp值决定了系统对当前误差的反应强度。在STM32F103上调试时建议从以下步骤开始将Ki和Kd设为0逐步增加Kp直到出现持续振荡记录此时的临界Kp值Kcr初始工作Kp取Kcr的50-60%typedef struct { float Kp, Ki, Kd; float target; float actual; float error[3]; // 当前、上次、上上次误差 } PID_Controller; void PID_Init(PID_Controller* pid) { memset(pid, 0, sizeof(PID_Controller)); pid-Kp 5.0f; // 初始试探值 }2.2 积分项(Ki)消除稳态误差的慢性子当小车出现以下现象时需要调节Ki长时间运行后速度始终低于目标值负载变化时速度恢复缓慢调试技巧表格现象Ki调整方向典型修正幅度速度持续偏低增加Ki10%~20%超调后恢复慢减小Ki-15%~25%出现周期性抖动大幅减小Ki-50%以上2.3 微分项(Kd)系统的预见能力Kd参数对四轮小车的直线保持特别关键。通过以下代码可实现带滤波的微分项float PID_Calculate(PID_Controller* pid, float actual) { pid-actual actual; pid-error[0] pid-target - actual; // 低通滤波后的微分项 float d_term 0.2f * (pid-error[0] - pid-error[1]) 0.8f * pid-d_previous; pid-d_previous d_term; float output pid-Kp * pid-error[0] pid-Ki * pid-integral pid-Kd * d_term; pid-error[2] pid-error[1]; pid-error[1] pid-error[0]; return output; }3. 蓝牙控制与PID联调实战HC-05模块的串口控制需要与PID周期同步。推荐采用以下架构蓝牙指令解析层运动指令队列PID实时控制层// 蓝牙指令处理示例 void UART_Handler(uint8_t cmd) { static float target_speed 0; switch(cmd) { case F: // 前进 target_speed 10.0f; break; case B: // 后退 target_speed - 10.0f; break; default: target_speed 0; } // 限幅处理 target_speed fmaxf(-100.0f, fminf(100.0f, target_speed)); Update_PID_Target(target_speed); }注意蓝牙指令的响应延迟会影响PID效果。建议在TIM中断中固定周期调用PID计算而非在串口中断中直接处理。4. 典型问题排查手册4.1 电机抖动问题排查流程检查电源电压TB6612输入≥6V确认编码器接线无干扰双绞线最佳逐步测试先单独测试单个电机编码器再测试两个电机同步最后启用四个电机4.2 参数整定记录表调试阶段KpKiKd现象描述改进措施初始值5.000明显振荡降Kp至3.0第一次调3.00.50稳态误差5%Ki增至0.8第二次调3.00.80.2转向时超调Kd增至0.5最终参数2.80.70.4响应时间200ms微调Kp降低功耗4.3 高级技巧动态参数调整对于需要变速运行的小车可采用分段PID参数float Get_Adaptive_PID_Params(float current_speed) { if(current_speed 30.0f) { return (PID_Params){3.0f, 1.0f, 0.5f}; // 低速段参数 } else { return (PID_Params){2.0f, 0.5f, 0.8f}; // 高速段参数 } }实验室的灯光下看着小车终于能笔直地穿越测试场地那种成就感远比简单复制代码来得强烈。记得最后一次参数微调时将Kd从0.3调到0.35小车的转弯轨迹立刻变得干净利落——这就是控制算法的魅力所在。

更多文章