实验11.实现小车自主避障
一、实验目的:通过小车自主避障实验,学习超声波测距相关知识,并实现小车的自主避障。
二.实验过程及分析:本实验首先需要通过阅读超声波模块的相关资料,掌握超声波测距的方法,然后学习如何使小车在蓝牙控制的同时也能实现避障功能。
学习要点:超声波测距知识点,小车自主避障
超声波测距知识点:
首先看看超声波模块长什么样子
接口定义:
Vcc、 Trig(控制端)、 Echo(接收端)、 Gnd
本产品使用方法:控制口发一个 10US 以上的高电平,就可以在接收口等待高电平输出.
一有输出就可以开定时器计时,当此口变为低电平时就可以读定时器的值,此时就为此次测
距的时间,方可算出距离.如此不断的周期测,就可以达到你移动测量的值了。
超声波模块测距原理:
应用注意事项:
1:此模块不宜带电连接,如果要带电连接,则先让模块的 Gnd 端先连接。否则会影响
模块工作。
2:测距时,被测物体的面积不少于 0.5 平方米且要尽量平整。否则会影响测试结果。
主要相关代码:
初始化函数 TIM2_Cap_Init,把 TIM2 的 CH4 初始化为输入捕获
/**************************************************************************
函数功能:定时器2通道4输入捕获
入口参数:入口参数:arr:自动重装值 psc:时钟预分频数
返回 值:无
**************************************************************************/
void TIM2_Cap_Init(u16 arr,u16 psc)
{
RCC->APB1ENR|=1<<0; //TIM2 时钟使能
RCC->APB2ENR|=1<<2; //使能PORTA时钟
GPIOA->CRL&=0XFFFF00FF;
GPIOA->CRL|=0X00008200;//Pa.2 推挽输出 Pa.3 输入
TIM2->ARR=arr; //设定计数器自动重装值
TIM2->PSC=psc; //预分频器
TIM2->CCMR2|=1<<8; //CC1S=01 选择输入端 IC1映射到TI1上
TIM2->CCMR2|=0<<12; //IC1F=0000 配置输入滤波器 不滤波
TIM2->CCMR2|=0<<10; //IC2PS=00 配置输入分频,不分频
TIM2->CCER|=0<<13; //CC1P=0 上升沿捕获
TIM2->CCER|=1<<12; //CC1E=1 允许捕获计数器的值到捕获寄存器中
TIM2->DIER|=1<<4; //允许捕获中断
TIM2->DIER|=1<<0; //允许更新中断
TIM2->CR1|=0x01; //使能定时器2
MY_NVIC_Init(1,3,TIM2_IRQn,1);
}
在 TIM2 的中断服务函数里面实现脉宽测量
/**************************************************************************
函数功能:超声波回波脉宽读取中断
入口参数:无
返回 值:无
作 者:平衡小车之家
**************************************************************************/
void TIM2_IRQHandler(void)
{
u16 tsr;
tsr=TIM2->SR;
if((TIM2CH4_CAPTURE_STA&0X80)==0)//还未成功捕获
{
if(tsr&0X01)//溢出
{
if(TIM2CH4_CAPTURE_STA&0X40)//已经捕获到高电平了
{
if((TIM2CH4_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
{
TIM2CH4_CAPTURE_STA|=0X80;//标记成功捕获了一次
TIM2CH4_CAPTURE_VAL=0XFFFF;
}else TIM2CH4_CAPTURE_STA++;
}
}
if(tsr&0x10)//捕获1发生捕获事件
{
if(TIM2CH4_CAPTURE_STA&0X40) //捕获到一个下降沿
{
TIM2CH4_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平脉宽
TIM2CH4_CAPTURE_VAL=TIM2->CCR4; //获取当前的捕获值.
TIM2->CCER&=~(1<<13); //CC1P=0 设置为上升沿捕获
}else //还未开始,第一次捕获上升沿
{
TIM2CH4_CAPTURE_STA=0; //清空
TIM2CH4_CAPTURE_VAL=0;
TIM2CH4_CAPTURE_STA|=0X40; //标记捕获到了上升沿
TIM2->CNT=0; //计数器清空
TIM2->CCER|=1<<13; //CC1P=1 设置为下降沿捕获
}
}
}
TIM2->SR=0;//清除中断标志位
}
调用 Read_Distane 函数实现对超声波模块的触发和对回波脉宽的测量
/**************************************************************************
函数功能:超声波接收回波函数
入口参数:无
返回 值:无
**************************************************************************/
u16 TIM2CH4_CAPTURE_STA,TIM2CH4_CAPTURE_VAL;
void Read_Distane(void)
{
PAout(2)=1; //Trig(控制端)产生一个10us以上的高电平
delay_us(15);
PAout(2)=0;
if(TIM2CH4_CAPTURE_STA&0X80)//成功捕获到了一次高电平
{
Distance=TIM2CH4_CAPTURE_STA&0X3F;
Distance*=65536; //溢出时间总和
Distance+=TIM2CH4_CAPTURE_VAL; //得到总的高电平时间
Distance=Distance*170/1000;
//printf("&d \r\n",Distance);
TIM2CH4_CAPTURE_STA=0; //开启下一次捕获
}
}
注意:单片机定时器的个数有限,TIM2 也是平衡小车左路编码器的接口。但是如果采集超声波的话,就不再采集这一路编码器。 然后改用 右路编码器近似算出左路编码器的值。
int Balance_Pwm,Velocity_Pwm,Turn_Pwm;
int TIM1_UP_IRQHandler(void)
{
if(TIM1->SR&0X0001)//5ms定时中断
{
TIM1->SR&=~(1<<0); //===清除定时器1中断标志位
Encoder_Right=Read_Encoder(4); //===读取编码器的值
#if MODE_BIZHANG==1
Encoder_Left=Encoder_Right; //===避障模式,左路编码器直接由右路编码器近似,并取消转向环中的编码器使用,只用Z轴陀螺仪
#else
Encoder_Left=-Read_Encoder(2); //===读取编码器的值,因为两个电机的旋转了180度的,所以对其中一个取反,保证输出极性一致
#endif
......
小车自主避障:在避障时候,蓝牙遥控依然可以使用,但是小车检测到前方 0.5 米有障碍会自动后退。
关键代码:
#if MODE_BIZHANG==1
if(Distance<500)
{
Movement+=700 ;
if(1==Flag_Qian)
Movement=700;
}
#endif
三.实验现象:小车能够自主避障,也就是通过蓝牙控制小车的运动,当超声波模块检测到小车前方 0.5 米处有障碍时会自动后退。
四.实验总结:通过本次实验学习了利用超声波测距的相关知识和注意事项,并学习了如何实现小车的自主避障,避免了蓝牙控制和超声波避障的冲突。