做一辆PID调速循迹小车——从接线到调参的踩坑实录

2026-11-072
AI 快速预览详细 收起
本文介绍了如何通过PID调速实现循迹小车的稳定控制。首先解释了为什么需要速度闭环,然后详细说明了硬件接线、编码器测速方法以及PID参数的调整过程。文章还提供了实际调试中的常见问题和解决方案,如共地连接、外部中断计数等。最后总结了工程要点,帮助读者从零开始制作一台稳定的小车。

一、为什么要做闭环:开环小车的"翻车现场"

很多新手第一台智能小车都是开环:给左右电机同样的 PWM,车就"理论上"直走。可一上地面就露馅——左边轮子先转、右边轮子打滑,走两米歪成香蕉;地毯、瓷砖、木地板换一张地面,速度全变。原因很简单:直流电机不是理想元件,同样的 PWM 占空比,因电池电压下降、电机内阻差异、地面摩擦不同,转速根本不一样。

要做"指哪走哪"的小车,必须把开环升级成速度闭环:用编码器实时测出每个轮子的转速,让 PID 算法不断微调 PWM,把实际转速拉回到目标值。这篇就带你从硬件接线、编码器读数,一路调到 PID 稳起来。

二、硬件清单与接线

模块

型号建议

作用

备注

主控Arduino UNO / DFRomeo逻辑运算、PWM输出Romeo板自带电机驱动可省TB6612
电机驱动TB6612FNGPWM驱动直流电机比L298N效率高、发热小
减速电机TT马达带霍尔编码器执行+测速1:30或1:45减速比,每圈64脉冲
循迹模块4路红外循迹 / SEN05识别黑线数字输出,上拉需共地
电源2S锂电(7.4V)供电务必加共地,别用USB单独供电

 

TB6612 关键接线:PWMA/PWMB 接 Arduino 的 PWM 脚(如 D5/D6),AIN1/AIN2、BIN1/BIN2 接普通数字脚控制方向,STBY 拉高使能,VM 接电机电源,VCC 接 3.3~5V,所有 GND 必须连在一起。这一步是新手烧板重灾区:共地没接,控制信号参考电位漂移,电机动不动乱转。

三、编码器测速:M法与外部中断

测速最稳的做法是把编码器两相脉冲接到 Arduino 的外部中断脚(UNO 是 D2/D3),用 A 相触发中断、B 相判方向,每次中断计数加一。中断里只做"计数++",绝不放大段逻辑。

主循环里每 20ms 取一次增量,除以采样时间得到转速:

volatile long cntL = 0, cntR = 0;

void onEncL(){ cntL++; }   // A相中断,只计数

void setup(){

  attachInterrupt(digitalPinToInterrupt(2), onEncL, RISING);

}

// 主循环: 每20ms

float speedL = (cntL - lastL) * 60.0 / (PPR * 0.02); // 转/分, PPR=每圈脉冲数

新手常见坑:用了轮询读编码器(polling),转速一高就漏脉冲;或者没做软件消抖,一个脉冲触发多次中断,测出来虚高一倍。中断计数 + 合理采样周期(20~50ms)是稳妥起点。

四、PID到底在调什么

PID 的三个参数各有各的脾气,把它想成"开车调速"就不抽象了:

参数

直观作用

调大表现

太小表现

Kp看当前误差就动手响应快、易超调震荡反应迟钝、追不上目标
Ki记住历史欠账消除稳态误差、易积分饱和稳态偏差消不掉
Kd预测趋势提前刹车抑制超调、抗扰、怕噪声压不住超调

 

调参口诀:先 P 后 I 再 D。先把 Ki、Kd 设 0,从小到大加 Kp 直到小车能追目标但轻微震荡;再加一点 Ki 消掉"总差一点点"的稳态误差;最后用 Kd 压住超调。速度环典型起步值(TT马达+TB6612):Kp≈2.0、Ki≈0.5、Kd≈0.1,按自己车微调。

float computePID(float target, float now, float &prevError, float &integral){

  float error = target - now;

  integral += error;

  integral = constrain(integral, -255, 255); // 抗积分饱和

  float out = Kp*error + Ki*integral + Kd*(error - prevError);

  prevError = error;

  return constrain(out, -255, 255);          // 抗输出饱和

}

五、现场调试与踩坑记录

第一台车调 PID 时最容易"调着调着就乱",记下这几点能省一半时间:

• 上电先验编码器方向:用手转左轮,串口里 cntL 应增加;反了就把中断脚对调,否则 PID 一闭环就把轮子往反方向猛打。

• 先原地测空载再上地:空载转速稳了再放地面,负载变化要重调 Kp。

• 电池电压是关键变量:锂电从 8.2V 掉到 7.0V,同样 PWM 转速能差 15%。闭环能扛住,但别指望开环也稳。

• 循迹环与速度环要分开:循迹是"方向环"(输出左右轮速差),速度环是"执行环"(保证每个轮子达到目标速度)。把两个环混在一个 PID 里调,必崩。

六、实战案例:瓷砖地面循迹不抖头

一辆 4 路循迹小车在瓷砖上高频"左右抽搐"。排查后发现是速度环 Kp 给太高,编码器噪声被放大。把采样周期从 20ms 放到 30ms,加了一阶低通滤波 `(新值*0.3 + 旧值*0.7)`,再把 Kp 从 3.5 降到 2.2,小车过弯平滑了。结论:噪声是 Kd 的天敌,闭环前先确认编码器读数本身干净。

七、工程要点小结

• TB6612 务必共地、STBY 拉高,否则驱动不出力。

• 编码器走外部中断,中断里只计数,别做浮点运算。

• 调参顺序:P → I → D,先空载后上地。

• 速度环与循迹方向环解耦,各调各的 PID。

• 电池电压会漂移,靠闭环抗,不靠开环赌。

八、延伸阅读

• DFRobot Romeo 驱动板 + 编码器电机官方例程

• Arduino 外部中断与 `attachInterrupt` 用法

• 《PID 控制从零到工程实战》社区精华帖

(本文为 DIY 实践整理,参数为常见经验值,请结合自己的电机、电池与地面微调。欢迎在评论区贴出你的 PID 波形一起折腾。——爱控电子)

创作许可协议

本项目采用 CC BY(署名) 进行许可。

评论(0)
- 没有更多了 -