Files
Loongson_2k0300_SmartCar/docs/ENCODER_BRAKE.md
T

123 lines
4.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 编码器刹车 — 设计与实现
## 1. 硬件
编码器引脚:
| 信号 | 引脚 | 模式 |
|---|---|---|
| LSB 脉冲 | GPIO 67 | 输入 |
| DIR 方向 | GPIO 72 | 输入 |
两引脚均属 gpiochip64GPA64base=6416 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
```