概要
基于STM32F4的智能巡线识别小车,巡线采用openmv,识别采用k210
整体架构流程
1.电机选用的是13线的编码电机
2.巡线采用openmv
3.识别采用k210
4.主控为STM32F407ZGT6
技术细节
(1)巡线移动。采用openmv循迹和步进电机的巡线移动方案。
(2)识别病房号数字。可采用k210视觉单片机识别。由于追求识别准确率,所以单个数字的数据集有300张。
(3)k210的训练可以在MainHub这个网站上进行yolo2的训练,亲测不错。将训练模型和main.py放进SD卡中就可以运行了.网站链接:
Maixhub 模型训练 - Sipeed Wiki
(4)运行openmv的循迹时一定要插一张SD卡,不知道为啥有时代码会跑没!!!
代码部分
main.c
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
delay_init(168);
uart2_init(115200); //K210初始化
uart6_init(115200); //OPemMV初始化
uart_init(115200); //初始化串口UART1
// uart3_init(115200); //蓝牙初始化
LED_Init(); //LED初始化
// infra_init(); //5路灰度初始化
Motor_Init(); //电机初始化
Encoder_TIM_Init(); //编码器初始化
PWM_Init_TIM(83,999); //电机PWM初始化 //84M/84/1000=1000+
Speed_Pid_init();
Pid_Lin_Patrol();
OLED_Init(); //OLED初始化
OLED_Clear();
while(1)
{
//病房1
if((xinhao==0)&&(number=='1'))
{
Speed_pid_Init(20.f,20.f);
while(1)
{
find1();
}
}
//病房2
else if((xinhao==0)&&(number=='2'))
{
Speed_pid_Init(20.f,20.f);
while(1)
{
find2();
}
}
else{
Flag_start=1;
}
//数字3
if((xinhao==0)&&(number=='8'|number=='3'|number=='4'|number=='5'|number=='6'|number=='7'))
{
Speed_pid_Init(20.f,20.f);
if(crossroad == 0 && (L1 + L2 + M + R1 + R2) >=3) //第一个十字路口
{
slow();
crossroad++;
Flag_Direction='1';
}
if(crossroad == 1 && (L1 + L2 + M + R1 + R2) >=3)//经过第二个十字路口判断
{
if(Flag_Direction=='0') //3号病房
{
while(1)
{
find3();
}
}
else if(Flag_Direction=='2') //4号病房
{
while(1)
{
find4();
}
}
else
{
crossroad++;
// Flag_Direction=1;
}
}
if(crossroad == 2 && (L1 + L2 + M + R1 + R2) >=3)//经过第三个十字路口判断
{
if(Flag_Direction=='0') //5 8号病房
{
delay_ms(210);
turn_90_left_3();
crossroad++;
}
}
if(((L1 + L2 + M + R1 + R2) >=3)&& crossroad == 3 )//达到丁字路口
{
if(Flag_Direction=='0')
{
while(1)
{
find5();
}
}
else if(Flag_Direction=='2')
{
while(1)
{
find8();
}
}
}
if(crossroad == 2 && (L1 + L2 + M + R1 + R2) >=3) //6 7号病房
{
if(Flag_Direction=='2')
{
delay_ms(220);
turn_90_right_2();
crossroad++;
}
}
if( (L1 + L2 + M + R1 + R2) >=3 && crossroad == 3 )//达到丁字路口
{
if(Flag_Direction=='0')
{
while(1)
{
find7();
}
}
else if(Flag_Direction=='2')
{
while(1)
{
find6();
}
}
}
}
k210.c
#include "k210.h"
#include "usart.h"
#include "Motor_Drive.h"
char k210_data;
char number;
extern char Flag_Direction;
int flag=0;
void uart2_init(u32 bound){
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_USART2);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_USART2);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA,&GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = bound;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART2, &USART_InitStructure);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
// USART_ITConfig(USART2, USART_IT_TXE, ENABLE);
USART_ClearFlag(USART2,USART_FLAG_TC);
USART_Cmd(USART2, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void USART2_IRQHandler(void)
{
if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
{
char b;
USART_ClearFlag(USART2, USART_FLAG_RXNE);
b = USART2->DR;
if(flag==0)
{
number=b;
flag++;
}
Flag_Direction=b;
USART_SendData(USART2,b);
}
}
openmv.c
#include "openmv.h"
#include "sys.h"
//#include "bluetooth.h"
#include "control.h"
//#include "xinhao.h"
#include "delay.h"
//#include "motor.h"
#include "usart.h"
//
//如果使用ucos,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "includes.h" //ucos 使用
#endif
int L1,L2,M,R1,R2;
void uart6_init(u32 bound){
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6,ENABLE);
GPIO_PinAFConfig(GPIOG,GPIO_PinSource9,GPIO_AF_USART6);
GPIO_PinAFConfig(GPIOG,GPIO_PinSource14,GPIO_AF_USART6);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_14;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOG,&GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = bound;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART6, &USART_InitStructure);
USART_Cmd(USART6, ENABLE);
//USART_ClearFlag(USART6, USART_FLAG_TC);
USART_ITConfig(USART6, USART_IT_RXNE, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = USART6_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void USART6_IRQHandler(void)
{
if (USART_GetITStatus(USART6, USART_IT_RXNE) != RESET)
{
int a;
USART_ClearFlag(USART6, USART_FLAG_RXNE);
a = USART6->DR;
R2 = ((u8)a & 0x10) >> 4;
R1 = ((u8)a & 0x08) >> 3;
M = ((u8)a & 0x04) >> 2;
L1 = ((u8)a & 0x02) >> 1;
L2 = (u8)a & 0x01;
}
}
小结
其实这里偷了一个懒,药品的检测用的是一个红外对管,有时间的话各位还是试一试压力传感器吧