从“水缸加水”到“平衡车”:用STM32 CubeMX和HAL库,5步搞定你的第一个PID闭环控制项目

张开发
2026/4/20 12:43:26 15 分钟阅读

分享文章

从“水缸加水”到“平衡车”:用STM32 CubeMX和HAL库,5步搞定你的第一个PID闭环控制项目
从“水缸加水”到“平衡车”用STM32 CubeMX和HAL库5步搞定你的第一个PID闭环控制项目平衡车、恒温杯垫、无人机悬停——这些看似复杂的控制系统核心都离不开PID算法。许多初学者在啃完理论公式后面对实际项目仍无从下手。本文将用STM32CubeMX和HAL库带你在5个步骤内构建完整的PID闭环系统避开那些教科书不会告诉你的实战陷阱。1. 硬件准备与CubeMX基础配置1.1 最小系统搭建平衡车项目需要这些核心部件STM32F103C8T6最小系统板蓝色药丸MPU6050六轴传感器约8元/个TB6612电机驱动模块12V直流减速电机带编码器更佳18650电池组两节串联注意电机驱动模块的VM引脚必须接电池正极VCC接5V逻辑电源避免控制器供电不足导致的异常抖动。1.2 CubeMX关键配置在CubeMX中完成这些必要设置/* PWM生成配置 */ TIM1-CCR1 0; // 初始化占空比为0% HAL_TIM_PWM_Start(htim1, TIM_CHANNEL_1); /* ADC采样配置 */ HAL_ADC_Start_DMA(hadc1, (uint32_t*)adc_buffer, 2); /* 串口调试输出 */ printf(PID Debug: Kp%.2f, Output%.2f\r\n, pid.Kp, output);配置要点选择正确的时钟源HSE 8MHz启用TIM1的PWM输出通道配置ADC规则组为连续转换模式开启DMA传输减轻CPU负担2. PID算法移植与HAL库适配2.1 从公式到代码经典位置式PID的HAL库实现typedef struct { float Kp, Ki, Kd; float integral; float prev_error; } PID_Controller; float PID_Update(PID_Controller* pid, float setpoint, float measurement) { float error setpoint - measurement; pid-integral error * dt; float derivative (error - pid-prev_error) / dt; pid-prev_error error; return pid-Kp * error pid-Ki * pid-integral pid-Kd * derivative; }2.2 三个易错点解决方案积分饱和限制integral累计范围if(pid-integral 1000) pid-integral 1000; else if(pid-integral -1000) pid-integral -1000;微分冲击对测量值进行低通滤波# Python模拟代码展示原理 filtered 0.9 * filtered 0.1 * new_value采样时间抖动使用硬件定时器触发HAL_TIM_Base_Start_IT(htim2); // 定时器中断中调用PID计算3. 参数调试实战技巧3.1 从零开始的调参路线图阶段目标操作预期现象纯P控制建立基础响应Kp从0.1开始倍增出现小幅振荡加入积分消除静差KiKp/采样周期超调量增大加入微分抑制振荡KdKp*采样周期/8响应曲线平滑3.2 串口可视化调试法使用匿名四轴地面站观察实时曲线发送数据格式printf($%.2f,%.2f,%.2f#, setpoint, actual, output);典型问题诊断持续低频振荡Kp过大需降低20%静差无法消除Ki过小加倍尝试高频抖动Kd过大减半处理4. 平衡车项目完整实现4.1 姿态解算关键代码MPU6050数据处理流程// 读取原始数据 HAL_I2C_Mem_Read(hi2c1, MPU6050_ADDR, ACCEL_XOUT_H, 1, raw_data, 14, 100); // 互补滤波 angle 0.98*(angle gyro*dt) 0.02*accel_angle;4.2 电机控制策略速度环角度环双PID结构------- 设定角度 -| 角度环 |- 目标速度 -| 速度环 |- PWM输出 ------- -------实现代码框架void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim htim2) { // 10ms定时中断 float angle Get_MPU6050_Angle(); float speed_target PID_Angle_Update(angle); float speed_actual Get_Encoder_Speed(); float pwm PID_Speed_Update(speed_target, speed_actual); __HAL_TIM_SET_COMPARE(htim1, TIM_CHANNEL_1, pwm); } }5. 进阶优化与故障排查5.1 常见问题速查表现象可能原因解决方案电机剧烈抖动电源功率不足更换大电流电池角度测量漂移传感器未校准执行零偏校准响应延迟明显PID计算周期过长优化代码结构5.2 性能提升技巧动态参数调整根据倾斜角度自适应调整Kppid.Kp BASE_KP fabs(angle) * ADAPTIVE_FACTOR;死区补偿消除电机启动静摩擦if(fabs(output) 0.1) output 0.15 * (output0?1:-1);软件限幅保护电机驱动电路pwm constrain(pwm, -900, 900); // 限制在±90%占空比调试平衡车那周实验室地板上全是车轮打滑的黑色痕迹。最惊喜的时刻是当Kd值调到0.8时原本摇晃的车体突然像被无形的手扶稳——那一刻真正理解了微分项预测未来的魔力。

更多文章