上一节解决了“PID 公式怎样计算”,这一节把算法接入真实的双轮速度链。编码器负责测量,低通滤波抑制抖动,两个 PID 分别修正左右电机,串口曲线用于判断闭环是否正常。
本篇目标与控制链
该文件要实现的现象是:左右轮各自跟踪目标速度,同时把原始编码器速度与滤波后速度输出到串口。
左右编码器速度 → 一阶低通 → 两个增量式 PID → 输出限幅 → 左右电机命令 → 串口曲线观测文件中的 30 cm/s、40 cm/s 只出现在目标设置和注释中。若编码器模块没有完成脉冲数到线速度的换算,这些数值仍只是控制量,不能直接当作已标定物理速度。
为什么左右轮要分开控制
代码建立 pid_speed_left 和 pid_speed_right 两个实例。双轮机械阻力、电机常数、减速箱间隙和轮径很难完全一致,只用一个输出会导致直行时持续跑偏。
两个控制器允许独立目标和独立反馈:
left_output = pid_calculate_incremental(&pid_speed_left, filtered_speed_left);right_output = pid_calculate_incremental(&pid_speed_right, filtered_speed_right);最终分别传给 Motor_SetSpeed()。双通道结构已经明确,但接入时仍要核对电机接口、PWM 范围和正负方向定义。
一阶低通滤波
源码对左右速度分别使用指数平滑:
filtered = alpha * raw + (1.0f - alpha) * filtered;新值权重 alpha 越小,曲线越平滑,但响应越慢。滤波后的相位滞后会被 PID 视作“电机还没跟上”,可能推动输出继续增大。
因此滤波参数不能只靠观察曲线是否漂亮。应同时记录原始速度、滤波速度、目标值和输出,比较噪声衰减与上升时间。
滤波状态是文件级 static 变量。它会跨任务调用保留,但没有公开复位接口。模式切换、编码器故障恢复或重新起步时,旧滤波值可能短暂影响新控制过程。
PID_Init() 做了什么
初始化函数分别配置左右轮参数和输出限制,再调用 pid_set_target() 写入不同目标值。
PID_Init() 通过 pid_app.h 调用目标设置接口。接入工程时必须沿声明与链接关系确认它最终使用哪一套 PID 实现;函数同名并不能保证目标切换行为相同。
参数注释称其为实调结果,但没有记录:
- 实际控制周期;
- 轮径、减速比和编码器分辨率;
- 电池电压、车体负载和地面条件;
- 阶跃响应、稳态误差和输出饱和比例。
因此这些数值只能视为当前示例配置,不能当作可移植的调参答案。
PID_Task() 的逐步执行
任务首先读取左右编码器的 speed_cm_s,再进行独立低通。随后执行两个增量式控制器,将结果送入两个电机对象。
文件还保留了航向修正的注释代码:
// pid_set_target(&pid_speed_left, v + output_yaw);// pid_set_target(&pid_speed_right, v - output_yaw);这表达了“基础速度 ± 转向修正”的差速思路,但当前代码处于注释状态,不能写成已启用的航向闭环。
任务末尾通过 my_printf() 输出目标和滤波速度。串口打印若为阻塞式,可能拉长控制周期;接入非抢占式调度器时,应降低打印频率或使用发送队列。
增量式控制器与限幅
增量式 PID 把误差变化转换成输出变化,适合连续速度调节。它仍需要三个工程条件:
- 固定且可测的任务周期;
- 与电机接口一致的输出上下限;
- 故障或停车时明确复位内部输出。
若电机驱动已经饱和,而 PID 内部输出仍继续累加,解除饱和后可能出现较长恢复过程。应记录限幅前后输出,必要时加入跟踪式或条件式抗饱和。
推荐接入非抢占式调度器
速度环任务应完成一次采样和计算后立即返回:
void SpeedControlTask(void *context){ Encoder_Update(); PID_Task();}真实周期应由调度器定义,并和编码器测速窗口保持一致。不要在任务内调用阻塞延时,也不要每一拍打印大量文本。
启动顺序建议为:编码器有效性检查 → 低输出开环方向测试 → 单轮闭环 → 双轮闭环 → 再叠加航向或循迹修正。
常见故障定位
| 现象 | 优先检查 |
|---|---|
| 一侧轮速越调越快 | 编码器符号与电机输出符号是否构成负反馈 |
| 曲线很平滑但响应迟钝 | alpha 是否过小,任务周期是否过长 |
| 目标改变时输出跳变 | 目标接口是否重置 PID,滤波状态是否保留 |
| 左右同目标仍跑偏 | 两侧反馈换算、机械差异和独立参数 |
| 偶发周期变长 | 串口输出是否阻塞,任务是否被其他函数占用 |
首次上电必须架空车轮,并从受限输出开始。具体限值只能来自电机、驱动和定时器配置,当前文件没有足够硬件证据。
接入真实小车前还要确认什么
| 检查项 | 当前代码表现 | 接入要求 |
|---|---|---|
| 左右轮闭环 | 两个控制器分别计算 | 分别确认反馈符号、电机方向和参数 |
| 速度滤波 | PID 使用低通后的反馈 | 同时记录原始值,评估噪声与滞后的折中 |
| 航向修正 | 相关代码仍被注释 | 速度环稳定后再叠加转向量 |
| 串口观测 | 已输出目标和滤波速度 | 控制周期内避免阻塞式高频打印 |
| 物理单位 | 变量名写作 cm/s | 用轮径、减速比和编码器分辨率完成标定 |
本篇总结
- 这份文件描述的是双轮速度环应用,不是完整 PID 库。
- 左右轮独立闭环能补偿机械与电气差异。
- 低通滤波减少测速抖动,同时引入控制滞后。
- 航向差速代码仍被注释,不能视作已启用功能。
- 要把示例变成可靠模块,还需固定周期、状态复位、非阻塞观测和实车曲线。