板级连接 与执行器
所有映射均来自当前 Keil 工程的实际初始化代码。五路探头顺序、双电机方向脚、OLED 软 I²C 与蓝牙串口共用同一块 STM32F103C8T6。
整车功能布局
top view schematicADC1 + DMA
5 路 12 位模拟量循环扫描,DMA 后台写入 AD_Value[5],主循环直接取整帧。
TIM2 双路 PWM
72 MHz ÷ 720 ÷ 100,得到 1 kHz PWM;占空比范围 0–100,最小有效占空比 28。
OLED 128×64
PB8/PB9 软件 I²C,4 行 × 16 列 HUD 显示方向、偏差、左右输出与状态位图。
USART3 / HC-05
9600 8N1,RXNE 中断接收;字符 K 切换模式,其余指令进入遥控状态。
工程构建 框架
Keil uVision 工程按 Start / Library / System / Hardware / User 五个分组组织;最后一次 Rebuild 为 0 Error、0 Warning,并生成可直接烧录的 HEX。
Target 1 · 编译配置
Project.uvprojx固件占用
from build.log.c · .h · .sarmcc -cstartup_stm32f10x_md.sProject.axfProject.hex源码分组 · Group View
5 groups模块依赖图
call / linkCode=11710 · RO=1810 · RW=64 · ZI=1648;链接输出 .\Objects\Project.axf,随后由 fromelf 生成 HEX。编译日志显示 0 Error、0 Warning,耗时约 1 秒。
Key.c、LED.c、PWM.c 存在于 Hardware 文件夹,但当前 Project.uvprojx 未收录。Key 使用 PB11(与蓝牙 RX 冲突),LED 使用 PA2(与左轮 PWM 冲突),因此不能直接加入现有工程。
循迹算法 与控制链路
从模拟电压到轮端 PWM 的每一次转换都可追溯到源码。控制周期固定 5 ms,误差以 5 路黑度加权求取,再经过 PD、速度调度与差速混合。
五路黑度与偏差
E = Σ(weight[i] × dark[i]) / Σdark[i]
权重 [-2,-1,0,1,2];总黑度 < 0.12 判为丢线,返回 999.0。线落在两探头之间时仍能得到 0.5 级连续误差。
位置式 PD
D = E − E_prev
U = Kp·E + Ki·I + Kd·D
U = clamp(U, −45, 45)
当前参数 Kp=20.0, Ki=0.0, Kd=25.0,实际表现为 PD;丢线时清空积分与上一拍误差,避免重新压线时猛打方向。
差速混合与死区
if |E| < 0.3 → U = 0
L = base + U
R = base − U
刚过弯后 corner_hold=50 拍维持 40 低速;中心 0.3 死区抑制 S 弯交叉点附近的“画龙”摆动。
极限差速与轮端
nonzero |v| < 30 → sign(v)·30
Car_Move(L, R) → PWM 0…100
最外侧探头压线时跳过 PID 直接打死;MOTOR_LR_SWAP=1 在 Car_Move 入口交换两路,以补偿实车接线反接。
五路循迹 实时仿真
拖动黑线位置,观察 AD 黑度、加权误差、PD 补偿与轮端输出如何变化。模型复现源码中的阈值、死区、极限差速与最低速度限制。
Sensor / control visualizer
TRACK · 5 msTelemetry
computed from source formulas说明:传感器响应采用随距离线性衰减的可视化近似;黑度归一化、加权误差、PD、45 补偿限幅、30 最低速度、70/−30 极限差速等控制量按源码规则计算。
迷宫状态机 与脱困策略
主循环每 5 ms 进入一次状态机。正常循迹之外,还包含死胡同掉头、终点锁停、丢线搜索、倒车脱困与卡死自救。
Active state graph
click a node十字 / 三路压黑
≥3 路黑视为路口,强制直行 60×5ms=300ms 冲过去;随后冷却 1s,防止同一路口重复触发。
死胡同
位图 mb & 0x1B == 0x1B(两侧各两路黑)时停车 200 ms,再原地右转,最长 3 s;中间探头压线即恢复循迹。
虚线区
“黑 → 短白 → 黑”连续 3 次,且白间隙持续 10–400 ms,判定进入虚线区;长白会清零计数。
T 字终点
进入虚线区后,五路全黑持续 100ms 才锁停;ST_STOP 永久停车,等待重新上电或模式切换。
丢线 / 卡死
丢线依次尝试直行、按方向打死、原地慢转、停车找线;传感器 3 s 无变化则原地转 360°,左右各一次。
JUNC_LEFT_RULE=0 与 AUTO_TURN90=0,所以 ST_JWAIT → ST_JADV → ST_TURN 这套“路口一律左转 / 定时 90°”路径仍然编译保留,但不会被当前主流程触发。页面以实际可达状态为主。蓝牙遥控 与 OLED 仪表
比赛时迷宫区禁止遥控;蓝牙模式作为调试与资源区接管通道。USART3 中断接收单字符指令,500 ms 无新指令自动停车。
Command pad
click to preview每次收到有效指令重置 REMOTE_TIMEOUT_CNT=50;倒计时归零后 motor_cmd='S',防止断连后车辆继续行驶。
按键为页面内交互预览,不会向真实小车下发蓝牙数据。
OLED HUD preview
128 × 64 / 4 × 16第 1 行运动方向;第 2 行误差 / PD 补偿 / 当前模式;第 3 行左右轮输出;第 4 行五路压黑位图、黑线数、虚线区标志与心跳字符。刷新周期 50ms。
关键参数 速查表
以下数值直接取自当前源码与 Keil 工程,便于现场调车时快速定位。BASE_SPEED 等旧宏仍存在,但实际循迹由动态 base 覆盖。
循迹控制
PID.c / main.c| 比例系数 kp | 20.0 |
| 积分系数 ki | 0.0 |
| 微分系数 kd | 25.0 |
| 白底 ADC 参考 | 3370 |
| 黑线 ADC 参考 | 60 |
| 丢线总黑度门限 | 0.12 |
| PID 补偿限幅 | ±45 |
| 中心死区 | 0.3 |
| 直道 / 弯道基础速度 | 45 / 30 |
| 极限差速 | +70 / −30 |
迷宫事件
main.c| 主循环周期 | 5 ms |
| 冲十字直行 | 300 ms |
| 路口冷却 | 1 s |
| 死胡同停车 | 200 ms |
| 掉头最长 | 3 s |
| 掉头速度 | ±50 |
| 虚线短白窗口 | 10–400 ms |
| 虚线交替次数 | 3 次 |
| 终点全黑保持 | 100 ms |
| 卡死检测 | 3 s |
is_after_dashed && mb == 0x1F;FINISH_BLACK_MIN 宏存在但未参与最终判断。外设与通信
ADC / Motor / blue| MCU 主频 | 72 MHz |
| ADC 时钟 | 12 MHz |
| ADC 分辨率 / 通道 | 12 bit / 5 |
| PWM 频率 | 1 kHz |
| PWM 最小占空比 | 28 |
| 蓝牙波特率 | 9600 8N1 |
| 遥控超时 | 50 ticks |
| 遥控速度 F/B | ±45 |
| 遥控转向 L/R | ±60 |
| 冲刺 y/t | ±100 |
Source map
User/main.c1209 行 · 主循环 / 状态机 / 模式切换Hardware/PID.c黑度加权 / 偏差 / PD 补偿Hardware/Motor.c双轮 PWM / 方向 / 最小占空比Hardware/ADC.cADC1 + DMA 五通道采样Hardware/blue.cUSART3 中断 / 指令解析Hardware/OLED.c软件 I²C / 128×64 HUDProject.uvprojxTarget 1 · 分组 / 工具链 / 输出build.log0 Error · 0 Warning · 内存占用