• 沒有找到結果。

机器人的距离检测

TMOD为定时器模式寄存器,它也有8位,但不能像TCON一样可以一位一位的设置,只能

模式2最大计数值为256us(28),满足要求,因此用模式2来显示LED灯闪烁功能,计数的值 CC为0.2ms/1us=200。利用公式计算得出TC=256-200=59,换成十六进制为TC=0x38。

例程:TimeApplication.c

z 搭建LED的测试电路(具体请参照第二章内容)

z 接通教学板的电源

z 输入、保存并运行程序Time_Application.c z 验证与P1_0连接的LED是否每个0.4ms闪烁一次

#include <AT89X52.H>

#include <stdio.h>

void initial(void); //子函数声明 void main(void)

{

void initial(void) {

void TIMER(void) interrupt 1 //中断服务程序,1是定时器0的中断号 {

void initial(void); //子函数声明

主函数main()很好理解:首先对中断进行初始化设置,然后等待中断。

IE=0x82;

EA=1且ET0=1,打开了全局和定时器0的中断(参考表6-4)。

TCON=0x00;

停止定时器,并清除了中断标志(参考表6-1)。

TMOD=0x02;

返回值 函数名([参数])interrupt m[using n]

{

使用“寄存器组”的概念使软件的不同部分可以拥有一组私有的寄存器,不受其他部分 的影响,因而可以快速高效地进行“上下文切换”。

由于LED灯的闪烁频率过快,而人的视觉反应不够快,因此你观察到LED灯是一直亮着的。

你可以借助示波器观察P1_0输出的是不是矩形波,周期是不是400us。

该你了——调整定时器时间

为了可以看见LED灯闪烁,你可以使用定时器模式0,由于在此方式下最大延时时间为8ms

(213=8192)。对比第二章的LED程序,分析它们有何不同之处,使用示波器观察,你会发 现使用定时器方式可以产生更精确的时间。

若效果还不明显,你可设计一个循环,如当检测到2500次中断后更改一次IO口的电平,

即将闪烁时间改为2500*0.4ms=1s,有利于肉眼观察。

任务二 测试扫描频率

红外线探测器频率探测

图6-1显示的是教材所使用的红外线探测器频率与灵敏度关系数据表的部分摘录。这个 摘录显示了红外线探测器在接收到频率不同于38.5kHz

时红外线信号时其敏感程度随频率变化的曲线图。例如,

当你发送频率为40kHz的信号给探测器时,它的灵敏度是 频率为38.5kHz的80%;如果红外LED发送频率为42kHz,

探测器的灵敏度是频率为38.5kHz的50%左右。对于灵敏 度很低的频率,为了让探测器探测到反射的红外线,物 体必须离探测器更近。

另一个角度来考虑就是,高灵敏度的频率可以探测 远距离的物体,低灵敏度的频率可以探测距离较近的物 体。这使得距离探测就简单了。

选择5个不同频率,从最低灵敏度到最高灵敏度进行 测试,依赖于探测器不能再检测到物体的红外线频率,

就可以推断物体的大概位置。

图6-1 灵敏度与频率关系图 对频率扫描进行编程做距离探测

图6-2举例说明机器人如何用红外发射频率做距离测试。在这个例子中,目标物体在区 域3。也就是说,发送35700Hz和38460Hz频率能发现物体,发送29370Hz、31230Hz以及33050Hz 频率就不能发现物体。如果你移动物体到区域2,那么发送33050Hz、35700Hz以及38460Hz 可以发现物体,发送29370Hz和31230Hz频率不能发现物体。

图6-2 频率和探测区域 int distanceLeft, irDetectLeft;

unsigned int frequency[5]={29370,31230,33050,35700,38460};

void timer_init(void) {

IE=0x82; //开总中断EA,允许定时器0中断ET0 TMOD |= 0X01; //定时器0工作在模式1:16位定时器模式 }

void FreqOut(unsigned int Freq) {

void Timer0_Interrupt(void) interrupt 1 //定时器中断 {

LeftLaunch = ~LeftLaunch; //取反 TH0 = 0xFF; //重新设值 TL0 = time;

}

void Get_lr_Distances() {

unsigned int count;

leftdistance = 0; //初始化左边的距离 for(count = 0;count<5;count++)

{

FreqOut(frequency[count]);//发射频率 irDetectLeft = LeftIR;

printf("irDetectLeft = %d",irDetectLeft);

if(irDetectLeft == 1) leftdistance++;

} }

int main(void) {

uart_Init();

timer_init();

printf("Progam Running!\n");

printf("FREQENCY ETECTED\n");

while(1) {

Get_lr_Distances();

printf("distanceLeft = %d\n",leftdistance);

printf("---\n");

unsigned int frequency[5]={29370,31230,33050,35700,38460};

uart_Init();

频率为f时,周期T=1/f,高低电平持续时间为t=1/(2T),根据公式TC=2n-CC可算定时器 初值time:

f time t 500000

65536

根据n=8时计算,即函数FreqOut(frequency[count])中用的time = 256 - (500000/Freq) 来计算。当低八位计满后,整个寄存器将溢出。

根据图6-2所示的描述原理,如果检测结果irDetectLeft为1,即没有发现物体,则距离 leftdistance加1。循环描述,当5个频率描完后,可根据leftdistance的值来判断物体离机 器人的大致距离。

运行程序时,在机器人前端放一白纸,前后移动白纸,调试终端将会显示白纸所在的区 域,如图6-3所示。

图6-3 距离探测输出实例

程序通过计算 “1” 出现的数量,就可以确定目标在哪个区域。

紧记,这种距离测量方法是相对的而非绝对地精确。然而,它为机器人跟随,跟踪和其 他行为提供了一个足够好的探测距离的能力。

z 输入、保存并运行程序TestLeftFrequencySweep.c z 用一张纸或卡片面对IR LED/探测器做距离探测

z 改变纸片与机器人距离,记录使distanceLeft变化的位置 该你了――测试右边的IR LED/探测器

z 修改程序TestLeftFrequencySweep.c,对右边的IR LED/探测器做距离探测测试 z 运行该程序,检验这对IR LED/探测器能否测量同样的距离。

你可参考教材配套光盘对应例程中的注释部分。

例程:DisplayBothDistances.c

z 修改程序TestLeftFrequencySweep.c,添加右边IR LED/探测器部分 z 输入、保存并运行程序DisplayBothDistances.c

z 用纸片重复对每个IR LED进行距离探测,然后对两个IR LED同时进行测试 该你了――更多的距离测试

z 尝试测量不同物体的距离,弄清物体的颜色和(或)材质是否会造成距离测量的差异

任务三 尾随小车

让一个机器人跟随另一个机器人行走,跟随的机器人也叫尾随车。尾随车要正常工作必 须知道距离引导车有多远。如果尾随车落在后面,它必须能察觉并加速。如果尾随车距离引 导车太近,它也要能察觉并减速。如果当前距离正好合适,它会等待直到测量距离变远或变 近。

距离仅仅是由机器人和其它自动化机器需要控制一种数值之一。当一个机器被设计用来 自动维持某一数值,比如距离、压力或液位等,它一般都包含一个控制系统。这些系统有时 由传感器和阀门组成,或者由传感器和电机组成。在机器人里面,由传感器和连续旋转电机

组成。还必须有某些处理器可以接受传感器的测量结果并把它们转化为机械运动。必须对处 理器编程来基于传感器的输入做出决定,从而控制机械输出。

闭环控制是一种常用的维持控制目标数据的方法,它很好地帮助机器人保持与一个物体 之间的距离。闭环控制算法类型多种多样,最常用的有滞后、比例、积分以及微分控制。所 有这些控制方法都将在《过程控制》教材中详细介绍。

图6-4所示的方框图描述了机器人用到的比例控制过程的步骤,即机器人用右边的IR LED/探测器探测距离并用右边的伺服电机调节机器人之间的位置以维持适当的距离。

图6-4 右伺服电机及IR LED/探测器的比例控制方框图

你仔细观察一下图6-4中的数字,学习一下比例控制是如何工作的。这个特殊的例子是 右边的IR LED/探测器和右边的伺服电机的比例控制方框图。设定位置为2,说明你想机器人 维持它和任何它探测到的物体之间的距离是2。测量的距离为4,距离太远。误差是设定值减 去测量值的差,即2-4=-2,这在圆圈的左方以符号的形式指出,这个圆圈叫求和点。接着,

误差传入一个操作框。这个操作框显示,误差将乘以一个比例常数Kp。Kp的值为70。该操作 框的输出显示为–2×70 = –140,这叫输出校正。这个输出校正结果输入到另一个求和点,

这时它与电机的零点脉冲宽度1500相加。相加的结果是1360,这个脉宽可以让电机大约以3/4 全速顺时针旋转。这让机器人右轮向前、朝着物体的方向旋转。

第二次经过闭环,测量距离可能发生变化,但是没有问题,因为不管测量距离如何变,

这个控制环路将会计算出一个数值,让电机旋转来纠正任何误差。修正值与误差总是成比例 关系,该误差就是设定位置和测量位置的关系的偏差。

控制环都有一组方程来主导系统行为。图6-4中的方框图是对该组方程的可视化描述方 法。下面是从方框图中归纳出来的方程关系及结果:

Error = Right distance set point – Measured right distance

= 2 – 4 Output adjus = error·Kp

= –2 ·70

= –140

Right servo output = Output adjust + Center pulse width

= – 140 +1500

= 1360

通过一些置换,上面三个等式可被简化为一个,提供你相同的结果:

Right servo output = (Right distance set point – Measured right distance)   Kp+ Center pulse width

代入数值,你可以看到结果一致:

= ((2 – 4)·70) + 1500

= 1360

左边的IR LED/探测器以及左边的伺服电机的控制框图如图6-5所示,与右边的运算法则 类似。不同的是比例系数Kp的值由+70变为为-70。假设与右边的测量值一样,输出修正的脉 冲宽度应该为1640。下面是该框图的计算等式:

图6-5 左伺服电机及IR LED/探测器的比例控制方框图

Left servo output = (Left distance set point – Measured left distance)   Kp+ Center pulse width

= ((2 – 4)·(–70)) +1500

= 1640

这个控制环的值让电机大约以3/4全速逆时针旋转。这个对机器人的左轮来讲是一个向 前旋转的脉宽。反馈的意思是,系统的输出被尾随车重新采样做另一个距离探测。控制环一 次又一次的重复运行,大概每秒40次。

对尾随车编程

下面的例子说明如何用C语言求解上面的方程。右边距离设置为2,测量距离由变量 distanceRight存储,Kp为70,零点脉冲宽度为1500:

pulseRight = (2 - distanceRight )* 70 + 1500 左伺服电机的比例系数Kp为-70:

pulseLeft = (2 – distanceLeft) * (-70) + 1500

既然数值 -70, 70, 2, 和 1500 全都有命名,干脆对这些常数声明如下:

#define Kpl -70

#define Kpr 70

#define SetPoint 2

#define CenterPulse 1500

由于程序中有这些常数声明,你可以用Kpl代替-70,Kpr代替70,SetPoint代替2,

CenterPulse代替1500。在常量声明之后,比例控制计算式象这样:

pulseLeft = (SetPoint – distanceLeft) * Kpl + CenterPulse pulseRight = (SetPoint – distanceRight) * Kpr + CenterPulse

声明变量很大的便利在于,你只需在程序的开始部分对变量做一次改变。程序的开始部 分的修改会反映到所有你用到该常量的地方。例如把#define Kpl -70中的-70改为-80,那 么程序中所有Kpl的值都会由-70更改为-80。对于左、右比例控制系统的试验来讲,这是非

z 输入、保存并运行程序FollowingRobot.c

z 把大小为8.5×11英寸的纸片置于机器人的前面,就像障碍物墙。机器人应该维持它 和纸片之间的距离为预定的距离

z 尝试轻轻旋转一下纸片,机器人应该跟随之旋转 z 尝试用纸片引导机器人四处运动,机器人应该跟随它 z 移动纸片距离机器人特别近时,机器人应该后退,远离纸片

z 尝试轻轻旋转一下纸片,机器人应该跟随之旋转 z 尝试用纸片引导机器人四处运动,机器人应该跟随它 z 移动纸片距离机器人特别近时,机器人应该后退,远离纸片