循迹小车低速一顿一顿,我靠串口打印揪出了干扰源

2026-11-122

下午调试一辆 PID 循迹小车,电机在低速段明显一顿一顿,速度曲线像锯齿一样跳。PID 参数调了半天没改善,反而越调越乱。直觉告诉我这不是算法问题,而是硬件层面的干扰。

硬件清单

· 主控:Arduino UNO R3

· 驱动器:艾思控AQMD2403BLS-M(适配 12V-18W / 24V-50W,电流6A/3A,能耗制动3A,尺寸 45×45×18mm 裸板)

· 电机:12V 带编码器直流减速电机(60 线 AB 相)

· 电源:12V 3A 锂电池组

· 传感器:5 路红外循迹模块(TCRT5000)

· 其他:杜邦线若干、面包板

接线说明

· AQMD2403BLS-M 的 PWM 输入接 UNO D3(硬件 PWM 引脚),DIR 接 D4,GND 与 UNO 共地。

· 电机编码器 A/B 相分别接 UNO D2/D3(外部中断引脚),注意 D3 已被 PWM 占用,这里需要换到D18/D19(即 A0/A1 对应的中断引脚,UNO 只有 D2/D3 有中断,所以实际接D2/D3,PWM 改到D5)。

· 红外循迹模块输出接A0~A4,VCC/GND 从 UNO 5V 引出。

· 电机电源和逻辑电源共用 12V 电池,驱动器 VIN 接电池正极,GND 接电池负极,UNO 通过 Vin 引脚从同一电池取电。

【配图建议:接线拓扑图,标注功率回路与信号回路的走线路径】

现象描述

· 占空比低于 20% 时,电机启动困难,偶尔"咔哒"一声才转起来。

· 匀速运行时,串口打印的编码器计数值忽大忽小,速度反馈跳变明显。

· 红外循迹读数在电机启停瞬间出现毛刺,偶尔误判黑线位置。

· 用手轻触驱动器外壳,能感觉到轻微的麻手感(感应电)。

排查过程

第一步,怀疑 PID 参数没调好。把 Kp 从 2.0 降到0.5,Ki 清零,Kd 从 0.1 升到0.3,现象依旧,低速抖动没有改善。排除算法问题。

第二步,怀疑编码器接线松动或信号线太长。缩短编码器线到5cm,用屏蔽线重接,抖动减轻但没消除。排除纯接线问题。

第三步,用万用表测编码器 A 相波形,发现电机运行时信号线上叠加了大约 200~300mV 的高频噪声。把示波器探头换到红外模块的输出引脚,同样看到电机换相时的尖峰脉冲。此时基本锁定:功率回路的噪声耦合到了信号线上。

根因分析

  1. ​共地走线不合理​:电机大电流回路与编码器/传感器信号线在面包板上共用了一段 GND 走线,电机换相时的 di/dt 在 GND 阻抗上产生压降,直接叠加到信号地参考上。
  2. ​编码器线与电机线平行走线​:两者并排捆扎了 15cm 左右,电机线上的高频噪声通过分布电容耦合到编码器信号线。
  3. AQMD2403BLS-M ​ 的 PWM ​ ​频率较高​:该驱动器默认 PWM 频率约 20kHz,快速开关产生的 dv/dt 通过寄生电容辐射到邻近的模拟信号线,红外模块的模拟输出尤其敏感。

解决过程

硬件上做了三处改动:

  1. 把编码器线换成双绞屏蔽线,屏蔽层单端接驱动器 GND。
  2. 红外模块的每路输出加一个 100nF 电容到GND,做简单的 RC 低通滤波。
  3. 重新布线:电机功率线走底板一侧,信号线走另一侧,两者交叉时垂直跨越,不平行走线。

软件上,用串口打印代替示波器,实时观察编码器速度和红外读数,确认改善效果:

// PID 循迹小车 - 串口调试版
volatile longencoderCount = 0;
unsigned long lastTime = 0;
float lastSpeed = 0;

void setup() {
Serial.begin(115200);
pinMode(2, INPUT_PULLUP); // 编码器 A 相
pinMode(3, INPUT_PULLUP); // 编码器 B 相
attachInterrupt(digitalPinToInterrupt(2), onEncoder, CHANGE);
pinMode(5, OUTPUT); // PWM 输出到驱动器
pinMode(4, OUTPUT); // DIR
lastTime = millis();
}

void loop() {
unsigned long now = millis();
if (now - lastTime >= 50) { // 每 50ms 计算一次速度
noInterrupts();
long count = encoderCount;
encoderCount = 0;
interrupts();
float speed = count / (50.0 / 1000.0); // 计数/秒
// 简单移动平均滤波,平滑速度反馈
lastSpeed = 0.7 * lastSpeed + 0.3 * speed;
// 串口打印:时间戳 | 原始计数 | 滤波后速度
Serial.print(now);
Serial.print(",");
Serial.print(count);
Serial.print(",");
Serial.println(lastSpeed, 1);
lastTime = now;
}
// PID 控制逻辑省略...
}

void onEncoder() {
encoderCount++;
}

验证结果

改造后低速占空比 10% 也能平稳启动,不再有"咔哒"声。串口绘图器里速度曲线从锯齿状变成了平滑的波浪线,红外读数在电机启停时也不再跳变。实测下来,低速段的速度标准差从大约 ±15 计数降到了 ±3 计数以内。

踩坑小结

  1. ​信号线与功率线必须分开走​,平行走线超过 5cm 就要警惕耦合噪声。
  2. ​编码器线用双绞屏蔽线​,屏蔽层单端接地,比裸杜邦线抗干扰能力强很多。
  3. 模拟信号输出加 RC ​ ​滤波​,100nF 电容并联到 GND,成本几乎为零但效果明显。
  4. ​没有示波器就用串口打印​,Arduino 的 Serial Plotter 足够观察趋势变化,排查干扰问题够用。
  5. ​共地不是简单地连在一起就行​,大电流回路的 GND 压降会污染整个参考地,星型接地或单点接地更可靠。

结尾

这次排查下来,硬件布线的细节比 PID 参数更影响低速性能。大家做小车时有没有遇到过类似的"玄学抖动",最后是怎么解决的?

创作许可协议

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

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