基于STM32红外避障小车的设计(有代码)

您所在的位置:网站首页 红外避障小车毕业论文 基于STM32红外避障小车的设计(有代码)

基于STM32红外避障小车的设计(有代码)

2023-01-22 23:07| 来源: 网络整理| 查看: 265

什么是避障小车

用红外光电传感器,探测到物体即输出脉冲,输入到单片机中处 理一下,再对电机驱动模块进行控制,实现壁障的功能,这样的避障小车又称为简单的避障机器人。

各种避障方法: 1、红外线避障 2、超声波避障

红外避障原理

基本硬件 红外发射管和接收管:分离式和一体式 在这里插入图片描述 变送电路:模拟量;数字量:将模拟量经过比较器输出开关量

选择模块简介:

在这里插入图片描述 不怕光HJ-IR2传感器 • 1、HJ-IR2相当于一个红外电子开关,检测到障碍输出低电平,平 时高电平。。 • 2、前方有障碍物时,红外管发出的红外信号经红外接收管接收 回来后,经集成的芯片放大,比较后,输出一低电平,点亮模块 上的LED发光管,同时可以输出一个低平信号,信号可以作为单 片机的信号输入检测控制外部各种驱动模块之用。 • 3、模块三线制,VCC为电原+5V,OUT为信号输出端,GND接电源 负极。 • 4、探测距离大概为1~30CM(探测距离的长短和供电电压、电流还 有周围环境有关,这里只作为参考) • 5、工作电压5V 工作电流 18-30ma左右。

2路壁障模块的输出 :

在一般电子设计比赛等对壁障模块功能要求不高的场合,完全可 以采用比较器输出开关量,这样编程简单,易于实现; 1路壁障模块模块则输出1路开关量,可以接单片机的普通输入IO 口;

2路壁障模块原理 :

根据小车的运行情况有以下几种运动方式: 若没有被任何一个探头检测到,小车直行; 左边探头检测到物体时小车向右转 ; 右这探头检测到物体时小车向左转 •;上述算法描述是最简单的红外壁障算法,如果有一定的速度需求, 则在以上算法上进行改进。

壁障模块的安装调试步骤 :

将2路探头呈一行布置在智能车前方,探头朝前面, 可以采用铜柱+螺丝方式固定; 将中控板固定在车身上; 正确连接中控板和探头的杜邦线; 正确连接控制主板; 将小车放到地面上,前方10CM处放物体,调节电位器, 保证某探头在经过物体时,LED的状态不同。 若无论怎么调节电位器,LED状态都不变化,则应该 是杜邦线接触不好,要更换。

简单源码分析—IO口定义

在这里插入图片描述

简单源码分析—算法分析

在这里插入图片描述主程序:

#include "stm32f10x.h" #include "interface.h" #include "LCD1602.h" #include "IRCtrol.h" #include "motor.h" #include "UltrasonicCtrol.h" #include "redvoid.h" //全局变量定义 unsigned int speed_count=0;//占空比计数器 50次一周期 char front_left_speed_duty=SPEED_DUTY; char front_right_speed_duty=SPEED_DUTY; char behind_left_speed_duty=SPEED_DUTY; char behind_right_speed_duty=SPEED_DUTY; unsigned char tick_5ms = 0;//5ms计数器,作为主函数的基本周期 unsigned char tick_1ms = 0;//1ms计数器,作为电机的基本计数器 unsigned char tick_200ms = 0;//刷新显示 char ctrl_comm = COMM_STOP;//控制指令 char ctrl_comm_last = COMM_STOP;//上一次的指令 unsigned char continue_time=0; int main(void) { delay_init(); GPIOCLKInit(); UserLEDInit(); // LCD1602Init(); // IRCtrolInit(); TIM2_Init(); MotorInit(); //UltraSoundInit(); RedRayInit(); ServoInit(); while(1) { if(tick_5ms >= 5) { tick_5ms = 0; tick_200ms++; if(tick_200ms >= 40) { tick_200ms = 0; LEDToggle(LED_PIN); } VoidRun(); } } }

串口部分:

#include "uart.h" #include "interface.h" //UART function //UART1 TxD GPIOA9 RxD GPIOA10 void USART1Conf(u32 baudRate) { USART_InitTypeDef USART_InitSturct;//定义串口1的初始化结构体 GPIO_InitTypeDef GPIO_InitStruct;//定义串口对应管脚的结构体 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA , ENABLE);//打开串口管脚时钟 //USART1_Tx_Pin Configure GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;//输出引脚 GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;//设置最高速度50MHz GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//推挽复用输出 GPIO_Init(GPIOA , &GPIO_InitStruct);//将初始化好的结构体装入寄存器 //USART1_Rx_Pin Configure GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;//GPIO模式悬浮输入 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;//输入引脚 GPIO_Init(GPIOA, &GPIO_InitStruct);//将初始化好的结构体装入寄存器 //USART1 Configure RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 , ENABLE);//时钟使能 USART_InitSturct.USART_BaudRate = baudRate;//波特率19200 USART_InitSturct.USART_WordLength = USART_WordLength_8b;//数据宽度8位 USART_InitSturct.USART_StopBits = USART_StopBits_1;//一个停止位 USART_InitSturct.USART_Parity = USART_Parity_No;//无奇偶校验 USART_InitSturct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitSturct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//使能发送与接收 USART_Init(USART1 , &USART_InitSturct);//将初始化好的结构体装入寄存器 //USART1_INT Configure USART_ITConfig(USART1 , USART_IT_RXNE , ENABLE);//使能接收中断 // USART_ITConfig(USART1 , USART_IT_TXE , ENABLE); USART_Cmd(USART1 , ENABLE);//打开串口 USART_ClearFlag(USART1 , USART_FLAG_TC);//解决第一个数据发送失败的问题 } void PutChar(u8 Data) { USART_SendData(USART1 , Data); while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);//等待发送完毕 } void PutStr(char *str)//发送一个字符串 { while(*str != '\0') { USART_SendData(USART1 , *str++); while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);//等待发送完毕 } } void PutNChar(u8 *buf , u16 size) { u8 i; while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); //防止第一字节丢失 for(i=0;i GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = FRONT_LEFT_F_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(FRONT_LEFT_F_GPIO, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = FRONT_LEFT_B_PIN; GPIO_Init(FRONT_LEFT_B_GPIO, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = FRONT_RIGHT_F_PIN; GPIO_Init(FRONT_RIGHT_F_GPIO, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = FRONT_RIGHT_B_PIN; GPIO_Init(FRONT_RIGHT_B_GPIO, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = BEHIND_LEFT_F_PIN; GPIO_Init(BEHIND_LEFT_F_GPIO, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = BEHIND_LEFT_B_PIN; GPIO_Init(BEHIND_LEFT_B_GPIO, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = BEHIND_RIGHT_F_PIN; GPIO_Init(BEHIND_RIGHT_F_GPIO, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = BEHIND_RIGHT_B_PIN; GPIO_Init(BEHIND_RIGHT_B_GPIO, &GPIO_InitStructure); } //根据占空比驱动电机转动 void CarMove(void) { BEHIND_RIGHT_EN; /* //左前轮 if(front_left_speed_duty > 0)//向前 { if(speed_count < front_left_speed_duty) { FRONT_LEFT_GO; }else { FRONT_LEFT_STOP; } } else if(front_left_speed_duty < 0)//向后 { if(speed_count < (-1)*front_left_speed_duty) { FRONT_LEFT_BACK; }else { FRONT_LEFT_STOP; } } else //停止 { FRONT_LEFT_STOP; }*/ //右前轮 if(front_right_speed_duty > 0)//向前 { if(speed_count FRONT_RIGHT_STOP; } } else if(front_right_speed_duty FRONT_RIGHT_BACK; }else //停止 { FRONT_RIGHT_STOP; } } else //停止 { FRONT_RIGHT_STOP; } //左后轮 if(behind_left_speed_duty > 0)//向前 { if(speed_count BEHIND_LEFT_STOP; } } else if(behind_left_speed_duty BEHIND_LEFT_BACK; } else //停止 { BEHIND_LEFT_STOP; } } else //停止 { BEHIND_LEFT_STOP; } /* //右后轮 if(behind_right_speed_duty > 0)//向前 { if(speed_count < behind_right_speed_duty) { BEHIND_RIGHT_GO; } else //停止 { BEHIND_RIGHT_STOP; } } else if(behind_right_speed_duty < 0)//向后 { if(speed_count < (-1)*behind_right_speed_duty) { BEHIND_RIGHT_BACK; } else //停止 { BEHIND_RIGHT_STOP; } } else //停止 { BEHIND_RIGHT_STOP; }*/ } //向前 void CarGo(void) { front_left_speed_duty=SPEED_DUTY; front_right_speed_duty=SPEED_DUTY; behind_left_speed_duty=SPEED_DUTY; behind_right_speed_duty=SPEED_DUTY; } //后退 void CarBack(void) { front_left_speed_duty=-SPEED_DUTY; front_right_speed_duty=-SPEED_DUTY; behind_left_speed_duty=-SPEED_DUTY; behind_right_speed_duty=-SPEED_DUTY; } //向左 void CarLeft(void) { front_left_speed_duty=-20; front_right_speed_duty=SPEED_DUTY; behind_left_speed_duty=-20; behind_right_speed_duty=SPEED_DUTY+10;//增加后轮驱动力 } //向右 void CarRight(void) { front_left_speed_duty=SPEED_DUTY; front_right_speed_duty=-20; behind_left_speed_duty=SPEED_DUTY+10;//增加后轮驱动力 behind_right_speed_duty=-20; } //停止 void CarStop(void) { front_left_speed_duty=0; front_right_speed_duty=0; behind_left_speed_duty=0; behind_right_speed_duty=0; } void MotorInit(void) { MotorGPIO_Configuration(); CarStop(); }

红外遥控配置:

#include "IRCtrol.h" #include "interface.h" unsigned char ir_rec_flag=0;//接收数据标志位 1 有新数据 0 没有 unsigned char IRCOM[4]; //use time3 realize delay systick已经在main函数中使用了,在中断中不能重复使用 void Time3Init(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); TIM_TimeBaseStructure.TIM_Period = 1; TIM_TimeBaseStructure.TIM_Prescaler = (72 - 1);//72M / 72 = 1us TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Down; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); } //1us 延时 void DelayUs(vu32 nCount) { u16 TIMCounter = nCount; TIM_Cmd(TIM3, ENABLE); TIM_SetCounter(TIM3, TIMCounter); while (TIMCounter>1) { TIMCounter = TIM_GetCounter(TIM3); } TIM_Cmd(TIM3, DISABLE); } //外部中断配置 红外遥控配置 void IRCtrolInit(void) { GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure;//定义一个外部中断相关的结构体 NVIC_InitTypeDef NVIC_InitStructure; //定义一个中断的结构体 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO , ENABLE); GPIO_InitStructure.GPIO_Pin = IRIN_PIN;//配置使能GPIO管脚 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//配置GPIO模式,输入上拉 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//配置GPIO端口速度 GPIO_Init(IRIN_GPIO , &GPIO_InitStructure); GPIO_EXTILineConfig(IRIN_PORTSOURCE , IRIN_PINSOURCE); EXTI_InitStructure.EXTI_Line = IRIN_EXITLINE;//将对应的GPIO口连接到中断线上 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//中断事件类型,下降沿 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//选择模式,中断型 EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能该中断 EXTI_Init(&EXTI_InitStructure);//将配置好的参数写入寄存器 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); //阶级为0,不可嵌套 NVIC_InitStructure.NVIC_IRQChannel = IRIN_IRQCH;//打开PINA_8的外部中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//主优先级0,最高 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //子优先级,最低 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能该模块中断 NVIC_Init(&NVIC_InitStructure); //中断初始化,将结构体定义的数据执行 Time3Init(); } /******************************************************************************* * 函 数 名 :DelayIr * 函数功能 :0.14MS 延时 * 输 入 :无 * 输 出 :无 *******************************************************************************/ void DelayIr(unsigned char x) { while(x--) { DelayUs(140); } } void IRIntIsr(void) { unsigned char j,k,N=0; DelayIr(15); if (IRIN==1) { return; } continue_time = 40;//连发信号,表示指令持续 40*5 = 200ms 无指令停车 //确认IR信号出现 while (!IRIN) //等IR变为高电平,跳过9ms的前导低电平信号。 {DelayIr(1);} for (j=0;j while (IRIN) //等 IR 变为低电平,跳过4.5ms的前导高电平信号。 {DelayIr(1);} while (!IRIN) //等 IR 变为高电平 {DelayIr(1);} while (IRIN) //计算IR高电平时长 { DelayIr(1); N++; if (N>=30) { return;} //0.14ms计数过长自动离开。 } //高电平计数完毕 IRCOM[j]=IRCOM[j] >> 1; //数据最高位补“0” if (N>=8) {IRCOM[j] = IRCOM[j] | 0x80;} //数据最高位补“1” N=0; }//end for k }//end for j k = ~IRCOM[3]; if (IRCOM[2] != k) { return; } //指令转换 switch(IRCOM[2]) { case 0x46: ctrl_comm = COMM_UP;break; case 0x15: ctrl_comm = COMM_DOWN;break; case 0x44: ctrl_comm = COMM_LEFT;break; case 0x43: ctrl_comm = COMM_RIGHT;break; case 0x40: ctrl_comm = COMM_STOP;break; default : return; } ir_rec_flag = 1; }

红外避障模块:

#include "redvoid.h" #include "interface.h" #include "motor.h" extern char ctrl_comm; //获取红外避障模块状态 char GetVoidStatus(void) { char left=0,right=0; char count; if(VOID_L_IO == BARRIER_Y) { count = 2; while(--count)//10ms 采集2次均要采集到前面障碍物信息,滤波 { if(VOID_L_IO == BARRIER_N) break; Delayms(1); } if(count == 0) left = 1; } if(VOID_R_IO == BARRIER_Y) { count = 2; while(--count)//10ms 采集2次均要采集到前面障碍物信息,滤波 { if(VOID_R_IO == BARRIER_N) break; Delayms(1); } if(count == 0) right = 2; } return left + right; } //延时的同时检测红外,一旦发生障碍物,就停止并跳出延时 void DelayCheck(int ms) { while(ms--) { Delayms(1); if(VOID_NONE != GetVoidStatus()) { CarStop(); return; } } } //红外避障处理 //处理方式:左边检测到 后退500ms 右转500ms // 右边检测到 后退500ms 左转500ms // 两边检测到 后退700ms 右转500ms // 没检测到 直行 void VoidRun(void) { char status; status = GetVoidStatus(); switch(status) { case VOID_LEFT: ctrl_comm = COMM_RIGHT;CarBack(); Delayms(500); CarRight(); DelayCheck(500); break; case VOID_RIGHT: ctrl_comm = COMM_LEFT;CarBack(); Delayms(500); CarLeft(); DelayCheck(500); break; case VOID_BOTH: ctrl_comm = COMM_RIGHT;CarBack(); Delayms(700); CarRight(); DelayCheck(500); break; case VOID_NONE: ctrl_comm = COMM_UP;CarGo(); break; default: break; } }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3