Skip to content

RtimesC/Smart-Car-Line-Following-Project

Repository files navigation

Smart Car Line Following Project (智能寻迹小车)

这是一个基于 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


⚙️ 核心算法说明

  1. 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),提高对中线的敏感性
  • 距离越远权重越小,避免边界干扰

2. PD 控制 (PD Control)

Parameters: KP (Proportional Gain) = 40.0 KD (Derivative Gain) = 95.0 correction = KP × error + KD × d_error

3. 低通滤波 (Low-pass Filter)

自适应滤波:

  • 误差 > 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

5. 丢线搜索策略 (Lost Line Search)

当连续超过 30 帧检测不到黑线时:

  • 阶段 1:沿上一次转向方向进行原地转圈
  • 阶段 2:切换为 交替搜索(先左转 40 帧,再右转 40 帧),扩大搜索范

⚙️ 参数详细说明

这些参数控制小车的寻线性能。根据赛道条件和实际表现进行调整。

BASE_SPEED (基础前进速度)

const int BASE_SPEED = 190;  // 范围: 0~255
  • 功能: 小车在中线附近且无修正时的基础速度
  • 值越大 (200~255): 小车速度快,反应时间短
  • 值越小 (100~150): 小车速度慢,更稳定但容易超调
  • 常见范围: 150~220(取决于赛道宽度)
  • 调试建议: 从190开始,如果抖动明显就降低,如果响应迟钝就提高

MAX_CORRECTION (最大差速修正)

const int MAX_CORRECTION = 140;  // 范围: 0~255
  • 功能: 限制PD控制对电机速度的最大调整量
  • 例如: 如果计算出修正量=150,但MAX_CORRECTION=140,则会被限制为140
  • 值越大 (160~200): 小车转向幅度更大,控制更激进
  • 值越小 (80~120): 转向平缓温和,控制更保守
  • 常见范围: 100~160
  • 调试建议: 如果左右抖动,降低此值。如果转弯不足,提高此值

KP (比例系数)

const float KP = 40.0f;  // 范围: 10~80
  • 功能: 决定小车对当前误差的反应强度
  • 公式: 修正量 = KP × 误差 + KD × 误差变化率
  • 值越大 (50~80): 反应快,转向幅度大,修正力度强
  • 值越小 (20~35): 反应温和,平滑但可能无法应对急转
  • 值过大症状: 左右抖动、摇晃明显
  • 值过小症状: 反应迟钝、无法跟踪急弯
  • 常见范围: 30~60
  • 调试建议: 从40开始,每次调整 5~10

KD (微分系数)

const float KD = 95.0f;  // 范围: 30~150
  • 功能: 阻尼系数,抑制误差变化速度,防止超调
  • 公式: 修正量 = KP × 误差 + KD × 误差变化率
  • 误差变化率 = 误差的微分(速度)
  • 值越大 (120~150): 阻尼强,抖动少但反应变慢
  • 值越小 (30~60): 阻尼弱,反应快但容易超调摇晃
  • 值过大症状: 转向反应慢,像在"拖沓"
  • 值过小症状: 超调明显,频繁左右摇晃
  • 常见范围: 60~120
  • 调试建议: 摇晃就提高,反应慢就降低

ALPHA (低通滤波系数)

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开始,如果有颤抖就降低,如果反应慢就提高

SEARCH_TURN_SPEED (丢线搜索速度)

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还不够,还需要配套的控制参数

第二步:加强PD控制响应

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: 240245250255
  • 每次提高5~10,看是否仍能稳定寻线
  • 如果开始摇晃,停止增加

优先级 2 - 调整KP响应速度

KP: 556065(如果BASE_SPEED=255还是响应不过来)
  • 但要注意不要太高导致超调

优先级 3 - 微调KD防超调

KD: 110120(如果出现摇晃)
KD: 110100(如果反应太慢)

优先级 4 - 调整滤波平滑度

ALPHA: 0.450.50(如果噪声多)
ALPHA: 0.450.40(如果反应太慢)

优先级 5 - 增加MAX_CORRECTION转向能力

MAX_CORRECTION: 165180(如果转弯不足)
MAX_CORRECTION: 165150(如果转向太激进)

📊 逐步提速的安全方案

不要一次性全改,应该逐步调整:

阶段 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;

→ 最终验证


⚠️ 高速寻线常见问题排查

问题 1:速度快但会冲出赛道

原因: 响应不够快

解决方案:

// 增加比例系数
KP: 5560

// 增加滤波(减少噪声干扰)
ALPHA: 0.450.48

// 增加MAX_CORRECTION
MAX_CORRECTION: 165175

问题 2:速度快时左右摇晃明显

原因: 阻尼不足,超调严重

解决方案:

// 增加微分系数
KD: 110125

// 降低比例系数(避免过度修正)
KP: 5548

// 增加滤波平滑度
ALPHA: 0.450.50

问题 3:丢线后找不到线

原因: 搜索速度或搜索策略不适配

解决方案:

// 增加搜索速度
SEARCH_TURN_SPEED: 160175

// 增加丢线阈值(多找几帧再切换策略)
LOST_LINE_MAX: 3050

问题 4:在直线上还好,弯道就冲出去

原因: 转向能力不足

解决方案:

// 在弯道前降速(代码级别修改,或减小BASE_SPEED)
// 增加转向修正范围
MAX_CORRECTION: 165180 或更高

// 增强比例响应
KP: 5562

🧪 实际测试流程

  1. 先用推荐的高速配置上传代码

    BASE_SPEED = 240, KP = 55, KD = 110, ALPHA = 0.45, MAX_CORRECTION = 165
  2. 打开串口监视器,观察实时数据

    • 如果 Error 在 -1.0 ~ 1.0 之间波动,说明控制良好
    • 如果频繁 -3.0 ~ 3.0 大幅波动,说明参数太激进
  3. 在赛道上测试

    • 先在直线段测试,确保稳定
    • 再在弯道测试,确保不冲
    • 记录最高稳定速度
  4. 根据测试结果微调

    • 如果冲出 → 降低 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;
  1. 上传代码
  2. 打开串口监视器(波特率9600)
  3. 在赛道上测试
  4. 根据表现微调参数

预期结果: 比默认配置快 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) 回到中等速度,适合不稳定的赛道

MAX_CORRECTION (最大差速修正)

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) 转向太弱,高速容易冲出

KP (比例系数 - Proportional Gain)

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) 温和反应 弯道容易冲出

KD (微分系数 - Derivative Gain)

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) 很敏感 频繁左右摇晃

ALPHA (低通滤波系数)

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) 非常平滑 明显延迟感

SEARCH_TURN_SPEED (丢线搜索速度)

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) 非常缓慢 严重延迟

🎯 优化参数 (Optimization Parameters)

DEADZONE (死区)

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)

TURN_THRESHOLD (转向判定阈值)

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) 过度敏感,容易频繁改变

LOST_LINE_MAX (丢线最大帧数)

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

ADAPTIVE_ALPHA_HIGH (大误差时的滤波系数)

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)

ADAPTIVE_ALPHA_LOW (小误差时的滤波系数)

const float ADAPTIVE_ALPHA_LOW = 0.2f;  // 当 error < 0.3 时使用

作用: 误差很小时,降低滤波系数以保持平滑

为什么选择 0.2?

  • 接近中线时,传感器信号会有微小波动
  • 0.2的低滤波系数(高惯性)可以忽略这些波动
  • 结果是更平稳的运动

调整建议:

  • 如果中线附近有抖动 → 降低到 0.1~0.15
  • 如果反应太慢 → 提高到 0.25~0.30

📊 静态变量说明

filtered_error (滤波后的误差)

static float filtered_error = 0.0f;
  • 存储低通滤波后的误差值
  • 用于PD控制计算
  • 比raw_error更平滑,受噪声影响小

last_error (上一帧的滤波误差)

static float last_error = 0.0f;
  • 用于计算误差微分:d_error = filtered_error - last_error
  • 反映误差变化速度
  • 每帧更新一次

last_turn_direction (上次转向方向)

static int last_turn_direction = 1;  // -1左,1右
  • 记录小车最后一次明显转向的方向
  • 丢线时,用这个方向进行搜索
  • 只在 |error| > TURN_THRESHOLD 时更新

lost_line_count (连续丢线帧计数)

static int lost_line_count = 0;
  • 统计连续检测不到黑线的帧数
  • 每次丢线时 +1
  • 找到线后重置为 0
  • 超过 LOST_LINE_MAX 时切换搜索模式

use_alternate_search (是否使用交替搜索)

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.35

平衡方案(推荐入门)

BASE_SPEED = 190
MAX_CORRECTION = 140
KP = 40
KD = 95
ALPHA = 0.35

高速模式(本配置)

BASE_SPEED = 240
MAX_CORRECTION = 165
KP = 55
KD = 110
ALPHA = 0.45

极限竞速(不推荐新手)

BASE_SPEED = 255
MAX_CORRECTION = 200
KP = 70
KD = 130
ALPHA = 0.55

完整详细版本!可以直接作为参考手册 📚

About

智能小车循迹项目

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors