赞
踩
如果你是XD的,哈哈哈哈哈,代码直接可用,把线连接好就行啦!~~~~如果没啥变化的话!!!~~~四轮和自由轮很像,稍加修改就可以完成,相信大家可以的
代码链接: 循迹避障小车进阶版代码 || https://download.csdn.net/download/VCA821/13203358
写在最前:最近由于需要制作了一个循迹避障小车,制作比较简单但是还是出现了很多bug,因此在博客中记录一下,希望对后期需要制作的能有所帮助,小车由PWM信号+L293D驱动。(二轮驱动,第三轮为自由轮)
要求:小车要求循迹避障,有两种避障策略,在循迹黑线上遇到障碍物停车,循迹黑线外遇到障碍物要避障(左转,右转,后退均可),循迹过程中要求不能出黑线之外。
循迹原理:(红外探头+信号处理板)
我们在车头前加有3个红外探头板,分别在左中右三个位置,循迹原理很简单代码也十分容易理解好写,红外探头在光滑地板上会收到发射出去后反射的红外信号,如果探头在黑线上,则无法收到(黑线吸收红外光),当探头收到时,对应的信号调整板对应位置的led会亮,同时TTL输出端会给一个低电平,相反当某个探头在黑线上,对应位置led会灭,TTL输出端会给一个高电平,因此通过这种方式我们就知道任意一个探头是否在线上。
因此我们举个例子,两边灯亮,中间灯灭,说明小车前端中间探头在线上,这时候是正向,因此我们在代码中要求小车直行,若左灯灭,中间灯和右灯都亮,说明左探头在线上,小车现在是斜向右方,因此我们需要小车左转来实现方向回正,下面配个图来说明例子(途中只有左右两个探头,但不影响理解)
若仅仅实现循迹,代码要求就十分简单了(这里我们不再说小车前进等代码,只说明策略)
当左灯灭,TTL给1,车身右斜,循环左转至中间灯灭两边灯亮(即正向)后直行,否则就一直摆正,右向同样如此。
- /***LED_1,LED_2,LED_3分别对应左中右三个红外探头***/
-
-
- if(LED_1==1&&LED_3==0) //左方黑线亮,左转直到正向
- {
- while(1)
- {
- CarLeft();
- if(LED_1==0&&LED_3==0&&LED_2==1)
- break;
- }
- }
-
-
- else if(LED_1==0&&LED_3==1) 右方黑线亮,右转直到正向
- {
- while(1)
- {
- CarRight();
- if(LED_1==0&&LED_3==0&&LED_2==1)
- break;
- }
- }
-
- else CarGo();
避障原理:(超声波探头)
驱动代码是我直接从网上复制,借鉴的代码,在此附上链接,讲解非常详细,感谢作者。
但是笔者在使用驱动中也遇到了只收到一个非常小的数,即使已经按照上面链接中的要求更正,但还是收到一个非常小的数字,对此笔者对其测距代码进行了小小改动,对定时器测距进行小延时,去除小值数据,请对比上述链接中代码~在中间加了一个Delay_Us(10);问题解决。其实笔者试过,Delay_Us(1);同样可以解决问题。
- float Hcsr04GetLength(void )
-
- {
-
- u32 t = 0;
-
- int i = 0;
-
- float lengthTemp = 0;
-
- float sum = 0;
-
- while(i!=5)
-
- {
-
- //TRIG_Send = 1; //发送口高电平输出
- GPIO_SetBits(GPIOA, GPIO_Pin_5); // Alias
-
- Delay_Us(15);
-
- //TRIG_Send = 0;
- GPIO_ResetBits(GPIOA, GPIO_Pin_5); // Alias
-
- //while(ECHO_Reci == 0); //等待接收口高电平输出
- while(0 == GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6))
- OpenTimerForHc(); //打开定时器
-
- i = i + 1;
-
- //while(ECHO_Reci == 1);
- while(1 == GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6))
-
-
-
- Delay_Us(10); //延时,去除小数值
-
-
-
-
- CloseTimerForHc(); //关闭定时器
-
- t = GetEchoTimer(); //获取时间,分辨率为1US
-
- lengthTemp = ((float)t/58.0);//cm
-
- sum = lengthTemp + sum ;
-
-
-
- }
-
- lengthTemp = sum/5.0;
-
- return lengthTemp;
-
- }
在测距驱动和循迹策略都有的情况下,笔者将代码合二为一,实现要求功能(以下为while函数中代码)
- if(LED_1==0&&LED_3==0&&LED_2==0)
- {
- length = Hcsr04GetLength();
- if(length<=20.00)
- {
- while(1)
- {
-
- for(cnt1=0;cnt1 <= 60;cnt1++)
- for(cnt=0;cnt <= 8000;cnt++)
- CarBack();
-
- for(cnt1=0;cnt1 <= 60;cnt1++)
- for(cnt=0;cnt <= 8000;cnt++)
- CarRight();
-
- length = Hcsr04GetLength();
- if(length>=40.00)
- break;
- }
- }
- else CarGo();
- }
- else
- {
- length = Hcsr04GetLength();
- if(length<=20.00)
- CarStop();
- else
- {
-
- /***********路径判断***********/
-
- if(LED_1==1&&LED_3==0) //左方黑线亮,左转直到正向
- {
- while(1)
- {
- length = Hcsr04GetLength();//这个判断很重要,否则转弯过程中
- if(length<=20.00) //会被判断为线外,会后退右转
- CarStop();
- else CarLeft();
- if(LED_1==0&&LED_3==0&&LED_2==1)
- break;
- }
- }
- else if(LED_1==0&&LED_3==1) 右方黑线亮,右转直到正向
- {
- while(1)
- {
- length = Hcsr04GetLength();
- if(length<=20.00)
- CarStop();
- else CarRight();
- if(LED_1==0&&LED_3==0&&LED_2==1)
- break;
- }
- }
- else CarGo(); //其实这里并不严谨,笔者后期有改动。
-
- }
- }
- }
以上代码和驱动没有问题,但是有个很严重的问题就是
原因是该代码中测距是由定时器计数,在此cpu参与计数,单片机是单核运行,因此大概一半以上时间都带等数据返回,如果速度太快小车在循迹中灯闪时却在等待数据,则直接冲出线外,解决方案(定时器捕获测距),CPU不参与计数,大大提高了检测速率。
有问题欢迎留言~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。