这是一个基于 Arduino 的智能自动寻迹小车项目。小车通过 7 个红外传感器阵列 实时检测黑线位置,采用 PD 控制算法 + 低通滤波 动态调节左右电机的 PWM 速度,实现平滑的自动寻线行驶。同时配备 WS2812 RGB 彩色 LED,通过不同颜色指示小车的当前状态。
主要特性:
- ✅ 多通道红外传感器(7 个)用于高精度黑线检测
- ✅ PD + 低通滤波控制,运行平稳无抖动
- ✅ 自适应滤波,根据误差大小动态调整响应速度
- ✅ 丢线智能搜索策略,支持交替转圈寻线
- ✅ 实时 RGB LED 状态指示灯
- ✅ 完整的调试串口输出,便于参数调试
| 组件 | 说明 |
|---|---|
| MCU | Arduino UNO / Nano 或兼容板 |
| 电机驱动 | 直流电机 × 2 + 电机驱动模块(支持 PWM 控制) |
| 传感器 | 红外传感器模块(通过移位寄存器连接)× 7 个 |
| LED | WS2812 RGB 灯珠 × 2 个 |
| 移位寄存器 | 用于传感器数据读取和碰撞开关 |
引脚配置: Sensor Pins: Pin 8 - Shift Register LOAD Pin 12 - Shift Register MISO (Data) Pin 13 - Shift Register CLK
Motor Control: Pin 6 - Left Motor Backward Pin 7 - Left Motor Forward Pin 9 - Right Motor Backward Pin 10 - Right Motor Forward
RGB LED: Pin 4 - WS2812 Data Line
Interrupts: INT0 (Pin 2) - Left Motor Pulse Counter INT1 (Pin 3) - Right Motor Pulse Counter
Smart-Car-Line-Following-Project/ ├── xunji.ino # Main program with line-following logic ├── motor.h / motor.cpp # Motor PWM control wrapper ├── comm.h / comm.cpp # Sensor data reading (shift register) ├── Adafruit_NeoPixel.h # RGB LED driver library ├── Adafruit_NeoPixel.cpp # RGB LED driver implementation └── README.md # This file
- Error Calculation Uses weighted averaging to calculate deviation from centerline: Sensors: L3 L2 L1 Mid R1 R2 R3 Weights: -4 -2.5 -1 0 1 2.5 4
Error = (sum of weighted sensor values) / (number of active sensors) 权重说明:
- 中心传感器权重更大(±4),提高对中线的敏感性
- 距离越远权重越小,避免边界干扰
Parameters: KP (Proportional Gain) = 40.0 KD (Derivative Gain) = 95.0 correction = KP × error + KD × d_error
自适应滤波:
- 误差 > 1.5:α = 0.5(快速响应)
- 误差 < 0.3:α = 0.2(平滑输出)
- 其他情况:α = 0.35(默认)
####4. Differential Speed Control
Motor speeds are adjusted based on error:
Positive error (biased right): Slow right motor, speed up left motor → turn left Negative error (biased left): Slow left motor, speed up right motor → turn right
当连续超过 30 帧检测不到黑线时:
- 阶段 1:沿上一次转向方向进行原地转圈
- 阶段 2:切换为 交替搜索(先左转 40 帧,再右转 40 帧),扩大搜索范
这些参数控制小车的寻线性能。根据赛道条件和实际表现进行调整。
const int BASE_SPEED = 190; // 范围: 0~255- 功能: 小车在中线附近且无修正时的基础速度
- 值越大 (200~255): 小车速度快,反应时间短
- 值越小 (100~150): 小车速度慢,更稳定但容易超调
- 常见范围: 150~220(取决于赛道宽度)
- 调试建议: 从190开始,如果抖动明显就降低,如果响应迟钝就提高
const int MAX_CORRECTION = 140; // 范围: 0~255- 功能: 限制PD控制对电机速度的最大调整量
- 例如: 如果计算出修正量=150,但MAX_CORRECTION=140,则会被限制为140
- 值越大 (160~200): 小车转向幅度更大,控制更激进
- 值越小 (80~120): 转向平缓温和,控制更保守
- 常见范围: 100~160
- 调试建议: 如果左右抖动,降低此值。如果转弯不足,提高此值
const float KP = 40.0f; // 范围: 10~80- 功能: 决定小车对当前误差的反应强度
- 公式:
修正量 = KP × 误差 + KD × 误差变化率 - 值越大 (50~80): 反应快,转向幅度大,修正力度强
- 值越小 (20~35): 反应温和,平滑但可能无法应对急转
- 值过大症状: 左右抖动、摇晃明显
- 值过小症状: 反应迟钝、无法跟踪急弯
- 常见范围: 30~60
- 调试建议: 从40开始,每次调整 5~10
const float KD = 95.0f; // 范围: 30~150- 功能: 阻尼系数,抑制误差变化速度,防止超调
- 公式:
修正量 = KP × 误差 + KD × 误差变化率 - 误差变化率 = 误差的微分(速度)
- 值越大 (120~150): 阻尼强,抖动少但反应变慢
- 值越小 (30~60): 阻尼弱,反应快但容易超调摇晃
- 值过大症状: 转向反应慢,像在"拖沓"
- 值过小症状: 超调明显,频繁左右摇晃
- 常见范围: 60~120
- 调试建议: 摇晃就提高,反应慢就降低
const float ALPHA = 0.35f; // 范围: 0.1~0.9- 功能: 平滑误差信号,减少传感器噪声
- 公式:
滤波误差 = (1 - ALPHA) × 前一次误差 + ALPHA × 原始误差 - 值越大 (0.6~0.9): 滤波少,响应快但可能有噪声
- 值越小 (0.1~0.3): 滤波多,输出平滑但反应有延迟
- ALPHA = 1.0: 完全不滤波(使用原始传感器数据)
- ALPHA = 0.0: 完全不更新(始终用上一次的值)
- 值过大症状: 抖动、噪声大
- 值过小症状: 反应迟钝、有延迟感
- 常见范围: 0.25~0.50
- 调试建议: 从0.35开始,如果有颤抖就降低,如果反应慢就提高
const int SEARCH_TURN_SPEED = 135; // 范围: 80~200- 功能: 小车丢失黑线后,进行原地转圈搜索时的电机速度
- 值越大 (160~200): 搜索快速,覆盖面积大
- 值越小 (80~120): 搜索缓慢,谨慎小心
- 特点: 此时一个电机速度为此值,另一个为0(原地转圈)
- 值过大症状: 转得太快,可能冲过黑线
- 值过小症状: 转得太慢,找线花时间太长
- 常见范围: 100~160
- 调试建议: 设置为BASE_SPEED的70%左右最佳
问题:左右摇晃、频繁抖动?
→ 降低 KD (例如:95 → 70)
→ 或提高 MAX_CORRECTION
问题:反应迟钝、转向太慢?
→ 提高 KP (例如:40 → 50)
→ 或提高 ALPHA (例如:0.35 → 0.45)
问题:超调明显、转弯过度回调?
→ 提高 KD (例如:95 → 120)
→ 或降低 KP (例如:40 → 30)
问题:转向颤抖、有噪声感?
→ 降低 ALPHA (例如:0.35 → 0.25)
→ 或提高 MAX_CORRECTION
问题:丢线后找不到线?
→ 提高 SEARCH_TURN_SPEED (例如:135 → 160)
→ 检查 LOST_LINE_MAX 是否足够大
```markdown
### 🏎️ 高速寻线参数配置方案
在保证准确寻线的前提下,实现最快速度。这需要在 **快速响应** 和 **稳定性** 之间找到平衡。
---
### 📋 参数配置策略
#### **第一步:提高基础速度**
```cpp
const int BASE_SPEED = 240; // 从190提高到最大240
- 这是小车能跑的极限速度(0~255范围)
- 但单纯提高BASE_SPEED还不够,还需要配套的控制参数
const float KP = 55.0f; // 从40提高到55,快速响应偏差
const float KD = 110.0f; // 从95提高到110,增强阻尼防止超调为什么这样调?
- 高速时,任何小的偏差都会被放大
- KP高(55)能快速检测并修正偏差
- KD高(110)能防止过度修正导致的摇晃
const float ALPHA = 0.45f; // 从0.35提高到0.45为什么增加滤波?
- 高速运行时,传感器数据波动大
- 增加滤波可以减少噪声干扰
- 平滑的误差信号 + 强响应 = 稳定的高速控制
const int MAX_CORRECTION = 165; // 从140提高到165为什么提高?
- 高速转弯需要更大的转向幅度
- 165允许最多 ±165 的PWM调整空间
- 例如:BASE_SPEED=240 ± 165 = 75~255,全速范围利用
const int SEARCH_TURN_SPEED = 160; // 从135提高到160为什么提高?
- 如果丢线搜索太慢,高速时容易继续冲出赛道
- 160能快速找回黑线
// ===== 高速寻线参数组合 =====
const int BASE_SPEED = 240; // 基础速度:最大
const int MAX_CORRECTION = 165; // 最大修正:增强转向
const float KP = 55.0f; // 比例系数:快速响应
const float KD = 110.0f; // 微分系数:防超调
const float ALPHA = 0.45f; // 滤波系数:增强平滑
const int SEARCH_TURN_SPEED = 160; // 搜索速度:快速找线如果这个配置还不够快或有问题,按这个顺序微 :
优先级 1 - 提高基础速度(最直接)
BASE_SPEED: 240 → 245 → 250 → 255- 每次提高5~10,看是否仍能稳定寻线
- 如果开始摇晃,停止增加
优先级 2 - 调整KP响应速度
KP: 55 → 60 → 65(如果BASE_SPEED=255还是响应不过来)- 但要注意不要太高导致超调
优先级 3 - 微调KD防超调
KD: 110 → 120(如果出现摇晃)
KD: 110 → 100(如果反应太慢)优先级 4 - 调整滤波平滑度
ALPHA: 0.45 → 0.50(如果噪声多)
ALPHA: 0.45 → 0.40(如果反应太慢)优先级 5 - 增加MAX_CORRECTION转向能力
MAX_CORRECTION: 165 → 180(如果转弯不足)
MAX_CORRECTION: 165 → 150(如果转向太激进)不要一次性全改,应该逐步调整:
阶段 1 - 保守快速(在原基础上略加速)
const int BASE_SPEED = 210;
const float KP = 45.0f;
const float KD = 100.0f;
const float ALPHA = 0.38f;
const int MAX_CORRECTION = 150;→ 测试效果,观察是否稳定
阶段 2 - 中等快速(进一步加速)
const int BASE_SPEED = 225;
const float KP = 50.0f;
const float KD = 105.0f;
const float ALPHA = 0.42f;
const int MAX_CORRECTION = 160;→ 测试效果,观察是否稳定
阶段 3 - 全速模式(极限速度)
const int BASE_SPEED = 240;
const float KP = 55.0f;
const float KD = 110.0f;
const float ALPHA = 0.45f;
const int MAX_CORRECTION = 165;→ 最终验证
原因: 响应不够快
解决方案:
// 增加比例系数
KP: 55 → 60
// 增加滤波(减少噪声干扰)
ALPHA: 0.45 → 0.48
// 增加MAX_CORRECTION
MAX_CORRECTION: 165 → 175原因: 阻尼不足,超调严重
解决方案:
// 增加微分系数
KD: 110 → 125
// 降低比例系数(避免过度修正)
KP: 55 → 48
// 增加滤波平滑度
ALPHA: 0.45 → 0.50原因: 搜索速度或搜索策略不适配
解决方案:
// 增加搜索速度
SEARCH_TURN_SPEED: 160 → 175
// 增加丢线阈值(多找几帧再切换策略)
LOST_LINE_MAX: 30 → 50原因: 转向能力不足
解决方案:
// 在弯道前降速(代码级别修改,或减小BASE_SPEED)
// 增加转向修正范围
MAX_CORRECTION: 165 → 180 或更高
// 增强比例响应
KP: 55 → 62-
先用推荐的高速配置上传代码
BASE_SPEED = 240, KP = 55, KD = 110, ALPHA = 0.45, MAX_CORRECTION = 165
-
打开串口监视器,观察实时数据
- 如果
Error在 -1.0 ~ 1.0 之间波动,说明控制良好 - 如果频繁 -3.0 ~ 3.0 大幅波动,说明参数太激进
- 如果
-
在赛道上测试
- 先在直线段测试,确保稳定
- 再在弯道测试,确保不冲
- 记录最高稳定速度
-
根据测试结果微调
- 如果冲出 → 降低 BASE_SPEED 或增加 KD
- 如果速度不够 → 增加 BASE_SPEED 或 KP
- 如果摇晃 → 增加 ALPHA 或 KD
| 规则 | 说明 |
|---|---|
| KP < KD | 比例系数应小于微分系数,保证稳定性 |
| ALPHA ≥ 0.4 | 高速时滤波要强,减少噪声 |
| MAX_CORRECTION ≥ 150 | 转向能力要充足,否则弯道冲出 |
| 先稳定再加速 | 每次只改一个参数,逐步加速 |
| 记录每次配置 | 保存不同赛道的最佳参数 |
| 场景 | BASE_SPEED | KP | KD | ALPHA | 效果 |
|---|---|---|---|---|---|
| 稳定安全 | 150 | 35 | 85 | 0.30 | 慢但非常稳 |
| 平衡方案 | 190 | 40 | 95 | 0.35 | 中等速度,足够稳 |
| 高速方案 | 240 | 55 | 110 | 0.45 | 快且相对稳 |
| 极限竞速 | 255 | 65 | 120 | 0.50 | 最快但易失控 |
// 把这个配置直接粘贴到你的代码里
const int BASE_SPEED = 240;
const int MAX_CORRECTION = 165;
const float KP = 55.0f;
const float KD = 110.0f;
const float ALPHA = 0.45f;
const int SEARCH_TURN_SPEED = 160;- 上传代码
- 打开串口监视器(波特率9600)
- 在赛道上测试
- 根据表现微调参数
预期结果: 比默认配置快 30%~50%,同时保持良好的稳定性 🏁
```markdown
### 🔧 完整参数详细说明
这些参数分为两部分:**寻线主参数** 和 **优化参数**。理解每个参数的作用对调试至关重要。
---
## 📌 寻线主参数 (Line Following Parameters)
### **BASE_SPEED** (基础前进速度)
```cpp
const int BASE_SPEED = 240; // 范围: 0~255
作用: 小车在中线附近(无需修正)时的电机PWM值
工作原理:
当小车在中线上完美运动时:
左电机 = BASE_SPEED (240)
右电机 = BASE_SPEED (240)
→ 两轮等速,直线行进
为什么选择 240?
- Arduino PWM范围是 0~255,240接近最大值
- 给后续的修正量留足空间(±165)
- 完整范围:240 - 165 = 75(最慢)到 240 + 165 = 405(截断到255)
调整影响:
| 增加 BASE_SPEED | 效果 |
|---|---|
| +10 (250) | 整体快10%,但可用修正空间变小 |
| +30 (270) | 太快,容易冲出,不推荐 |
| 减少 BASE_SPEED | 效果 |
|---|---|
| -30 (210) | 速度下降,控制更稳定 |
| -50 (190) | 回到中等速度,适合不稳定的赛道 |
const int MAX_CORRECTION = 165; // 范围: 0~255作用: 限制PD算法对电机速度的最大调整幅度
工作原理:
PD计算出的修正量可能很大,比如 correction = 250
但 MAX_CORRECTION = 165 会限制它:
correction = constrain(250, -165, +165) = 165
实际电机PWM:
左电机 = 240 + 165 = 405 → 截断到255 (全速)
右电机 = 240 - 165 = 75 (最慢)
修正量的含义:
修正量 > 0(偏右):
left_motor += correction (左轮加速)
right_motor -= correction (右轮减速)
→ 小车左转,回到中线
修正量 < 0(偏左):
left_motor += correction (左轮减速,因为correction是负数)
right_motor -= correction (右轮加速)
→ 小车右转,回到中线
为什么选择 165?
- 高速模式下需要强力转向
- 完整利用 PWM 范围(0~255)
- BASE_SPEED = 240 ± 165 = [75, 255]
调整影响:
| 增加 MAX_CORRECTION | 效果 |
|---|---|
| +20 (185) | 转向更激进,快速纠正偏差 |
| +50 (215) | 转向过度,容易摇晃 |
| 减少 MAX_CORRECTION | 效果 |
|---|---|
| -30 (135) | 转向温和,平稳但可能转不过急弯 |
| -50 (115) | 转向太弱,高速容易冲出 |
const float KP = 55.0f; // 范围: 10~80作用: 决定小车对 当前误差 的反应强度
公式:
correction = KP × error + KD × d_error
↑
这部分由KP决定
具体例子:
如果当前误差 error = 1.5(严重偏右)
KP = 55,则:
修正量贡献 = 55 × 1.5 = 82.5
如果 KP = 40:
修正量贡献 = 40 × 1.5 = 60.0 (反应较弱)
如果 KP = 70:
修正量贡献 = 70 × 1.5 = 105.0 (反应很强)
为什么选择 55?
- 高速寻线需要快速反应
- 55足够快速检测偏差
- 与KD=110配合避免超调
调整影响:
| 增加 KP | 效果 | 风险 |
|---|---|---|
| +5 (60) | 反应更快 | 容易超调 |
| +15 (70) | 非常灵敏 | 容易摇晃 |
| 减少 KP | 效果 | 风险 |
|---|---|---|
| -5 (50) | 反应稍慢 | 高速时可能反应不过来 |
| -15 (40) | 温和反应 | 弯道容易冲出 |
const float KD = 110.0f; // 范围: 30~150作用: 根据误差 变化速度 进行阻尼,防止超调和摇晃
公式:
correction = KP × error + KD × d_error
↑
这部分由KD决定
其中 d_error = filtered_error_now - filtered_error_last
= 误差的微分(速度)
具体例子:
帧1:error = 0.5 → d_error = 0.5 - 0 = 0.5
修正量 = 55 × 0.5 + 110 × 0.5 = 27.5 + 55 = 82.5
帧2:error = 1.0 → d_error = 1.0 - 0.5 = 0.5
修正量 = 55 × 1.0 + 110 × 0.5 = 55 + 55 = 110
帧3:error = 0.8 → d_error = 0.8 - 1.0 = -0.2
修正量 = 55 × 0.8 + 110 × (-0.2) = 44 - 22 = 22
↑ 注意:虽然error还是0.8,但因为error在减小,
KD项是负的,会自动减弱修正(防止超调)
为什么选择 110?
- 与 KP=55 的比例约为 2:1,这是PD控制的黄金比例
- 防止高速运行时的超调摇晃
- 自动阻尼效应明显
调整影响:
| 增加 KD | 效果 | 风险 |
|---|---|---|
| +10 (120) | 更强阻尼 | 反应变慢 |
| +20 (130) | 非常平稳 | 可能无法及时转向 |
| 减少 KD | 效果 | 风险 |
|---|---|---|
| -10 (100) | 反应更快 | 容易超调摇晃 |
| -30 (80) | 很敏感 | 频繁左右摇晃 |
const float ALPHA = 0.45f; // 范围: 0.1~0.9作用: 平滑原始误差信号,减少传感器噪声影响
公式:
filtered_error = (1 - ALPHA) × filtered_error_prev + ALPHA × raw_error
↑惯性权重 ↑新信息权重
具体例子:
ALPHA = 0.45
帧1:raw_error = 0.5, filtered = 0
filtered = (1-0.45) × 0 + 0.45 × 0.5 = 0.225
帧2:raw_error = 2.0(突然跳变,可能是噪声)
filtered = (1-0.45) × 0.225 + 0.45 × 2.0
= 0.124 + 0.9 = 1.024
→ 滤波后是1.024,而不是直接用2.0
→ 平滑了这个跳变
帧3:raw_error = 0.6(恢复正常)
filtered = 0.55 × 1.024 + 0.45 × 0.6
= 0.563 + 0.27 = 0.833
ALPHA的含义:
- ALPHA = 0.0:完全不信任新数据,延迟大
- ALPHA = 0.5:新旧数据各占50%,平衡
- ALPHA = 1.0:完全信任新数据,响应快但噪声大
为什么选择 0.45?
- 高速模式需要较快响应(0.45 > 0.35)
- 但同时要平滑传感器噪声
- 0.45是快速和平滑的平衡点
调整影响:
| 增加 ALPHA | 效果 | 风险 |
|---|---|---|
| +0.05 (0.50) | 响应更快 | 噪声干扰增大 |
| +0.15 (0.60) | 敏感度高 | 容易抖动 |
| 减少 ALPHA | 效果 | 风险 |
|---|---|---|
| -0.05 (0.40) | 更平滑 | 响应略有延迟 |
| -0.15 (0.30) | 非常平滑 | 明显延迟感 |
const int SEARCH_TURN_SPEED = 160; // 范围: 80~200作用: 小车检测不到黑线时,原地转圈搜索的电机速度
工作原理:
当 line_seen = false(丢线)时:
if (last_turn_direction > 0) // 上次向右转
left_motor = 160
right_motor = 0
→ 左轮转,右轮停,小车向右转圈
else // 上次向左转
left_motor = 0
right_motor = 160
→ 右轮转,左轮停,小车向左转圈
为什么选择 160?
- 与 BASE_SPEED=240 的比例约为 0.67
- 搜索速度不能太快(容易冲过线)
- 也不能太慢(找线太久)
- 160是快速和安全的平衡
调整影响:
| 增加 SEARCH_TURN_SPEED | 效果 | 风险 |
|---|---|---|
| +20 (180) | 找线更快 | 可能冲过黑线 |
| +40 (200) | 非常快速 | 容易错过 |
| 减少 SEARCH_TURN_SPEED | 效果 | 风险 |
|---|---|---|
| -20 (140) | 更谨慎 | 找线太慢 |
| -40 (120) | 非常缓慢 | 严重延迟 |
const float DEADZONE = 0.2f; // 范围: 0.1~0.5作用: 在此误差范围内,不改变转向方向记录
工作原理:
代码逻辑:
if (error > TURN_THRESHOLD) // 0.4
last_turn_direction = 1; // 记为向右
else if (error < -TURN_THRESHOLD) // -0.4
last_turn_direction = -1; // 记为向左
// 在 [-0.2, 0.2] 之间(死区),不更新方向
作用:防止在中线附近频繁改变方向记录
为什么需要死区?
没有死区时:
error: -0.1 → 记录向左
error: +0.1 → 改记录向右
error: -0.1 → 改记录向左
→ 频繁变动,丢线时搜索方向混乱
有死区后:
error: -0.1 → 在死区内,保持原方向
error: +0.1 → 在死区内,保持原方向
→ 稳定,丢线时搜索更有方向性
调整建议:
- 赛道宽(黑线宽)→ 增加DEADZONE(0.3~0.4)
- 赛道窄(黑线窄)→ 减少DEADZONE(0.1~0.15)
const float TURN_THRESHOLD = 0.4f; // 范围: 0.2~0.8作用: 误差超过此值才记录新的转向方向
例子:
TURN_THRESHOLD = 0.4
error = 0.3 → 虽然偏右,但 |0.3| < 0.4,不更新方向
error = 0.5 → |0.5| > 0.4,更新为向右
error = -0.3 → 虽然偏左,但 |-0.3| < 0.4,不更新方向
error = -0.6 → |-0.6| > 0.4,更新为向左
为什么需要阈值?
- 避免小的摇晃改变转向方向
- 丢线后能更准确地找到之前转向的方向
- 提高丢线搜索的有效性
调整建议:
| 增加 TURN_THRESHOLD | 效果 |
|---|---|
| +0.2 (0.6) | 需要更大偏差才能改变方向,更稳定 |
| +0.4 (0.8) | 判定条件严格,可能误判 |
| 减少 TURN_THRESHOLD | 效果 |
|---|---|
| -0.1 (0.3) | 更敏感,快速反应小偏差 |
| -0.2 (0.2) | 过度敏感,容易频繁改变 |
const int LOST_LINE_MAX = 30; // 范围: 15~60作用: 连续丢线超过此帧数后,切换搜索策略
工作原理:
帧1~30:丢线但使用原始搜索(沿上次转向方向)
lost_line_count 从 0 递增到 30
帧31:lost_line_count > LOST_LINE_MAX (30)
use_alternate_search = !use_alternate_search
切换到交替搜索模式
lost_line_count 重置为 0
交替搜索:
先向左转40帧
再向右转40帧
扩大搜索范围
为什么需要这个参数?
- 避免陷入死循环(一直沿一个方向转)
- 如果线确实不在上次转向的方向,需要切换
- 提高找线的成功率
调整建议:
| 增加 LOST_LINE_MAX | 效果 |
|---|---|
| +15 (45) | 多试��次原始方向,再切换 |
| +30 (60) | 对原始方向更有信心 |
| 减少 LOST_LINE_MAX | 效果 |
|---|---|
| -10 (20) | 快速切换搜索策略 |
| -20 (10) | 很快放弃原始方向 |
推荐值:
- 宽赛道(好找线)→ 30~40
- 窄赛道(难找线)→ 40~50
- 急转弯赛道 → 20~30
const float ADAPTIVE_ALPHA_HIGH = 0.5f; // 当 error > 1.5 时使用作用: 误差很大时,提高滤波系数以加快响应
工作原理:
标准 ALPHA = 0.45(中等响应)
当 |error| > 1.5(严重偏离):
ALPHA = 0.5(更快响应)
→ 更信任新的传感器数据
→ 快速纠正严重偏差
当 |error| < 0.3(接近中线):
ALPHA = 0.2(更平滑)
→ 减少高频抖动
→ 保持平稳
在 0.3~1.5 之间:
ALPHA = 0.45(默认)
为什么需要自适应?
固定 ALPHA = 0.45 的问题:
- 接近中线时,0.45可能过快,导致抖动
- 严重偏离时,0.45可能过慢,反应不及时
自适应优势:
- 大偏差 → 快速响应
- 小偏差 → 平稳无噪声
- 自动适配不同情况
调整建议:
- 噪声多 → 降低 ADAPTIVE_ALPHA_HIGH(0.4~0.45)
- 响应慢 → 提高 ADAPTIVE_ALPHA_HIGH(0.55~0.60)
const float ADAPTIVE_ALPHA_LOW = 0.2f; // 当 error < 0.3 时使用作用: 误差很小时,降低滤波系数以保持平滑
为什么选择 0.2?
- 接近中线时,传感器信号会有微小波动
- 0.2的低滤波系数(高惯性)可以忽略这些波动
- 结果是更平稳的运动
调整建议:
- 如果中线附近有抖动 → 降低到 0.1~0.15
- 如果反应太慢 → 提高到 0.25~0.30
static float filtered_error = 0.0f;- 存储低通滤波后的误差值
- 用于PD控制计算
- 比raw_error更平滑,受噪声影响小
static float last_error = 0.0f;- 用于计算误差微分:
d_error = filtered_error - last_error - 反映误差变化速度
- 每帧更新一次
static int last_turn_direction = 1; // -1左,1右- 记录小车最后一次明显转向的方向
- 丢线时,用这个方向进行搜索
- 只在 |error| > TURN_THRESHOLD 时更新
static int lost_line_count = 0;- 统计连续检测不到黑线的帧数
- 每次丢线时 +1
- 找到线后重置为 0
- 超过 LOST_LINE_MAX 时切换搜索模式
static bool use_alternate_search = false;- false:使用原始搜索(沿上次转向方向)
- true:使用交替搜索(先左再右,扩大范围)
- 在 lost_line_count > LOST_LINE_MAX 时切换
问题现象 → 问题原因 → 调整参数 → 重新测试
【摇晃抖动】
↓
原因:PD响应过强或滤波不足
↓
调整:KD +10 或 ALPHA +0.05
【响应迟钝】
↓
原因:KP太小或ALPHA太小(滤波过强)
↓
调整:KP +5 或 ALPHA +0.05
【冲出赛道】
↓
原因:转向不足或反应慢
↓
调整:KP +10 或 MAX_CORRECTION +20
【高速摇晃】
↓
原因:BASE_SPEED太高,参数不匹配
↓
调整:KD +15 或 ALPHA +0.10
【丢线找不到】
↓
原因:搜索速度太慢或策略不对
↓
调整:SEARCH_TURN_SPEED +20 或 LOST_LINE_MAX +10
BASE_SPEED = 180
MAX_CORRECTION = 130
KP = 35
KD = 100
ALPHA = 0.35BASE_SPEED = 190
MAX_CORRECTION = 140
KP = 40
KD = 95
ALPHA = 0.35BASE_SPEED = 240
MAX_CORRECTION = 165
KP = 55
KD = 110
ALPHA = 0.45BASE_SPEED = 255
MAX_CORRECTION = 200
KP = 70
KD = 130
ALPHA = 0.55
完整详细版本!可以直接作为参考手册 📚