赞
踩
书接上文 https://blog.csdn.net/canoe1996/article/details/121979751?spm=1001.2014.3001.5501,前面博主做了一个可以使用蓝牙遥控的小车,这几天因为项目上的事空下来,就把剩余的模块加上去了,让小车稍微“智能”了一点,下面直入主题:
HC-SR04是市面上很常见的超声测距模块,4个口分别VCC接5V输入,GND,Trig触发口,Echo回响输入口
接下来看一下模块驱动图,首先使用MCU输出一个至少10us的信号至Trig口,模块内部会循环发出8个40Khz的脉冲,此后,Echo口会输出高电平,一直到输出的声波信号返回到模块,将Echo口接入MCU,用定时器记录输出回响信号,那么
距离 = 时间 * 声速(340m/s)/2
就可以计算出模块距离障碍物的距离,注意每次测量时间间隔200ms
按照前面驱动说明,下面是程序,这里直接定义了测距函数,使用TIM4为计时器,通过合适的分频和计数值,让定时器分辨率为1us,代码基本就是按照前面说的来写的,注释的也很清楚,这里我是取了5次平均来保证准确性,由于模块质量不太好,只能这样操作了。。。
float CS_front_distance(void) //前方测距 单位为cm { float length=0,sum=0; u16 tim; u8 i=0; while(i!=5) //取5次平均 { PCout(0)=1; delay_us(20); PCout(0)=0; //输出一个大于10us的高电平信号触发测距 while(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_1)==RESET); TIM_Cmd(TIM4,ENABLE); i+=1; while(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_1)==SET); TIM_Cmd(TIM4,DISABLE); //记录回响时间 tim=TIM_GetCounter(TIM4); length=(tim+overcount*1000)/58.0; //1/58.0 为0.017 cm/us 计算距离 sum=length+sum; TIM4->CNT=0; overcount=0; delay_ms(200); } length=sum/5; return length; }
这里就是实现一个检测前方有障碍物进行掉头的功能,下面是程序
//自动避障 length[0] = CS_front_distance();//将前方测距模块存放在0位置 delay_ms(100); if(length[0] > 50) //如果前方距离大于50cm,保持直行 { car_go_medium(); } if(length[0] < 50) //如果前方距离小于50cm,掉头 { car_stop(); delay_ms(100); car_back(); delay_ms(100); length[1] = CS_left_distance();//测左边距离 length[2] = CS_Right_distance();//测右边距离 if(length[1] > length[2] ) { //如果左边距离大于右边距离,且都大于50cm,则向右掉头 car_Left_circle(); delay_ms(300); } if(length[2] > length[1] ) { //否则向左掉头 car_Right_circle(); delay_ms(300); } }
这个模块就比较简单了,原理就是模块供电后不断发射红外光线,如果发射到黑色物体上,由于黑色吸收红外线,则模块接收不到反射回来的红外光,此时D0口输出高电平;如果发射到其他颜色的物体上,模块就会接收到反射回来的红外线,此时D0口输出低电平。
根据前面说的原理,驱动程序如下,首先是初始化PC6 和PC7为输入模式,然后通过GPIO_ReadInputDataBit()函数读取模块D0的状态
void trace_IO_init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);//使能GPIOC时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通输入模式 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉 GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化 GPIO_ResetBits(GPIOD,GPIO_Pin_6);//GPIOC0设置低 GPIO_ResetBits(GPIOD,GPIO_Pin_7);//GPIOC1设置低 } u16 Read_xunji_L_data(void) { L = GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_6); return L; }
由于我只买了2个TCRT5000,实际上是需要很多的模块放置在车头来进行探测,提高循迹的灵敏性;在车头左右各放置一个模块进行探测,程序如下,注释的很清楚:
//循迹 L1 = Read_xunji_L_data(); R1 = Read_xunji_R_data(); if(L1 == 1 && R1 ==1 ) // 如果左右检测到高电平,则说明左右都在黑线上,保持直行即可 { car_go_medium(); delay_ms(100); } if(L1 == 1 && R1 ==0 ) // 如果左高右低,则说明右边不在黑线上,应该向左行驶 { car_left(); delay_ms(100); } if(L1 == 0 && R1 ==1 ) // 如果左低右高,则说明左边不在黑线上,应该向右行驶 { car_right(); delay_ms(100); } if(L1 == 0 && R1 ==0 ) // 如果都不在黑线上,则停止 { car_stop(); delay_ms(100); }
总结一下
现在算是基本完成了智能小车,但基本功能都有,蓝牙遥控,智能避障,循迹,算是告一段落了;
如果后面要参加比赛的话,优化方向,硬件上就是画块PCB,做一个STM32F4的最小系统,将模块全部集成在板上,尝试加入摄像头,做图像识别(这个可能要用FPGA来做,比较难的了);程序上的话,就是不断调试优化,加入PID算法,让小车行驶的更舒适,要做好的话也需要很多时间;
这是我学习STM32F4大半年以来完成的一个项目,在此对C站上大佬们写的博客表示感谢,学习过程中在C站找到很多答案,自己以后也会多更博客,总结分享自己的嵌入式学习道路,大家有什么问题和意见都可以在评论区留言,共同学习,一起进步~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。