智能避障小车_基于单片机的智能玩具车系统设计

2022-11-19 16:05:30 浏览数 (2)

大家好,又见面了,我是你们的朋友全栈君。

【1】背景意义

近些年随着国民生活水平的提升,以小车为载体的轮式机器人进入了我们的生活,尤其是在一些布线复杂困难的安全生活区和需要监控的施工作业场合都必须依赖轮式机器人的视频监控技术。因此,基于嵌入式技术的无线通信视频监控轮式机器人应运而生。由于它们与人类工作相比具有成本低廉、安全稳定的优点,目前已经在许多危险作业以及工业场合得到了广泛应用而且轮式机器人不需要像人那样采取过多的保护措施,因此轮式机器人更适合在危险困难的工作环境中工作。然而轮式机器人在行驶中所能碰到的障碍很多,例如前部凸出物的碰触,后部凸出物的拖托,中部凸出物的顶举,特别还有垂直障碍和壕沟等,所以必须对轮式机器人的越障问题进行研究来解决类似问题。

针对复杂地形环境的巡检作业,设计一种基于wifi视频监控的智能小车。基于STM32F103主控板搭建智能小车的控制系统,并采用模块化的设计思想编写控制系统程序,为能够在复杂地形下进行巡检作业的轮式机器人研究提供理论依据。

【2】总设计方案

本课题利用STM32作为智能小车的主控制器来驱动智能小车的直流电机工作,电机驱动芯片采用L298N微型集成电路电机驱动芯片,配合STM32核心板使用实现四个直流电机运行和pwm软件调速,通过改变直流电机占空比的电压来改变平均电压的数值,从而改变电机的转速变化来驱动轮式机器人运行。轮式机器人行驶的状态有:前进、后退、左转、右转和停止。当轮式机器人在行驶过程中遇到障碍物,红外避障检测模块检测周围障碍物,轮式机器人自动停止或转向。通过WIFI无线信号作为传输媒介,以上位机或手机作为控制端来控制机器人的运动以及将摄像头所拍摄的视频信息在控制端界面中显示,这样便可观察轮式机器人周围的环境并对机器人进行实时监控。主要设计步骤有:

(1)根据提出方案的功能需求对智能小车进行结构设计。 (2)根据主控制器的基本结构和特点,设计总体硬件电路模块。总体硬件电路模块的设计包括电机驱动电路设计、红外避障电路设计、无线传输电路设计等。 (3)选择符合系统设计需求的系统软件,并在该软件的基础上编写驱动代码和应用软件代码。针对系统功能的具体要求,从系统信号稳定传输的角度出发,对电机驱动、调速、无线路由器系统的改造、视频信息的接受与发送、红外避障模块的改造和控制端界面的设计等进行详细的分析与设计,并完成代码的编写与调试。 (4)把硬件开发板和软件平台结合起来,对视频监控智能小车整个系统进行了整体测试。对测试中出现的问题进行相关的改进工作,进一步提高系统工作的可靠性和稳定性。

【3】结构设计

根据提出方案的功能需求,对轮式机器人的整体结构进行设计,采用双面覆铜加硬的PCB板料作为轮式机器人的底盘,其优点是:不易变形、不易折断、轻量化、不易造成短路;选用抗干扰TT马达,其加入压敏抗组的转子可抵抗电机突然启动产生的火花干扰,避免触发信号错误,可有效降低马达启动噪音,并在启动时可提供更大电流,使马力更强;使用航模级抗滑橡胶轮胎内带海绵表面平整不易变形,在避障行走时刹车不易撞上障碍物。马达用马达锁片固定到机器人底盘上,轮子通过轴与马达相连。

其余硬件设备均固定到机器人底盘上,包括电池座、红外避障传感器、wifi模块、摄像头、STM32单片机主控模块和L298N电机驱动芯片。机器人底盘俯视图示意图如图:

【4】系统硬件设计

硬件系统主要由单片机主控模块、电源模块、电机驱动模块、红外避障模块控制终端模块和无线视频监控模块组成。硬件系统框图如图:

(1)主控模块 主控模块采用STM32F103为主控制器,STM32F103属于中低端的32位ARM微控制器,该系列芯片是意法半导体(ST)公司出品,其内核是Cortex-M3。该系列芯片按片内Flash的大小可分为三大类:小容量(16K和32K)、中容量(64K和128K)、大容量(256K、384K和512K)。芯片集成定时器,CAN,ADC,SPI,I2C,USB,UART,等多种功能。STM32F103可使用keil C语言编译,支持STLink-SWD在线调试,主要用于收集信息、处理数据、协调系统中的每个功能模块预计要完成的任务。

(2)电源模块 电源模块在机器人的运行过程中,需要给单片机、电机、各大模块及传感器供电。为了保证系统的可靠供电,所以选择可充电的18650锂电池,如图3.5所示。**18650是锂离子电池的鼻祖–日本SONY公司当年为了节省成本而定下的一种标准性的锂离子电池型号,其中18表示直径为18mm,65表示长度为65mm,0表示为圆柱形电池。**常见的18650电池分为锂离子电池、磷酸铁锂电池。锂离子电池电压为标称电压为3.7v,充电截止电压为4.2v,磷酸铁锂电池标称电压为3.2V,充电截止电压为3.6v容量通常为1200mAh-3350mAh,常见容量是2200mAh-2600mAh。

(3)电机驱动模块 电机驱动模块采用L298N为电机驱动芯片,其原理图如图3.6所示。L298N是ST公司生产的一种高电压、大电流电机驱动芯片。该芯片采用15脚封装。主要特点是:工作电压高,最高工作电压可达46V;输出电流大,瞬间峰值电流可达3A,持续工作电流为2A;额定功率25W。内含两个H桥高电压大电流全桥式驱动器,可以用来驱动直流电动机和步进电动机、继电器线圈等感性负载;采用标准逻辑电平信号控制;具有两个使能控制端,在不受输入信号影响的情况下允许或禁止器件工作有一个逻辑电源输入端,使内部逻辑电路部分在低电压下工作;可以外接检测电阻, 将变化量反馈给控制电路。使用L298N芯片驱动电机,该芯片可以驱动一台两相步进电机或四相步进电机,也可以驱动两台直流电机,并联时可以驱动四台电机。此次研究将L298N配合STM32核心板无缝对插使用,实现无损扩展并对四个马达进行驱动和PWM调速。

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

(5)控制终端模块 控制终端模块有PC上位机和安卓手机两种,两种控制界面都能实现对于智能小车的各种运动状态的控制。

(6)无线视频监控模块 本模块采用720p高清USB摄像头,可以对轮式机器人的运动状态以及周围环境进行视频采集,然后将采集的视频数据通过无线信号返回到控制界面显示,以达到实时监控的目的。**USB接口是目前应用比较广泛的一种接口模式,几乎所有的产品都能支持,即插即用,具有强大的扩充能力,用起来十分方便。**依靠USB连接无线路由器获得的电压就能否满足摄像头正常工作需求的电压,这样就不用再接外部电压,使得电路设计更加简单方便。USB摄像头虽然在采集动态画面与成像清晰度上仍然无法与接口摄像头相比,但是其接口简单,即插即用,己经成为设计者的首选。本模块主要是用来完成轮式机器人与各个控制界面之间的通信,由于机器人移动性的特点,所以系统选用无线通信进行数据传输。无线通信的实现主要由无线路由器实现,通过无线路由器可以搭建一个局域网,并且在这局域网的基础上可以运行多种底层协议。控制终端与轮式机器人进行信号的控制和交互就是采用这种传输模式。首先运行于控制终端的网络程序通过局域网与轮式机器人建立起连接,待连接建立成功后,用户就可以使用控制终端的用户界面软件向轮式机器人发送各种控制指令和获取摄像头视频信息等数据。本系统设计将数字摄像头的驱动加载在无线路由器固件当中,当主控制器发出采集视频指令,摄像头开始工作。

【5】系统软件设计

软件的设计包括:主程序的设计、电机驱动程序设计、红外循障程序设计、视频采集程序设计、无线数据传输程序设计

(1)电机驱动程序 电机的驱动主要是对L298N驱动芯片的操作,运用PWM调速方法完成对电机进行驱动控制。脉冲宽度调制(PWM),简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。PWM波的产生可以通过时钟频率、自动重装值等参数进行设置,从而调节PWM波的占空比和输出频率,即对脉冲宽度的控制,PWM原理如图:

由图我们先假定定时器工作正处于向上计数PWM模式,且当CNT小于CCRx 时,输出0,当CNT大于等于CCRx 时输出 1。那么就可以得到如上的PWM示意图:当CNT值小于CCRx的时候,IO输出低电平(0),当CNT值大于等于CCRx的时候,IO输出高电平(1),当CNT达到ARR值的时候,重新归零,然后重新向上计数,依次循环改变CCRx的值,就可以改变PWM输出的占空比,改变ARR的值,就可以改变PWM输出的频率,这就是PWM输出的原理。由此可知PWM 技术就是把直流电压斩成一系列脉冲,通过改变脉冲的占空比获得所需的输出电压。

由图L298N芯片的原理图,引脚A,B可用于输入PWM脉宽调制信号对电机进行调速控制。如果无须调速可将两引脚接5V,使电机工作在最高速状态,既将短接帽短接。假设驱动的两台直流电机分别为M1和M2,当输入信号端IN1接高电平输入端IN2接低电平时,电机M1正转。当信号端IN1接低电平,IN2接高电平,电机M1反转。控制另一台电机是同样的方式,输入信号端IN3接高电平,输入端IN4接低电平,电机M2正转(反之则反转)。PWM信号端A控制M1调速,PWM信号端B控制M2调速 。可通过单片机IO口状态来控制小车运行,电机具体运行方式如图

电机驱动程序使用了单片机定时器的PWM功能,通过输出频率及占空比可变的PWM波来驱动电机。具体实现方法为:首先,使能定时器和相关IO口时钟。其次,对定时器进行初始化并设置其自动重转载值和预分频值,将计数模式设置为向上计数模式。最后,再使能预装载寄存器,使能定时器,通过改变比较值CCRX,达到不同的占空比效果。智能小车电机驱动程序流程图如图所示(以M1为例):

电机驱动部分代码

代码语言:javascript复制
/*电机宏定义*/
#define left1on GPIO_SetBits(GPIOD,GPIO_Pin_6)
#define left1off GPIO_ResetBits(GPIOD,GPIO_Pin_6)
#define left2on GPIO_SetBits(GPIOG,GPIO_Pin_9)
#define left2off GPIO_ResetBits(GPIOG,GPIO_Pin_9)
#define right1on GPIO_SetBits(GPIOC,GPIO_Pin_11)
#define right1off GPIO_ResetBits(GPIOC,GPIO_Pin_11)
#define right2on GPIO_SetBits(GPIOD,GPIO_Pin_0)
#define right2off GPIO_ResetBits(GPIOD,GPIO_Pin_0)
extern volatile u32 time;
u8 start=0;
u16 time1,time2;
volatile u8 motor0_angel=90,motor1_angel=90,motor2_angel=90,motor3_angel=90,motor4_angel=90,motor5_angel=90;
void TIM2_IRQHandler(void)
{
if ( TIM_GetITStatus(TIM2 , TIM_IT_Update) != RESET ) 
{	
TIM_ClearITPendingBit(TIM2 , TIM_FLAG_Update);  
time1  ;
time2  ;
if(time1==50)
{  
time1=0;
time  ;
if(time>9)
time=0;
if(ina1>time)
left1on;
else 	
left1off;
if(ina2>time)
left2on;
else 	
left2off;
if(inb1>time)
right1on;
else 	
right1off;
if(inb2>time)
right2on;
else 	
right2off;
}
if(time2>1818)
time2=0;
if(time2<motor0)
motor0on;
else
motor0off;
if(time2<motor1)
motor1on;
else
motor1off;
if(time2<motor2)
motor2on;
else
motor2off;
if(time2<motor3)
motor3on;
else
motor3off;
if(time2<motor4)
motor4on;
else
motor4off;
if(time2<motor5)
motor5on;
else
motor5off;
}		 	
}
void USART3_IRQHandler(void)
{
unsigned char rec_data;
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
{
USART_ClearITPendingBit(USART3, USART_IT_RXNE);
/* Read one byte from the receive data register */
rec_data = USART_ReceiveData(USART3);
if(start!=0&&rec_data!=0xff)						//如果已收到包头并且当前收到的不是包尾
{
buf[start-1]=rec_data;							//缓存数据
start  ;
}
else if(start!=0&&rec_data==0xff)					//如果收到包尾
{
mode[0]=buf[0];									//给状态存储数组赋值
mode[1]=buf[1];
mode[2]=buf[2];
start=0;
mode1=1;										//指示主函数循环检测一次
}
else if(rec_data==0xff&&start==0)					//如果收到的是包头
start  ;	
}
}
void dianji(u8 i)
{
switch(i)
{
case 1:					   //前进
speed_right=4;
speed_left=4;
break;
case 2:					   //后退
speed_right=-4;
speed_left=-4;
break;
case 3:					   //左转
speed_right=-2;
speed_left=4;
break;
case 4:					   //右转
speed_right=4;
speed_left=-2;
break;
case 0:					   //停止
speed_right=0;
speed_left=0;
break;
case 5:					   //左前
speed_right=2;
speed_left=5;
break;
case 6:					   //右前
speed_right=5;
speed_left=1;
break;
case 7:					   //左后
speed_right=-2;
speed_left=-5;
break;
case 8:					   //右后
speed_right=-5;
speed_left=-2;
break;
}
}

舵机程序:

代码语言:javascript复制
/*舵机宏定义*/
#define motor0on GPIO_SetBits(GPIOA,GPIO_Pin_0)
#define motor0off GPIO_ResetBits(GPIOA,GPIO_Pin_0)
#define motor1on GPIO_SetBits(GPIOA,GPIO_Pin_1)
#define motor1off GPIO_ResetBits(GPIOA,GPIO_Pin_1)
#define motor2on GPIO_SetBits(GPIOA,GPIO_Pin_2)
#define motor2off GPIO_ResetBits(GPIOA,GPIO_Pin_2)
#define motor3on GPIO_SetBits(GPIOF,GPIO_Pin_8)
#define motor3off GPIO_ResetBits(GPIOF,GPIO_Pin_8)
#define motor4on GPIO_SetBits(GPIOF,GPIO_Pin_9)
#define motor4off GPIO_ResetBits(GPIOF,GPIO_Pin_9)
#define motor5on GPIO_SetBits(GPIOF,GPIO_Pin_10)
#define motor5off GPIO_ResetBits(GPIOF,GPIO_Pin_10)
void duoji(u8 i)
{
if(mode[2]>180)
mode[2]=180;
switch(i)
{
case 1:					   
motor0_angel=mode[2];				  //取角度
break;
case 2:					   
motor1_angel=mode[2];		
break;
case 3:					
motor2_angel=mode[2];		   
break;
case 4:					   
motor3_angel=mode[2];		
break;
case 5:					   
motor4_angel=mode[2];		
break;
case 6:					   
motor5_angel=mode[2];		
break;
}
}

中断部分:

代码语言:javascript复制
void USART3Conf(u32 baudRate)
{
NVIC_InitTypeDef 	NVIC_InitStruct;//定义一个设置中断的结构体	
USART_InitTypeDef USART_InitSturct;//定义串口1的初始化结构体
GPIO_InitTypeDef GPIO_InitStruct;//定义串口对应管脚的结构体
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3 , ENABLE);//打开串口管脚时钟
//USART3_Tx_Pin Configure 
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;//输出引脚
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;//设置最高速度50MHz
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//推挽复用输出
GPIO_Init(GPIOB , &GPIO_InitStruct);//将初始化好的结构体装入寄存器
//USART3_Rx_Pin Configure
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;//GPIO模式悬浮输入
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11;//输入引脚
GPIO_Init(GPIOB, &GPIO_InitStruct);//将初始化好的结构体装入寄存器
//USART3 Configure	
USART_InitSturct.USART_BaudRate = baudRate;//波特率9600
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(USART3 , &USART_InitSturct);//将初始化好的结构体装入寄存器	
//USART1_INT Configure
USART_ITConfig(USART3 , USART_IT_RXNE , ENABLE);//使能接收中断
//	USART_ITConfig(USART3 , USART_IT_TXE , ENABLE);
USART_Cmd(USART3 , ENABLE);//打开串口
USART_ClearFlag(USART3 , USART_FLAG_TC);//解决第一个数据发送失败的问题
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStruct.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//打开该中断
NVIC_Init(&NVIC_InitStruct);
}

(2)红外避障控制程序 红外避障模块选用的红外避障传感器由发射管与接收管组成的,发射管发射红外线,当检测到障碍物时,接收管接受到红外线反射信号,经过比较器后,输出一个低电平信号送给单片机利用物体的反射性质,在一定范围内,如果没有障碍物,发射出去的红外线,因为传播距离越远而逐渐减弱,最后消失;如果有障碍物,红外线遇到障碍物,被反射到达传感器接收头,传感器检测到这一信号,就可以确认正前方有障碍物,并送给单片机,单片机进行一系列的处理分析,协调小车两轮工作,完成一个躲避障碍物动作。红外避障的控制程序的基本原理为首先检测是否有障碍物。当检测到有障碍物时,判断是做左边的传感器检测都到的还是右边的传感器检测到的,若是左边,则小车需先后退,然后右转。如过是右边的传感器检测到的,则小车应该先后退再左转。其算法流程图如图所示:

代码语言:javascript复制
//GPIOÅäÖú¯Êý
void MotorGPIO_Configuration(void)
{		
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_speed_duty)
{
FRONT_RIGHT_GO;
}else                //Í£Ö¹
{
FRONT_RIGHT_STOP;
}
}
else if(front_right_speed_duty < 0)//Ïòºó
{
if(speed_count < (-1)*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_speed_duty)
{
BEHIND_LEFT_GO;
}	else                //Í£Ö¹
{
BEHIND_LEFT_STOP;
}
}
else if(behind_left_speed_duty < 0)//Ïòºó
{
if(speed_count < (-1)*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();
}

(3)无线视频采集程序 摄像头的工作原理其实就是将光学信号转换电信号的过程,通过图像传感器将物镜转换为电信号,然后再经过A/D转换成数字图像信号,最后将数字图像信号发送给摄像头内部DSP(数字信号处理)处理芯片进程处理。本系统设计将数字摄像头的驱动加载在无线路由器固件当中,当主控制器发出采集视频指令,摄像头开始工作,并将釆集回来的视频信息通过TCP协议利用WIFI无线路由器连接的信号发送到显示界面显示出来无线视频采集程序流程图如图所示:

(4)主程序 系统主程序主要完成子程序调用和各种初始化操作,首先系统上电后,启动初始化程序,判断有无避障中断发送,发生避障中断时,执行避障子程序。执行完子程序后,发送电机控制信号。主程序流程图如图:

代码语言:javascript复制
int main(void)
{
/* 配置系统时钟为 72M */  
SystemInit();	
/* led 端口配置 */ 
ALL_GPIO_Config();	
/*usart3 串口配置 */
USART3Conf(9600);
TIM2_NVIC_Configuration();
//NVIC_Configuration();
TIM2_Configuration();	
/* TIM2 开始计时 */
START_TIME;	
while(1)
{
if(mode1==1)						//每次收到指令执行一次
{
mode1=0;
if(mode[0]==0)					//判断操作对象
dianji(mode[1]);
else if(mode[0]==1)
duoji(mode[1]);
else if(mode[0]>=2&&mode[0]<=4)
other(mode[0]);
}
}
}
/*************************************************************************************
协议规定:
包头   类型位  数据位   数据位    结束位
0XFF   0X**     OX**    0X**      0XFF
各命令说明:
类型位    数据位   数据位    功能
0X00       0X01      0X00    前进
0X00       0X02      0X00    后退
0X00       0X03      0X00    左转
0X00       0X04      0X00    右转
0X00       0X00      0X00    停止
0X00       0X05      0X00    左前
0X00       0X06      0X00    右前
0X00       0X07      0X00    左后
0X00       0X08      0X00    右后
0X01       0X01      角度    舵机1
0X01       0X02       .      舵机2
0X01       0X03       .      舵机3
0X01       0X04       .      舵机4
0X01       0X05       .      舵机5
0X01       0X06       .      舵机6
0X02       0X00      0X00    车灯亮
0X02       0X01      0X00    车灯灭
0X03       0X00      0X00    喇叭开
0X03       0X01      0X00    喇叭关
0X04       0X00      0X00   自定义开
0X04       0X01      0X00   自定义关
*****************************************************/

【6】实现效果

运用STM32F103 单片机为控制器,采用 C 语言在Keil 软件进行编程,来控制小车则完成前进、后退、左拐、右拐等动作。实现由红外传感器来检测信号,将检测到的信号送到单片机,由单片机处理后控制小车的行驶状态。实现由视频监控模块对轮式机器人的运动状态以及周围环境进行视频采集,然后将采集的视频数据通过无线信号返回到控制界面显示,以达到实时监控的目的。实现由无线路由模块来完成智能小车与各个控制界面之间的通信。最终实现了一个集视频监控、自动避障、wifi控制等功能于一体的智能小车控制系统系统。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/180627.html原文链接:https://javaforall.cn

0 人点赞