基于STM32F407VET6单片机的自动泊车系统设计
摘要
本文介绍了一个基于STM32F407VET6单片机的自动泊车系统的实现。该系统利用OpenMV模块、循迹检测模块、蜂鸣器模块和前轮转向式四轮车构建而成,旨在完成色块识别和自动泊车功能。系统通过模块化设计实现了从车库检测到自动泊车的一系列功能,能够适应不同场景下的自动泊车需求。
🚀完整项目源码下载链接👉:https://download.youkuaiyun.com/download/DeepLearning_/89900178
系统概述
功能需求
- 在相邻车库有车的情况下完成倒车入库和侧方位入库。
- 在相邻车库无车的情况下完成倒车入库和侧方位入库。
- 能够连续完成上述功能组合。
核心组件
- STM32F407VET6:作为核心处理器。
- OpenMV:用于色块识别。
- 循迹检测模块:用于检测地面库线。
- 蜂鸣器模块:用于声光提示。
- 直流电机和舵机:用于控制小车的运动。
方案论证
供电方案
- 方案一:电源直接给系统供电,存在电量损耗快的问题。
- 方案二:电源接入稳压模块给系统供电,确保电源电压稳定且可实时监测。
电机驱动方案
- 方案一:使用继电器,电路简单但不易精细控制。
- 方案二:使用分立元件构成电机驱动电路,结构简单但稳定性差。
- 方案三:使用DRV8701E作为电机驱动芯片,具有抗电磁干扰、驱动力强等优点,最终选用此方案。
摄像头方案
- 方案一:使用MT9V034神眼摄像头,特征识别函数编写复杂且识别精度低。
- 方案二:使用OpenMV,能够高效实现核心机器视觉算法,最终选用此方案。
理论分析与计算
PWM波配置
- 使用STM32F407的定时器2和定时器3生成PWM波,通过调整PWM波占空比来控制电机转速和舵机旋转角度。
- 定时器2的PWM波周期为0.02s,定时器3的PWM波周期为0.01s。
车库检测方法
- 对摄像头采集的视频进行实时色块检测,设定一个30×140的ROI区域,统计黑色像素点个数,当像素数达到设定阈值时,发送高电平信号给单片机,完成车库检测。
电路与程序设计
系统总体设计
- 核心处理器:STM32F407VET6。
- 主要模块:OpenMV模块、循迹检测模块、蜂鸣器模块、直流电机、舵机等。
单元电路设计
- 单片机最小系统:包括MCU、晶振和复位电路。
- 电机驱动模块:使用DRV8701E芯片。
- 独立按键模块:四位独立按键。
- 巡线避障模块:使用TCRT5000传感器。
系统程序设计
- 主程序流程:初始化各模块,按键扫描,执行倒车入库或侧方位入库操作,完成停车后出库。
- 定时器配置:生成PWM波控制电机和舵机。
- 电机控制:控制小车前进和倒退。
- 编码器:检测小车运行轨迹。
- 舵机控制:控制前轮转向。
- 色块识别:通过OpenMV模块识别车库。
测试方案与结果
测试仪器
- 电动车、秒表、比赛赛道。
测试方案
- 邻库有车:分别在距起点5cm、15cm、30cm处启动电动车,记录倒车入库和侧方位入库的时间和角度。
- 邻库无车:移除邻库车辆,重复上述测试。
测试结果
- 邻库有车:倒车入库和侧方位入库均能顺利完成,倒车时间在3秒左右,车身与库边夹角在10°左右。
- 邻库无车:同样能够顺利完成,倒车时间和角度与邻库有车情况相似。
结论
该系统通过模块化设计,成功实现了自动泊车功能。无论是在邻库有车还是无车的情况下,都能够准确识别车库并完成倒车入库和侧方位入库操作。系统性能稳定,满足设计要求。
附录
部分程序代码
#include "stm32f4xx.h"
#include "usart.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "pwm.h"
#include "timer.h"
#include "led.h"
#include "key.h"
#include "sensor.h"
#include "beer.h"
#include "speed.h"
#include "ste.h"
#include "Encoder.h"
int Flag_finish = 0;
int count_j = 0;
int main(void) {
LED_Init();
LED_Close();
delay_init(168);
delay_ms(7000); // 等待OpenMV完成初始化
TIM5_Int_Init(2000, 8399);
uart_init(115200);
Beer_Init();
speed_Init();
Sensor_Init();
ste_Init();
KEY_Init();
TIM_ETR_Init();
LED_Open(); // 各初始化完成标志
while (1) {
if (KEY_Num == 0) {
KEY_Num = KEY_Scan(0);
count_j = 0;
}
if (KEY_Num != 0 && count_j == 0) { // 有输入时延时2s
if (KEY_Num == 1) {
LED_Open();
Beer_Open();
delay_ms(500);
Beer_Close();
delay_ms(1500);
count_j++;
} else if (KEY_Num == 2) {
Beer_Close();
Beer_Open();
delay_ms(500);
Beer_Close();
delay_ms(1500);
count_j++;
}
}
// 前进识别
if ((KEY_Num == 1 || KEY_Num == 2) && Flag_back == 0) {
Forward_PWM(3000);
}
if (KEY_Num == 1 && Flag_back == 1) { // 倒车入库
Backward_PWM(0);
delay_ms(100);
STE_PWM(0);
TIM_SetCounter(TIM4, 0);
Backward_PWM(3000);
while (TIM_GetCounter(TIM4) < 170);
TIM_SetCounter(TIM4, 0); // 向后
STE_PWM(-300);
Backward_PWM(0);
delay_ms(100);
Forward_PWM(4000);
while (TIM_GetCounter(TIM4) < 400);
Forward_PWM(0);
STE_PWM(400);
delay_ms(100);
Backward_PWM(4000);
Beer_Open();
delay_ms(500);
Beer_Close();
while (Sensor1() == 0);
while (Sensor2() == 0);
delay_ms(200);
STE_PWM(0);
TIM_SetCounter(TIM4, 0);
while (TIM_GetCounter(TIM4) < 280);
Forward_PWM(0);
TIM_SetCounter(TIM4, 0); // 已入库
Beer_Open();
delay_ms(500);
Beer_Close();
delay_ms(4500);
Forward_PWM(4000); // 出库
// while (Sensor1() == 0 && Sensor2() == 0);
TIM_SetCounter(TIM4, 0);
while (TIM_GetCounter(TIM4) < 250);
STE_PWM(400);
TIM_SetCounter(TIM4, 0);
while (TIM_GetCounter(TIM4) < 1050);
// 进入完成阶段标志
Flag_finish = 1;
}
else if (KEY_Num == 2 && Flag_back == 1) { // 侧方位
TIM_SetCounter(TIM4, 0);
Forward_PWM(3000);
while (TIM_GetCounter(TIM4) < 400);
TIM_SetCounter(TIM4, 0);
Forward_PWM(0);
Beer_Open();
STE_PWM(200);
Backward_PWM(4000);
delay_ms(500);
Beer_Close();
while (Sensor1() == 0);
STE_PWM(-325);
TIM_SetCounter(TIM4, 0);
while (TIM_GetCounter(TIM4) < 600); // 已入库
Backward_PWM(0);
Beer_Open();
delay_ms(500);
Beer_Close();
delay_ms(4500);
Forward_PWM(4000); // 出库
while (Sensor2() == 0);
delay_ms(400);
STE_PWM(325);
TIM_SetCounter(TIM4, 0);
while (TIM_GetCounter(TIM4) < 770);
// 进入完成阶段标志
Flag_finish = 1;
}
if (Flag_finish == 1 && Flag_back == 1) { // 完成阶段标志
STE_PWM(0);
TIM5_Int_Init(2000, 8399);
TIM_SetCounter(TIM4, 0);
Forward_PWM(3000);
while (TIM_GetCounter(TIM4) < 500);
Forward_PWM(0);
TIM_SetCounter(TIM4, 0);
Flag_finish = 0;
Flag_back = 0;
KEY_Num = 0;
}
}
}
电路连接原理
- 详细电路图见设计报告附录。
实验结果照片
- 图片见设计报告附录。