用光敏电阻进行导航2文档格式.docx
《用光敏电阻进行导航2文档格式.docx》由会员分享,可在线阅读,更多相关《用光敏电阻进行导航2文档格式.docx(19页珍藏版)》请在冰豆网上搜索。
TestBothPhotoresistors.c
输入、保存并运行程序TestBothPhotoresistors.c。
将宝贝车机器人放置在跟随手电筒光源行走的表面上,确保机器人和串口电缆连接可靠,并且测量结果显示在调试终端里。
在表7-1第一行里记录测量的时间值。
打开手电筒,将光束聚焦在机器人前方。
此时测量的时间值应该明显的低于第一次设置的值。
在表6-1第二行里记录测量的时间值。
表7-1有无手电筒光束的时间测量值
右侧测量值
左侧测量值
描述
没有手电筒光源的时间测量值(环境光)
机器人正前方有手电筒光源束的时间测量值
#include<
BoeBot.h>
uart.h>
intmain(void)
{
unsignedintcount;
//机器人正前方有手电筒光源的时间测量值
unsignedinttimeLeft,timeRight;
uart_Init();
while
(1)
{
TH0=TL0=0;
TMOD=TMOD|0x01;
P1_5=0;
delay_nms(300);
P1_5=1;
TR0=1;
while((P1&
0x20)==0);
count=TH0;
count=count<
<
8;
count=count+TL0;
timeLeft=count;
TR0=0//把定时器关掉
P2_3=0;
P2_3=1;
while((P2&
0x08)==0);
timeRight=count;
printf("
L%dus\n"
timeLeft);
R%dus\n"
timeRight);
delay_nms(50);
}
}
试着让机器人面朝不同的方向,重复上述的测量。
要取得更好的结果,你可以将有无手电筒光束所测得的结果取平均值,替代表7-1的结果。
3)跟随手电筒光束
如果你计划在程序中使用一个常数,你可以给它一个有用的名字。
用define来定义常量,
这是下面例程中的要用到的一些常量:
#defineLeftAmbient944
#defineRightAmbient950
#defineLeftBright923
#defineRightBright923
现在,程序在任何地方使用LeftAmbient,微控制器将会使用944代替,使用RightAmbient,微控制器就会使用950,同样的,无论LeftBright出现在程序的任何地方,它的实际值是923,RightBright的实际值是923。
在实际运行程序之前,你必须用表7-1测得的值代替上述值。
常量也可被用来计算其它的常量。
这里是有关两个常量的例子,它们是LeftThreshold和RightThreshold,是由刚才所说的四个常量计算而来的。
LeftThreshold和RightThreshold在程序中用来计算出手电筒光束是否被探测到。
#defineLeftThreshold(LeftBright+LeftAmbient)/2
#defineRightThreshold(RightBright+RightAmbient)/2
这些常量所进行的数学计算是首先取平均值,然后乘一个比例因子。
LeftThreshold的值是(LeftBright+LeftAmbient)/2。
意思是,LeftThreshold是一个常量,它的值是LeftBright和LeftAmbient的平均值,当然并不是说一定要是除以2,还可以根据实际取其它的常数,比如2.006等等,来补偿环境因数。
FlashlightControlledBoeBot.c
输入程序FlashlightControlledBoeBot.c.
用表7-1没有手电筒光束的timeLeft测量值代替#defineLeftAmbient944中的944。
用没有手电筒光束的timeRight测量值代替#defineRightAmbient950中的
950。
用有手电筒光束的timeLeft测量值代替#defineLeftBright923中的923。
用有手电筒光束的timeRight测量值代替#defineRightBright923中的923。
打开主板和伺服电机的电源。
保存然后运行程序FlashlightControlledBoeBot.c。
试验并计算将光束聚集在哪里可以使机器人向前走,左转,右转。
用光束引导机器人穿过不同的障碍物。
#defineLeftAmbient42000
#defineRightAmbient42000
#defineLeftBright37020
#defineRightBright37020
#defineAmbientCL10//环境补偿因子,越大对光的敏感度越强
#defineAmbientCR10
#defineLeftThreshold(LeftAmbient+LeftBright)/2+AmbientCL
#defineRightThreshold(RightAmbient+RightBright)/2+AmbientCR
unsignedinttimeLeft,timeRight;
unsignedintcount;
voidTest_Photoresistors(void)
{
delay_nms
(1);
voidNavigate(void)
if((timeLeft<
LeftThreshold)&
&
(timeRight<
RightThreshold))
{
P1_1=1;
delay_nus(1700);
P1_1=0;
P1_0=1;
delay_nus(1300);
P1_0=0;
elseif(timeLeft<
LeftThreshold)
delay_nus(1400);
elseif(timeRight<
RightThreshold)
delay_nus(1600);
else
delay_nus(1500);
delay_nms(20);
ProgramRunning!
"
);
for(count=1;
count<
=1000;
count++)//开始/复位信号
P1_4=1;
delay_nus(1000);
P1_4=0;
while
(1)
Test_Photoresistors();
/*printf("
*/
Navigate();
Tip:
程序FlashlightControlledBoeBot.c是如何工作的
这是你使用表6-1的测量的四个常量。
现在这四个变量已经被声明,下面两行取平均值并乘以一个比例系数得到了程序所需的阀值,可以比较阀值和timeLeft以及timeRight的测量值来判断光敏电阻感应的是环境光还是聚焦光束。
下面这些变量用来存储放电时间的测量结果。
inttimeLeft,timeRight;
主程序中包含两个子函数调用。
所有实际的工作集中在两个子程序上,子函数Test_Photoresistors对两个RC光敏电阻电路进行放电时间测量,在前面介绍过,在此不再
介绍,Navigate判断并发送伺服电机控制脉冲。
Navigate子函数使用if…else来比较变量timeLeft和常量LeftThreshold,timeRight和RightThreshold。
记住,当测量的放电时间值小时,意味着探测到强光,当此值大时,意味着光不强。
因此,当存储测量结果的变量小于阀值时,意味着探测到手电筒光束,否则,没有探测到手电筒光束。
根据子程序探测到的情况,正确的导航脉冲被发出。
if((timeLeft<
P1_1=1;
delay_nus(1700);
P1_1=0;
P1_0=1;
delay_nus(1300);
P1_0=0;
elseif(timeLeft<
LeftThreshold)
delay_nus(1400);
}
elseif(timeRight<
RightThreshold)
delay_nus(1600);
else
delay_nus(1500);
delay_nms(20);
4)该你了――调节机器人性能和改变运动状态
你可以通过调整常量声明中的比例系数来调节程序的性能。
#defineLeftThreshold(LeftBright+LeftAmbient)/2+AmbientCL
#defineRightThreshold(RightBright+RightAmbient)/2+AmbientCR
如果你将比例系数由5/8改成1/2,机器人对光束的敏感程度会降低,这可能会改善手电筒光束的控制。
试用不同的比例系数,比如1/4,1/2,1/3,2/3,3/4等,注意机器人对手电筒光的任何不同反应。
修改例程中的if…else中的语句,你可以改变机器人的行动使其试图避开进入视觉范围的光线。
修改if…else语句,当机器人两侧光敏电阻都检测到手电筒光时,它向后退;
当机器人一侧的光敏电阻检测到手电筒光时,它转向另一侧。
1)重新调节光敏电阻
如果光敏电阻的聚光表面向上并向外,本任务的试验效果最好。
图7-2光敏电阻的方向
将光敏电阻的聚光表面向上并向外,如图7-2示。
2)编写向亮光移动的程序
向光源移动的关键是当两侧光敏电阻的测量结果差别小时,向前直走;
当两侧光敏电阻的测量结果差别大时,转向测量值小的一侧。
简而言之,宝贝车机器人会朝着更亮的地方转
动。
最初看起来是一个足够简单的编程任务;
像下面例子的if…else判断语句应该正常工作。
问题是,小车不会向前移动,因为它不断的左转然后右转,这是因为timeLeft和timeRight的变化很大。
每次宝贝车机器人转动一点,变量timeRight和timeLeft会变化很多以至于机器人试图去更正并向回走。
它永远不会得到向前走的脉冲信号。
if(timeLeft>
timeRight)
elseif(timeRight>
timeLeft)
下面是另一个工作稍好的代码块。
它将来回转弯的条件进行了修改。
在宝贝车机器人使
用左转脉冲之前变量timeLeft必须比timeRight大15。
同样的,当宝贝车机器人调整向右之前timeRight必须比timeLeft大15。
这就使机器人在特定的光线条件下转弯之前有机会使用足够多的向前脉冲。
timeRight+15)
timeLeft+15)
上面代码块的问题是它只能工作在中等黑暗的环境下。
如果将它拿到相当暗的地方,宝
贝车机器人不断的来回旋转,永远不会向前行走。
如果将它拿到更亮的地方,宝贝车机器人
只会向前运动,而不会调整向左或向右的方向。
为什么会是这样?
答案是这样的:
当宝贝车机器人处在房子的黑暗部分时,每个光敏电阻的测量值会大一
些。
机器人决定转向亮光源时,两个测量结果之间的差别会较大;
当机器人处在更亮一点的
地方时,每个光敏电阻的测量值会小一点,机器人决定做一个转动时,两个测量结果之间的
差别会比在黑暗的地方小。
使小车对不同的光线条件产生不同的响应的方法是设定一个变
量,即timeRight和timeLeft的平均值的分数。
这样的话,无论外界光线强弱,值总是正确的。
average=(timeRight+timeLeft)/2
difference=average/6
现在,变量difference可以被用在if…else语句中,当光线弱时,它的值大,当光线强时,它的值小。
(timeRight+difference))
(timeLeft+difference))
例程:
RoamingTowardTheLight.c
不像程序RoamingWithPhotoresistorDividers.c,不管外界光的强弱,这个程序将对用手在光敏电阻上投的阴影非常敏感。
这个程序不需要根据外界光线情况改变电阻,相反,它会计算光的强弱并在软件中使用变量average和difference调节灵敏度。
此程序测量timeLeft和timeRight的平均值,并用平均值来设置difference的值在timeLeft和timeRight的测量结果之间。
这个值用来判断是否发送一个转弯脉冲。
输入、保存并运行程序RoamingTowardTheLight.c。
将机器人放在不同的地方,让它移动,验证无论光的强度如何,你可以通过用手在RC电路的一个光敏电阻上投一个阴影来改变其运动轨迹。
试着将机器人放在光线很暗的房子里,但是有光线通过门从邻近很亮的屋子或走廊射进来,看机器人是否可以成功走出屋子。
//#defineLeftAmbient950
//#defineRightAmbient950
//#defineLeftBright923
//#defineRightBright923
intaverage,timeLeft,timeRight,difference,counter,count;
voidAverage_And_Difference(void)
average=(timeRight+timeLeft)/2;
difference=average/6;
if(timeLeft>
(timeRight+difference))
elseif(timeRight>
(timeLeft+difference))
for(counter=1;
counter<
c