题目归属:2023 年全国大学生电子设计竞赛 E 题《运动目标控制系统》
本仓库定位:以 STM32F103 + 双路步进电机 + K230 视觉 实现的云台闭环方案(相对舵机方案的「步进版」)
MCU:STM32F103C8(标准外设库)|视觉:K230 / 绿山派 |驱动:A4988 / DRV8825 / TMC2209(STEP/DIR)
E 题要求完成一套 「看见目标 → 控制执行机构 → 让激光/指示点跟上运动目标」 的系统,核心能力大致包括:
| 能力维度 | 题目侧关注点 | 本工程对应实现 |
|---|---|---|
| 目标感知 | 摄像头识别色块/激光/路径点,输出图像坐标 | K230 视觉脚本 + UART 定长二进制帧 |
| 二维控制 | 水平(Pan)+ 俯仰(Tilt)双轴云台 | 两路步进电机,独立位置环 |
| 动态跟随 | 目标运动时误差收敛、少抖、少丢步 | 像素误差 → PID → 每帧步数 → 可打断加减速运动 |
| 稳态品质 | 对准后抖动小、有死区与限幅 | ERR_DEADZONE、PID 输出限幅、Motor_Stop 平滑停 |
| 可演示性 | 方向可校、参数可调、现场可排障 | 假目标模式、OLED 实时 T/A/E/S、方向宏 |
题目本身不强制用舵机还是步进:舵机实现快、力矩包线友好;步进精度高、可开环累计位置、便于做平滑加减速与「步/帧」量化控制。本仓库选择后者,作为 E 题的 步进电机云台备赛/复现方案。
K230 每帧给出「实际点 actual」与「目标点 target」
→ STM32 算像素误差
→ 双轴 PID 输出「本帧要走的相对步数」
→ 双步进在中断里按梯形/三角加减速发 STEP 脉冲
→ 让 actual 追上 target(误差 → 0)
即:视觉闭环的二维跟踪云台,执行器是双步进,不是舵机。
同账号下另有舵机方案:2023-dian-sai-visual-gimbal。
| 对比项 | 舵机云台 | 本仓库(步进云台) |
|---|---|---|
| 执行器 | 舵机 PWM 角度 | 步进 STEP/DIR + 驱动板 |
| 控制量单位 | 度/帧 | 步/帧 |
| 位置模型 | 角度指令 | 开环累计步数 position |
| 运动品质 | 舵机内部曲线 | 显式梯形/三角加减速(v=√(v²±2a)) |
| 视觉协议 | 同一套 0xAA…0x55 思路 |
与本仓 k230 模块一致,便于双方案共用视觉脚本 |
┌─────────────────────┐
12V 电源 ────────►│ 双路步进驱动板 │────► 步进电机×2(水平 / 俯仰)
│ STEP/DIR/EN/GND │
└──────────▲──────────┘
│ STEP/DIR
┌──────────┐ UART 115200 ┌───┴──────────────┐ 软件 I2C ┌────────┐
│ K230 │──────────────►│ STM32F103C8 │───────────►│ OLED │
│ 视觉 │ TX → PA10 │ PID + 运动规划 │ PB8/PB9 │ 0.96" │
└──────────┘ └──────────────────┘ └────────┘
│ GND 共地 │ GND 共地
└──────────────────────────────┘
K230 视觉 --UART 115200--> k230 状态机 --> g_rect_data
|
actual=(x1,y1) target=(x2,y2)
v
err = target - actual(像素)
|
PID(输出:步/帧)+ 方向宏 + 死区
v
Motor_Move / Motor_Stop(可打断重规划)
MOTOR1=水平 MOTOR2=俯仰
|
v
OLED 显示 T / A / E / S
| 功能 | STM32 引脚 | 外设 | 说明 |
|---|---|---|---|
| 水平轴 STEP | PA0 | TIM2_CH1 PWM | 硬件发脉冲 |
| 水平轴 DIR | PA3 | GPIO | 方向 |
| 俯仰轴 STEP | PA6 | TIM3_CH1 PWM | 硬件发脉冲 |
| 俯仰轴 DIR | PA7 | GPIO | 方向 |
| 视觉串口 RX | PA10 | USART1_RX | ← K230 TX |
| 视觉串口 TX | PA9 | USART1_TX | 可选回传 |
| OLED SCL/SDA | PB8 / PB9 | 软件 I2C | 调试显示 |
| EN | 按驱动板常使能 | — | 常见低有效接 GND |
- 典型 1.8° 步进:200 步/圈;× 细分倍数 = 软件步数。
- 工程注释默认按 32 细分 → 6400 步/圈 估算;拨码细分必须与软件一致,否则 PID 等效增益全错。
- 驱动板 VMOT 常用 12V,信号地与电源地、STM32、K230 必须共地。
- 详细接表、上电顺序、排障见仓库根目录
连线说明书.md。
| 方案 | 问题 |
|---|---|
| 主循环 bit-bang | 帧率一抖,脉冲周期就抖;双轴更难保证 |
| 延时发脉冲 | 占满 CPU,视觉 PID 被饿死 |
| PWM 硬件发 STEP + 更新中断只数步/改 ARR | 脉冲由硬件产生;中断只做「一步完成 → 更新速度 → 写 ARR」 |
时基取 1 MHz(PSC=71 @ 72 MHz),使 ARR ≈ 每步微秒数,调参与示波器对照都直观。
User/main.c # 双模式主循环:假目标 / 真视觉闭环
Hardware/
Motor.c / Motor.h # 【S级】双路步进 + 梯形/三角加减速
bsp_pid.c / bsp_pid.h # 【A级】位置式 PID(输出=步/帧)
k230.c / k230.h # 【A级】UART 帧状态机
bsp_usart.c / .h # USART1 初始化
OLED.* # 调试界面
Key / LED # 预留
System/ Library/ Start/ # 启动、延时、标准库
连线说明书.md # 硬件接线全文
Project.uvprojx # Keil 工程
定长 12 字节 二进制帧:
| 字段 | 内容 |
|---|---|
| 帧头 | 0xAA |
| x1,y1,x2,y2,z | 各 2 字节,大端有符号 int16 |
| 帧尾 | 0x55 |
本工程语义约定(与 2023 舵机云台一致):
(x1, y1)= Actual 实际点(路径点 / 红点等)(x2, y2)= Target 目标点(激光或另一色点)- 闭环目标:
err = target - actual → 0 is_updated:中断解析成功置 1,主循环处理完必须清 0
解析在 K230_UART_Handler 中用 状态机 完成(等头 → 收 10 字节 → 校验尾),适合在 RXNE 中断里逐字节喂入,无动态内存。
out = Kp·e + Ki·∫e + Kd·(e − e_last)
e = target_pixel − actual_pixel
out 单位 = 本帧相对步数(再乘 PAN_DIR / TILT_DIR)
要点:
- 单位是步/帧,不是度;限幅
max_output≈40防止单帧猛甩丢步。 - 云台跟踪建议 先 Kp,略加 Kd,Ki 慎用(丢目标时积分易飙升)。
|err| < ERR_DEADZONE(默认 3 像素)时强制 0 步并Motor_Stop,抑制检测噪声抖动。- 默认参数见
main.c:水平约Kp=0.35,俯仰约Kp=0.27,可按负载与细分再调。
Motor_Move(id, steps):
- 按
v² = v0² + 2·a·s规划加速段长度;总步数不够则 三角曲线,够则 梯形(加速–匀速–减速)。 - 每一步在更新中断里用
v = √(v² ± 2a)刷新速度,再写 ARR。 - 方案 A:运动中可再次
Motor_Move打断并重规划,绝对位置position保留。- 这是「demo 走完再走」与「视觉每帧改主意」的分界线。
- 旧逻辑「忙则丢指令」会导致跟手差,不适合 E 题动态目标。
平滑停用 Motor_Stop(估算减速段),不要指望 Motor_Move(0) 停车(0 会直接 return)。
| 宏 | 含义 | 用途 |
|---|---|---|
USE_FAKE_VISION = 1 |
固定 target/actual,大步分段测方向 | 不上 K230 也能验机械与轴方向 |
USE_FAKE_VISION = 0 |
读 g_rect_data 真闭环 |
正式视觉跟踪 |
联调推荐顺序:
- 假目标:确认水平/俯仰方向 → 反了改
PAN_DIR/TILT_DIR(±1) - 接 K230,真闭环:看 OLED 上 E 是否收敛、S 是否在动
- 调 Kp / 死区 / vMax / accel,平衡「跟手」与「抖」
| 行 | 含义 |
|---|---|
| T: X Y | Target 目标像素(假目标模式末尾带 F) |
| A: X Y | Actual 实际像素 |
| E: X Y | 误差 err = T − A |
| S: P T | 步进累计位置:Pan / Tilt |
现场判读:E 不收敛 → 方向/增益/视觉语义;E≈0 但抖 → 死区/Kd/vMax;S 不动 → 使能/细分/脉冲是否输出。
- Keil 打开
Project.uvprojx(或 EIDE / VS Code 的Project.code-workspace) - 目标芯片 STM32F103C8,下载器 SWD
- 按
连线说明书.md接好电机、驱动板、K230、共地
信号与共地接好 → 再开 12V 电机电源 → 再给 STM32/K230 上电(或按现场电源方案同时上,但避免「先转轴再飞线」)。
| 参数 | 默认倾向 | 说明 |
|---|---|---|
| 起步 v0 | 120 步/秒 | pull-in,过高易启动失步 |
| 峰值 vMax | 2500 步/秒 | 过高易共振啸叫 |
| 加速度 | 1200 步/秒² | 过高启停硬抖 |
| 像素死区 | 3 | 抑制微抖 |
| 现象 | 可能原因 | 处理 |
|---|---|---|
| 有啸叫几乎不转 | PID 每帧仅 1~2 步 + 频繁打断 | 假目标改大步分段;真闭环略增 Kp/max_output |
| 猛抖、失步 | vMax/accel 过大 | 降峰值与加速度 |
| 跟不住动态目标 | 忙时丢弃 Motor_Move |
使用可打断版 Motor_Move(本仓已实现) |
| 方向反了 | 安装镜像 / 接线 | PAN_DIR / TILT_DIR 取反 |
| 完全不转 | EN 未使能、未共地、无 12V | 查驱动板 EN 与电源 |
| 细分对不上 | 拨码 ≠ 软件假设 | 统一细分,重估 Kp |
| 串口无数据 | TX/RX 反、波特率、电平 | 115200 8N1,K230_TX→PA10,3.3V |
S 级(电机)
- 灵魂公式
v = √(v² ± 2a)逐步调速 - 三角 / 梯形自动切换
- PWM 硬件发脉冲,中断只数步调速
- ARR 不预装载 + 溢出瞬间更新,减滞后与毛刺
- 1 MHz 时基使 ARR 物理意义清晰
A 级(闭环)
- 定长帧状态机解析视觉坐标
- 像素 PID 与「步/帧」单位设计
- 死区 + 输出限幅 + 平滑停
- 可打断运动规划,服务视觉每帧更新
| 仓库 | 说明 |
|---|---|
| 2023-dian-sai-visual-gimbal | 2023 E 题 · 舵机视觉云台 |
| brushless-motor | 无刷相关实验 |
| lingke-6axis-gyro | 六轴 IMU |
| jy901s | 维特 JY901S |
| mpu6050 | MPU6050 + DMP |
本仓库用于 2023 电赛 E 题备赛学习与方案复现,硬件参数、PID 与运动学需按你的机械负载与细分自行标定。
欢迎 Issue / PR 补充实测参数、视觉脚本与演示视频链接。
题目:2023 年全国大学生电子设计竞赛 E 题 · 运动目标控制系统
方案:STM32 双步进 + K230 视觉闭环云台