# 编码器刹车 — 设计与实现 ## 1. 硬件 编码器引脚: | 信号 | 引脚 | 模式 | |---|---|---| | LSB 脉冲 | GPIO 67 | 输入 | | DIR 方向 | GPIO 72 | 输入 | 两引脚均属 gpiochip64(GPA64,base=64,16 pins)。 ## 2. 编码器线程 `ControlInit()` 启动独立线程 `encoder_thread()`(`src/control.cpp:30`),持续运行直到 `ControlExit()`。 ``` encoder_thread(): 高频轮询 GPIO67 (LSB 边沿) + GPIO72 (方向) 轮询间隔: 500µs sleep (~2kHz) 每 100ms 窗口: g_enc_speed = pulse_cnt / elapsed_time (脉冲/秒, 原子变量) g_enc_dir = GPIO72 当前值 (原子变量) pulse_cnt 归零, 开始新窗口 ``` 通过 sysfs 文件描述符轮询(`GPIO::readValue()`),`lseek` + `read`。不依赖中断。 ## 3. 触发条件 `ControlUpdate(speed, block)` 中 `block == true` 时进入刹车流程。 `block` 信号来源(两者取 OR): - **斑马线**: `zebra_process()` 返回 true 当 `g_zstate == Z_STOP` - **红绿灯**: `traffic_light_process()` 返回 true 当 `g_tl_state != TL_NORMAL` 调用链: `motor_update(zebra_block, tl_block)` → `ControlUpdate(final_spd, zebra_block || tl_block)` ## 4. 比例刹车 无状态机,每帧根据编码器实时速度计算刹车力度: ``` ControlUpdate(speed, zebra_block): if !g_cfg.start → 两电机 duty=0, GPIO73 拉低, return if zebra_block: cur_speed = g_enc_speed.load() ← 编码器线程原子读 cur_dir = g_enc_dir.load() if cur_speed > 0.5: ← 仍在运动 brake_ns = cur_speed × g_cfg.brake_scale brake_ns = clamp(brake_ns, 0, g_cfg.brake_max) brake_pct = brake_ns / 500.0 ← ns → % (period=50000ns) motor[i]->updateduty(±brake_pct) ← 反向占空比 (方向取反) else: ← 已停止 (< 0.5 pps) motor[i]->updateduty(0) ← 不施加刹车 return 正常行驶: motor[0].updateduty(speed) motor[1].updateduty(speed) mortorEN.setValue(1) ``` **特点:** - **比例刹车**: 速度越快 → 刹车占空比越大 → 刹车力越强 - **自动停止**: 速度降到 0.5 pps 以下自动释放刹车,防止过冲 - **反向驱动**: 根据编码器方向 `cur_dir` 施加反方向 PWM ## 5. 参数 可通过文本文件热更新(debug 模式下每 30 帧重载): | 文件 | 类型 | 默认 | 含义 | |---|---|---|---| | `./brake_scale` | double | 10 | 速度(pps) → 刹车占空比(ns) 缩放系数 | | `./brake_max` | int | 10000 | 最大刹车占空比 (ns), 上限保护 | **数值示例:** 编码器读数 500 pps → brake_ns = 500 × 10 = 5000 ns → brake_pct = 5000/500 = 10% (period=50000ns, 即 duty = 50000 × 10/100 = 5000 ns 的 PWM 反转输出) ## 6. `updateduty()` 内部 ``` MotorController::updateduty(duty): pwm_ns = period × |duty| / 100 ← 转为占空比 ns → 写入 sysfs duty_cycle duty > 0 → GPIO 方向 = 1 (正转) duty ≤ 0 → GPIO 方向 = 0 (反转) ``` motor[0]: pwmchip8/pwm2 + GPIO12(左电机) motor[1]: pwmchip8/pwm1 + GPIO13(右电机) GPIO73: 电机使能 (mortorEN) ## 7. 生效范围 - **斑马线 STOP + 红绿灯 STOP/WAIT_GREEN** 时使用编码器刹车 - 正常行驶时编码器线程持续运行但刹车不触发 - 锥桶/挡板避障不使用编码器刹车(仅减速+绕行) - `g_cfg.start == 0` 时全部电机停转,不进入刹车流程 ## 8. 关键代码路径 ``` main.cpp └── while(running) └── CameraHandler() ├── zebra_process() → zebra_block ├── traffic_light_process() → tl_block └── motor_update(zebra_block, tl_block) └── ControlUpdate(final_spd, zebra_block || tl_block) └── if (block) → 读 g_enc_speed/g_enc_dir → 比例刹车 ControlInit() └── encoder_thread() 后台运行 → g_enc_speed, g_enc_dir ```