1. 项目概述
这个基于STM32和OpenMV的视觉循迹避障小车项目,是我最近完成的一个很有意思的嵌入式AI实践。作为一个玩了多年嵌入式开发的"老司机",我觉得这个项目特别适合想要入门嵌入式视觉和AI的朋友们。它不仅涵盖了硬件搭建、软件开发,还涉及到一些基础的机器视觉算法,可以说是嵌入式AI入门的绝佳练手项目。
1.1 核心功能解析
这个小车主要有两个核心功能:
首先是循迹功能。通过OpenMV摄像头识别地面上的黑色轨迹线,然后计算出小车偏离轨迹的角度,最后通过STM32控制舵机转向,让小车始终沿着黑线行驶。这个功能的关键在于视觉识别和转向控制的配合。
其次是避障功能。当超声波传感器检测到前方有障碍物时,小车会自动停止前进,然后执行避障动作。这里我们采用的是后退+转向的策略,简单但很有效。
提示:在实际测试中,我发现避障距离设置在15cm左右效果最好。太近容易撞上,太远又会影响行驶流畅度。
1.2 技术架构详解
整个系统的架构可以分为三层:
硬件层:
- STM32F103C8T6作为主控芯片
- OpenMV Cam H7负责视觉处理
- L298N电机驱动模块
- SG90舵机控制转向
- HC-SR04超声波模块用于避障
通信层:
- UART串口用于STM32和OpenMV之间的通信
- GPIO控制电机和舵机
- 中断处理紧急情况(如急停)
软件层:
- STM32固件负责底层控制
- OpenMV运行视觉算法
- 双模式切换逻辑
2. 硬件准备与搭建
2.1 硬件选型指南
在选择硬件时,我主要考虑了以下几个因素:
- 性价比:STM32F103C8T6价格便宜但性能足够
- 易用性:OpenMV有完善的视觉库,开发门槛低
- 扩展性:L298N驱动模块可以支持更大功率的电机
硬件清单如下:
| 组件 | 型号 | 数量 | 备注 |
|---|---|---|---|
| 主控板 | STM32F103C8T6 | 1 | 最小系统板即可 |
| 视觉模块 | OpenMV Cam H7 | 1 | 注意要买带镜头的版本 |
| 电机驱动 | L298N | 1 | 双H桥设计 |
| 直流电机 | TT马达 | 2 | 带减速齿轮的版本更好 |
| 舵机 | SG90 | 1 | 9g微型舵机 |
| 超声波模块 | HC-SR04 | 1 | 测距范围2-400cm |
| 电源 | 18650电池组 | 1 | 建议2节串联(7.4V) |
2.2 电路连接详解
接线是很多新手容易出错的地方,这里我详细说明下关键连接:
-
OpenMV与STM32的连接:
- OpenMV的TX接STM32的PA10(RX)
- OpenMV的RX接STM32的PA9(TX)
- 共地连接很重要!
-
电机驱动连接:
- IN1-IN4接STM32的PB8-PB11
- 电机输出接两个TT马达
- 注意电机极性,接反了会反转
-
舵机连接:
- 信号线接STM32的PB6
- 供电直接从L298N取5V
-
超声波模块:
- TRIG接PA1
- ECHO接PA2
注意:所有外设的GND都必须连接到一起,否则会出现通信异常。
3. 开发环境配置
3.1 STM32开发环境搭建
我推荐使用Keil MDK + STM32CubeMX的组合:
- 安装Keil MDK-ARM(记得安装STM32F1的Device Family Pack)
- 安装STM32CubeMX并下载STM32F1的HAL库
- 在CubeMX中配置项目:
- 时钟树设置为72MHz
- 启用USART1,波特率115200
- 配置TIM2的CH1为PWM输出(舵机控制)
- 配置TIM3的CH1-CH2为PWM输出(电机控制)
这里有个小技巧:在CubeMX中生成代码时,勾选"Generate peripheral initialization as a pair of .c/.h files",这样代码结构会更清晰。
3.2 OpenMV开发环境配置
OpenMV的开发相对简单:
- 下载OpenMV IDE(官网有各平台版本)
- 连接OpenMV摄像头,会自动提示固件更新
- 更新到最新固件后,就可以开始编程了
关键库的导入:
python复制import pyb # 硬件控制
import sensor # 摄像头控制
import image # 图像处理
import time # 时间控制
import math # 数学计算
from machine import UART # 串口通信
4. 核心代码实现
4.1 STM32主控程序设计
电机控制函数是核心之一,这里采用简单的电平控制:
c复制void Motor_Control(int speed_left, int speed_right) {
// 左电机控制
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, (speed_left > 0) ? GPIO_PIN_SET : GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, (speed_left < 0) ? GPIO_PIN_SET : GPIO_PIN_RESET);
// 右电机控制
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, (speed_right > 0) ? GPIO_PIN_SET : GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, (speed_right < 0) ? GPIO_PIN_SET : GPIO_PIN_RESET);
}
舵机控制需要注意PWM参数:
c复制void Servo_SetAngle(uint16_t angle) {
// 500对应0度,2500对应180度
TIM2->CCR1 = 500 + (angle * 10);
}
4.2 OpenMV视觉处理算法
循迹的核心是图像处理算法:
python复制def find_line():
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QQVGA) # 160x120分辨率足够
sensor.skip_frames(time=2000) # 等待摄像头稳定
uart = UART(3, 115200) # 使用UART3
while True:
img = sensor.snapshot()
# 检测黑色线 (0-64灰度值)
line = img.get_regression([(0, 64)], robust=True)
if line:
angle = line.theta()
if angle > 90: # 将角度转换到-90~90度范围
angle = angle - 180
uart.write("A%d\n" % angle) # 发送角度给STM32
4.3 避障逻辑实现
超声波测距的实现:
python复制def avoid_obstacle():
trigger_pin = Pin('P0', Pin.OUT)
echo_pin = Pin('P1', Pin.IN)
uart = UART(3, 115200)
while True:
# 发送10us的高电平触发信号
trigger_pin.low()
time.sleep_us(2)
trigger_pin.high()
time.sleep_us(10)
trigger_pin.low()
# 等待回波
while echo_pin.value() == 0:
signal_off = time.ticks_us()
while echo_pin.value() == 1:
signal_on = time.ticks_us()
# 计算距离 (声速343m/s)
distance = (signal_on - signal_off) * 0.0343 / 2
if distance < 15: # 15cm阈值
uart.write("STOP\n") # 发送停止指令
5. 系统调试与优化
5.1 循迹模式调试技巧
-
轨迹线制作:
- 使用黑色电工胶带,宽度建议2cm左右
- 背景最好用浅色,对比度要明显
-
参数调整:
- 在OpenMV IDE中实时查看图像处理效果
- 调整阈值
[(0, 64)]直到能稳定识别黑线
-
转向灵敏度:
- STM32端的角度补偿系数需要实测调整
- 初始可以设为
90 + angle/2,然后根据实际效果微调
5.2 避障模式调试要点
-
超声波模块安装:
- 确保朝向正前方
- 离地高度约10-15cm
-
避障策略优化:
- 后退时间500ms比较合适
- 转向角度可以随机左右,避免陷入局部循环
-
防误触发机制:
- 连续检测到3次障碍才触发
- 加入滤波算法消除偶发干扰
6. 常见问题与解决方案
在实际开发中,我遇到了不少坑,这里分享几个典型问题:
-
OpenMV无法识别黑线
- 原因:环境光线太强/太弱
- 解决:调整阈值范围,或者增加补光灯
-
小车转向抖动严重
- 原因:PWM频率不合适
- 解决:将舵机PWM频率调整为50Hz,电机PWM频率10kHz
-
串口通信不稳定
- 原因:波特率不匹配或接线错误
- 解决:确认双方都是115200,检查TX/RX是否交叉连接
-
电机偶尔不响应
- 原因:电源供电不足
- 解决:使用单独的18650电池��电机供电
-
超声波测距不准
- 原因:环境回声干扰
- 解决:增加多次测量取平均值的算法
7. 项目扩展思路
这个基础版本完成后,还可以考虑以下扩展方向:
-
增加更多传感器
- 添加红外传感器增强避障能力
- 加入IMU实现更精准的运动控制
-
升级视觉算法
- 使用AprilTag实现精确定位
- 加入颜色识别实现多路线选择
-
无线控制功能
- 增加蓝牙或WiFi模块
- 开发手机APP远程监控
-
自主导航
- 结合SLAM算法实现地图构建
- 加入路径规划功能
这个项目最让我满意的是它的可扩展性。通过更换不同的传感器和算法,可以实现从简单到复杂的各种功能,非常适合作为嵌入式AI学习的平台。我在开发过程中最大的体会是:硬件项目一定要边做边调,纸上谈兵是行不通的。
