共计 1540 个字符,预计需要花费 4 分钟才能阅读完成。
问题背景
红外对码管是寻迹小车中最常用的传感器之一,它的原理是通过发射红外光并接收反射光强度来判断地面黑线的位置。在 2024 年电子设计竞赛中,许多队伍都遇到了一个共同的问题:小车在寻迹过程中出现明显的左右抖动现象。

这种现象的主要原因包括:
- 传感器噪声:环境光干扰和传感器本身的噪声导致信号波动
- 机械延迟:舵机或电机响应存在滞后
- 控制算法缺陷:简单的位置式控制容易产生超调
这种抖动看似微小,但实际上会显著影响比赛成绩:
- 路径偏离误差可达±5cm
- 速度损失高达 30%
- 增加了能量消耗
技术方案对比
传统方案大多采用固定阈值法,这种方法实现简单但存在明显缺陷:
- 无法适应不同材质、颜色的赛道
- 对光照变化敏感
- 响应速度与稳定性难以兼顾
相比之下,动态阈值法具有明显优势:
- 实时跟踪环境变化
- 自动适应不同赛道条件
- 可以与 PID 控制形成互补
我们还考虑了卡尔曼滤波方案,但实测发现:
- STM32F103 系列处理器计算资源有限
- 对实时性要求高的场合可能造成控制延迟
- 实现复杂度较高
核心实现
硬件平台
我们采用 STM32F103C8T6 最小系统板,主要硬件配置如下:
- 5 路红外对码管传感器
- PCA9685 舵机驱动
- TB6612 电机驱动
动态阈值算法
// 在 adc.c 中实现动态阈值计算
#define SAMPLE_NUM 10
#define NOISE_THRESHOLD 50
uint16_t get_dynamic_threshold(uint16_t raw_values[]) {
uint16_t min = 4095, max = 0;
for(int i=0; i<SAMPLE_NUM; i++) {if(raw_values[i] < min) min = raw_values[i];
if(raw_values[i] > max) max = raw_values[i];
}
// 去除异常值
if((max - min) > NOISE_THRESHOLD) {return (max + min) / 2;
} else {return fixed_threshold; // 使用预设阈值}
}
PID 控制器实现
// pid.c 中的关键实现
typedef struct {
float Kp, Ki, Kd;
float integral;
float prev_error;
} PIDController;
float PID_Update(PIDController* pid, float error, float dt) {float derivative = (error - pid->prev_error) / dt;
pid->integral += error * dt;
// 积分限幅
pid->integral = constrain(pid->integral, -100, 100);
pid->prev_error = error;
return pid->Kp * error + pid->Ki * pid->integral + pid->Kd * derivative;
}
性能验证
我们设计了三种测试场景:
- 直线赛道(2 米)
- 90 度直角弯
- S 形连续弯道
测试结果对比:
| 指标 | 固定阈值法 | 动态阈值 +PID | 提升幅度 |
|---|---|---|---|
| 直线误差 (cm) | ±4.2 | ±1.5 | 64% |
| 弯道通过时间 (s) | 3.8 | 2.6 | 32% |
| 最大速度 (cm/s) | 35 | 48 | 37% |
避坑指南
- 不要盲目提高 P 参数:这会导致严重震荡
- 红外管安装建议:
- 间距 15-20mm
- 离地高度 8 -10cm
- 倾斜角度 15-30 度
- 调试技巧:
- 使用串口发送数据到 PC 端绘图
- 先调 P,再调 I,最后调 D
- 测试时从低速开始逐步提高
延伸思考
这个方案还有进一步优化的空间:
- 可以尝试加入摄像头进行多传感器融合
- 移植到 STM32H7 等高性能平台实现更复杂算法
- 增加自适应 PID 参数调整功能
通过这次竞赛实践,我们深刻体会到:在嵌入式系统中,算法的简洁性和实时性往往比复杂理论更重要。希望这个方案能帮助更多参赛队伍解决寻迹抖动问题。
正文完
发表至: 未分类
近两天内
