简介
本文给出了一个非常简单的介绍,到Arduino的平台上写的差差距控制器。我用这个例子Duemilanove。
该项目由两个输入轨道上的东/西光水平,然后用移动伺服电机,旋转东/西跟踪最强的光线水平。
在其所有的荣耀原油原型......剩余的MSDN光盘已经发现最后一个使用:
它如何工作
两个光传感器的基本光敏电阻,这些都是安装在90"给对方,想象这是你的眼睛,如果你看看墙上的直行,左眼45点左,和右眼45"的权利。这些传感器也屏蔽了,所以直接指向光源时,他们将看到最亮的水平。如果光源的动作,然后一个影子投射到传感器,改变其电阻。
跟踪阳光的照射下,例如当一个太阳能电池板,您希望阳光的强度最大,达到这个目标,两个传感器,因此需要看到同样的光强度。这就是我们如何确定的差距控制器输入。
读取输入传感器值,并做一比较,区别意味着他们在相同的光照水平,VE错误值意味着光线明亮的权利,并已经错误值意味着光线明亮到左边。
伺服然后发送一个位置值,和我们简单的递增或递减每次扫描输出的旋转平台,东部和西部,再次找到最佳的平衡点上的传感器的光水平。
在代码中,也上限和下限,以防止驾驶很难反对其最终损害伺服停止。死区值也是建立在代码中。这实际上意味着输出将不会改变,除非两个输入之间的误差大于一定值。死区防止抖动和不断抽搐的传感器。
我还增加了一个非常基本的平均2点在输入传感器,帮助理顺尖峰。在现实中,你可能要筛选了进一步的过滤掉不想要的噪音或尖峰。使用代码
在下载提供的草图文件可以上传到Arduino的。让我们采取了更加详细的看看代码。
代码的第一部分用于建立IO引脚分配,输入读数,错误和滚动平均误差的变量。死区范围也被定义,以及上限和下限,伺服,伺服最初的起点。
#include语句使得一个处理伺服阿尔杜伊诺的预建库的参考。它基本上允许一个简单的值写入伺服对象,然后用于设置伺服位置的脉冲宽度调制。#include <servo.h>
//IO Pins
int pinL = 5; //Left Sensor IO Pin
int pinR = 4; //Right Sensor IO Pin
int pinServo = 11; //Servo PWM pin
int leftValue = 0; //The left Sensor Value
int rightValue = 0; //The right Sensor Value
int error =0; //The Deviation between the 2 sensors
int errorAVG = 0; //Error Average - Rolling 2 Point
int deadband = 10; //Range for which to do nothing with output 10 = -10 to +10
//Servo Stuff
Servo hServo; //The servo object
int Position = 45; //Position to write out
int minPos = 5; //Min Position
int maxPos = 150; //Max Position
float output = (maxPos - minPos) /2; //Initial output Position
该代码的下一部分是Arduino的安装方法。这一次,是有效地使用任何你想要的主代码循环执行前初始化。在这个例子中,我所做的一切是伺服输出设置到最小,最大和中点为5秒,我的办公桌上,以便用于测试任何硬件的定位。串行端口串行报表泵出的消息,并可以在PC机上监控。{C}
代码的最后部分是主要的循环体,这是循环将持续运行,直到关闭电源或新代码下载到Arduino。
的输入值先读,然后抽出一些调试信息到串行端口。误差值计算,并经修订的新的传感器位置加入getTravel()返回的值决定。检查,以确保我们不会超过这些限制。void loop()
{
//Input Reading
leftValue = analogRead(pinL);
rightValue = analogRead(pinR);
Serial.print("L = "); Serial.print(leftValue); Serial.print(" | ");
Serial.print("R = "); Serial.print(rightValue); Serial.print(" | ");
Serial.print("E = "); Serial.print(error); Serial.print(" | ");
Serial.print("Eavg = "); Serial.print(errorAVG);
Serial.println();
//Calculate
error = leftValue - rightValue;
errorAVG = (errorAVG + error) / 2;
float newOutput = output + getTravel();
if (newOutput > maxPos)
{
Serial.println("At Upper Limit");
newOutput = maxPos;
}
else
{
if (newOutput < minPos)
{
Serial.println("At Lower Limit");
newOutput = minPos;
}
}
Serial.println("Writing output");
//Output Writing
hServo.write(newOutput);
output = newOutput;
}
我也有一个辅助方法getTravel(),它是用来确定如果我需要左右旋转,旋转,或做什么(如内死区)每次扫描。它只是返回一个1,-1或0,然后添加到当前位置之前被写入到伺服。
工作原型可以发现{A} int getTravel()
{
// -1 = Left; +1 = Right
if (errorAVG < (deadband * -1))
{
return 1;
}
else
{
if (errorAVG > deadband)
{
return -1;
}
else
{
//Do not move within deadband
return 0;
}
}
}
一个原型运行的视频。兴趣点
这是简单的,因为它得到。 ,你可以加强这方面的方法是:实施改善输入信号的噪声过滤加入某种形式的PID(比例/积分/微分)控制算法添加第二个垂直运动的伺服和额外的传感器
还有什么
参观我的其他文章或我的网站,为更多的Arduino的位和乙。 Arduino的CodeProject上搜索,也有由他人。
历史2010年9月22日 - 条第一版本| DaveAuld