机器人已经慢慢开始爬进我们的社会,让我们的生活变得更简单。我们已经可以在英国的道路上找到来自 Starship 的六轮送餐机器人,它们巧妙地在平民中导航到达目的地。每个导航到环境中的移动机器人都应该始终了解其相对于现实世界的位置和方向。有很多方法可以通过使用不同的技术来实现这一点,如 GPS、RF 三角测量、加速度计、陀螺仪等。每种技术都有其自身的优势,并且是独一无二的。在这个Arduino LM393 速度传感器教程中,我们将使用简单易用的LM393 速度传感器模块使用 Arduino 测量一些重要参数,例如速度、行进距离和机器人角度。通过这些参数,机器人将能够了解其真实世界的状态,并可以使用它进行安全导航。
Arduino 是构建机器人的爱好者中最受欢迎的选择,从简单的线跟随器到更复杂的自平衡或地板清洁机器人。您可以在机器人部分查看所有类型的机器人。
我们将建造一个由锂电池供电的小型机器人,并使用操纵杆驱动它。在运行期间,我们可以测量机器人的速度、距离和角度,并将其实时显示在连接到 Arduino 的 LCD 显示器上。这个项目只是帮助你测量这些参数,一旦你完成了这个,你就可以根据需要使用这些参数来自主操作你的机器人。听起来很有趣吧?所以让我们开始吧。
LM393 速度传感器模块 (H206)
在我们进入项目的电路图和代码之前,让我们了解LM393 速度传感器模块,因为它在项目中起着至关重要的作用。H206 速度传感器模块由集成了 LM393 电压比较器 IC 的红外光传感器组成,因此名称为 LM393 速度传感器。该模块还包括一个网格板,该网格板必须安装在电机的旋转轴上。所有组件都标记在下图中。
红外光传感器由一个 IR LED 和一个由一个小间隙隔开的光电晶体管组成。整个传感器装置放置在黑色外壳中,如上图所示。网格板由槽组成,板布置在红外光传感器的间隙之间,传感器可以感应到网格板中的间隙。栅板中的每个缝隙在通过缝隙时都会触发IR传感器;然后使用比较器将这些触发器转换为电压信号。比较器不过是 ON 半导体的 LM393 IC。该模块共有三个引脚,其中两个用于为模块供电,一个输出引脚用于计数触发次数。
H206 传感器安装布置
安装这些类型的传感器有点棘手。它只能安装在两侧都有轴突出的电机上。轴的一侧连接到车轮,而另一侧用于安装网格板,如上图所示。
由于轮子和盘子连接到同一根轴上,两者都以相同的速度旋转,因此通过测量盘子的速度,我们可以测量轮子的速度。确保网格板中的间隙通过 IR 传感器,只有这样传感器才能计算已通过的间隙数。只要满足指定条件,您也可以提出自己的机械布置来安装传感器。红外传感器通常用于许多机器人项目中,以引导机器人绕过障碍物。
上面显示的网格板有 20 个槽(网格)。这意味着传感器会为车轮一整圈找到 20 个间隙。通过计算传感器检测到的间隙数量,我们可以计算车轮行进的距离,类似地,通过测量传感器找到间隙的速度,我们可以检测到车轮的速度。在我们的机器人中,我们将这个传感器安装在两个轮子上,因此我们也可以找到机器人的角度。然而,使用加速度计或陀螺仪可以更明智地计算旋转角度,在此处学习将加速度计和陀螺仪与 Arduino连接,并尝试使用它们来测量旋转角度。
DIY Arduino LM393 速度传感器机器人电路图
该速度和距离感应机器人的完整电路图如下所示。Bot 由Arduino Nano作为其大脑组成,两个用于车轮的直流电机由 L298N H 桥电机驱动模块驱动。操纵杆用于控制机器人的速度和方向,两个速度传感器 H206 用于测量机器人的速度、距离和角度。然后测量值显示在16x2 LCD 模块中。连接到 LCD 的电位器可用于调节 LCD 的对比度,电阻器用于限制流向 LCD 背光的电流。
整个电路由一个 7.4V 锂电池供电。这个 7.4V 提供给电机驱动模块的 12V 引脚。然后,电机驱动模块上的稳压器将 7.4V 转换为稳定的 +5V,用于为 Arduino、LCD、传感器和操纵杆供电。
电机由 Arduino 的数字引脚 8、9、10 和 11 控制。由于还必须控制电机的速度,我们应该向电机的正极端子提供PWM 信号。因此,我们有引脚 9 和 10,它们都是支持 PWM 的引脚。操纵杆的 X 和 Y 值分别使用模拟引脚 A2 和 A3 读取。
正如我们所知,H206 传感器在检测到网格板中的间隙时会生成触发器。由于不应始终准确读取这些触发器以计算正确的速度和距离,因此两个触发器(输出)引脚都连接到 Arduino 板的外部中断引脚 2 和 3。将整个电路组装在底盘上并按照说明安装速度传感器,连接完成后,我的机器人如下所示。您还可以观看本页末尾的视频,了解传感器的安装方式。
现在硬件部分已经完成,让我们进入如何测量机器人的速度、距离和单程的逻辑,然后进入编程部分。
使用 LM393 速度传感器模块测量速度背后的逻辑
从传感器安装设置中,您应该知道 LM393 速度传感器模块 (H206) 仅测量网格板中存在的间隙。安装时应确保车轮(应测量其速度)和网格板以相同的速度旋转。就像这里一样,由于我们将轮子和盘子都安装在同一轴上,因此它们显然将以相同的速度旋转。
在我们的设置中,我们为每个车轮安装了两个传感器来测量机器人的角度。但是,如果您的目标只是测量速度和距离,我们可以将传感器安装在任何一个车轮上。传感器的输出(触发信号)最常连接到微控制器的外部中断引脚。每次检测到网格板中的间隙时,都会触发中断,并执行 ISR(中断服务程序)中的代码。如果我们能够计算出两个这样的触发器之间的时间间隔,我们就可以计算出车轮的速度。
在 Arduino 中,我们可以使用millis()函数轻松计算此时间间隔。从设备上电开始,该毫秒函数将每毫秒递增 1。因此,当第一个中断发生时,我们可以将 millis() 的值保存在一个虚拟变量中(如代码中的pevtime),然后当第二个中断发生时,我们可以通过从millis()中减去pevtime值来计算所花费的时间。
所用时间 = 当前时间 - 上一个时间所
用时间= millis ()- pevtime ; //以毫秒为单位的时间
一旦我们计算出所花费的时间,我们可以使用以下公式简单地计算 rpm 的值,其中 (1000/timetaken) 给出 RPS(每秒转数),然后乘以 60 将 RPS 转换为 RPM(每分钟转数) 。
rpm=(1000/timetaken)*60;
在计算 rpm 后,我们可以使用以下公式计算车辆的速度,前提是我们知道车轮的半径。
速度 = 2π × RPS × 车轮半径。
v = radius_of_wheel * rpm * 0.104
注意,上面的公式是以 m/s 为单位计算速度的,如果你想以 km/hr 为单位计算,请将 0.0104 替换为 0.376。如果您想知道值 0.104 是如何获得的,请尝试简化公式 V = 2π × RPS × 车轮半径。
即使使用霍尔传感器来测量旋转物体的速度,也使用相同的技术。但是对于 H206 传感器有一个问题,网格板有 20 个插槽,因此测量两个插槽间隙之间的时间会使微控制器过载。因此,我们仅在车轮完全旋转时测量速度。由于每个间隙都会产生两个中断(一个在间隙开始,另一个在间隙结束),我们将总共获得 40 个中断,以便轮子完成一个完整的旋转。因此,我们在实际计算车轮速度之前等待 40 次中断。相同的代码如下所示
if(rotation》=40)
{
timetaken = millis()-pevtime; //以毫秒为单位的时间
rpm=(1000/timetaken)*60; //计算转速的公式
pevtime = millis();
旋转=0;
}
这种方法的另一个缺点是,速度值不会下降到零,因为中断将始终等待车轮完成一个旋转来计算 rpm 值。这个缺点可以通过添加一个简单的代码来监控两个中断之间的时间间隔来轻松克服,如果它超过正常值,那么我们可以强制 rpm 和速度的值为零。链接在下面的代码中,我们使用变量dtime来检查时间差异,如果超过 500 毫秒,则速度和 rpm 的值被强制为零。
/*如果车辆停止则降为零*/
if(millis()-dtime》500) //500ms 内没有发现 inetrrupt
{
rpm= v = 0; // 使 rpm 和速度为零
dtime=millis();
}
测量车轮行驶距离背后的逻辑
我们已经知道,当车轮转一圈时,Arduino 会感应到 40 次中断。因此,对于轮子每转一圈,轮子行进的距离显然等于轮子的周长。由于我们已经知道车轮的半径,我们可以使用以下公式轻松计算所覆盖的距离
距离 = 2πr * 转数
距离 = (2*3.141*radius_of_wheel) * (left_intr/40)
使用公式 2πr 计算车轮的周长,然后乘以车轮的转数。
测量机器人角度背后的逻辑
确定机器人角度的方法有很多种。加速度计和陀螺仪通常用于确定这些值。但另一种便宜的方法是在两个车轮上都使用 H206 传感器。这样我们就可以知道每个轮子转了多少圈。下图说明了如何计算角度。
当机器人初始化时,它所面对的角度被认为是 0°。从那里它向左旋转,角度增加为负,如果它向右旋转,角度增加为正。为了便于理解,让我们考虑如图所示的 -90 到 +90 的范围。在这样的布置中,由于两个轮子具有相同的直径,如果任何一个轮子完全旋转,我们就会以 90° 的角度转动机器人。
例如,如果左轮完成一整圈(80 次中断),那么机器人将向左转 90°,类似地,如果右轮完成一整圈(80 次中断),那么机器人将向右转 -90°。现在我们知道,如果 Arduino 在一个轮子上检测到 80 个中断,那么机器人已经转动了 90°,我们可以根据哪个轮子判断机器人是正转(右)还是负(左)转。所以左右角可以用下面的公式计算
int angle_left = (left_intr % 360) * (90/80) ;
int angle_right = (right_intr % 360) * (90/80) ;
其中 90 是进行 80 度中断时所覆盖的角度。结果值是中断次数的乘积。我们还使用了 360 的模数,因此结果值永远不会超过 36。一旦我们计算了左角和右角,机器人面对的有效角度可以简单地通过从右角中减去左角来获得。
角度 = 角度右 - 角度左;
Arduino机器人代码
此速度和角度测量机器人的完整 Arduino 代码可在本页末尾找到。该程序的目的是使用上述逻辑计算机器人的速度、距离和角度,并将其显示在 LCD 屏幕上。除此之外,它应该提供一个使用操纵杆控制机器人的选项。
我们通过定义两个电机的数字 I/O 引脚来启动程序。请注意,我们还必须控制电机的速度,因此我们必须使用 Arduino 上的 PWM 引脚来控制电机。在这里,我们使用了引脚 8、9、10 和 11。
#define LM_pos 9 // 左电机
#define LM_neg 8 // 左电机
#define RM_pos 10 // 右电机
#define RM_neg 11 // 右电机
#define joyX A2
#define joyY A3
要测量所覆盖的速度和距离,我们需要知道车轮的半径,测量值并以米为单位输入,如下所示。对于我的机器人,半径为 0.033 米,但根据你的机器人,它可能会有所不同。
浮动radius_of_wheel = 0.033;//测量你的轮子的半径并在这里输入厘米
在setup函数中,我们将所有值初始化为零,然后在 LCD 上显示 Intro Text。我们还初始化了串行监视器以进行调试。然后我们提到速度传感器 H206 连接到引脚 2 和 3 作为外部中断。这就是检测到中断的地方,ISR 函数Left_ISR和Right_ISR将相应地执行。
void setup()
{
旋转 = rpm = pevtime = 0; //将所有变量初始化为零
Serial.begin(9600);
lcd.begin(16, 2); //初始化 16*2 LCD
lcd.print("Bot Monitor"); //介绍消息行 1
lcd.setCursor(0, 1);
lcd.print("-CircuitDigest"); //介绍消息第 2 行
延迟(2000);
lcd.clear();
lcd.print("Lt: Rt:");
lcd.setCursor(0, 1);
lcd.print("S:D:A:");
pinMode(LM_pos,输出);
pinMode(LM_neg,输出);
pinMode(RM_pos,输出);
pinMode(RM_neg,输出);
数字写入(LM_neg,低);
数字写入(RM_neg,低);
attachInterrupt(digitalPinToInterrupt(2), Left_ISR, CHANGE); //左轮传感器触发时
调用Left_ISR attachInterrupt(digitalPinToInterrupt(3), Right_ISR, CHANGE);//右轮传感器触发时调用Right_ISR
}
在 Left_ISR 例程中,我们简单地增加一个名为 left_intr 的变量,稍后将用于测量机器人的角度。在 Right_ISR 中,我们做同样的事情,但另外我们也在此处计算速度。每次中断都会增加变量旋转,然后使用上述逻辑来计算速度。
void Left_ISR()
{
left_intr++;delay(10);
}
无效 Right_ISR()
{
right_intr++; 延迟(10);
旋转++;
dtime=毫秒();
if(rotation>=40)
{
timetaken = millis()-pevtime; //以毫秒为单位的时间
rpm=(1000/timetaken)*60; //计算转速的公式
pevtime = millis();
旋转=0;
}
}
在主无限循环函数中,我们通过操纵杆监控 X 和 Y 的值。如果操纵杆移动,我们会根据该值控制机器人。机器人的速度取决于操纵杆被推多远。
int xValue = 模拟读取(joyX );
int yValue = 模拟读取(joyY );
int 加速度 = 地图 (xValue, 500, 0, 0, 200);
如果(xValue<500)
{
模拟写入(LM_pos,加速度);
模拟写入(RM_pos,加速度);
}
否则
{
类比写入(LM_pos,0);
模拟写入(RM_pos,0);
}
如果(yValue>550)
模拟写入(RM_pos,80);
如果(yValue<500)
analogWrite(LM_pos,100);
这将帮助用户移动机器人并检查获得的值是否符合预期。最后,我们可以使用上述逻辑计算机器人的速度、距离和角度,并使用以下代码将其显示在 LCD 上。
v = radius_of_wheel * rpm * 0.104;//0.033 是以米为单位的车轮半径
= (2*3.141*radius_of_wheel) * (left_intr/40);
int angle_left = (left_intr % 360) * (90/80) ;
int angle_right = (right_intr % 360) * (90/80) ;
角度 = 角度右 - 角度左;
lcd.setCursor(3, 0); lcd.print(""); lcd.setCursor(3, 0); lcd.print(left_intr);
lcd.setCursor(11, 0); lcd.print(""); lcd.setCursor(11, 0);lcd.print(right_intr);
lcd.setCursor(2, 1); lcd.print(""); lcd.setCursor(2, 1);lcd.print(v);
lcd.setCursor(9, 1); lcd.print(""); lcd.setCursor(9, 1);lcd.print(距离);
lcd.setCursor(13, 1); lcd.print(""); lcd.setCursor(13, 1);lcd.print(角度);
测试 Arduino 机器人以测量距离、速度和角度
准备好硬件后,将代码上传到 Arduino 并使用操纵杆移动机器人。机器人的速度、距离和角度将显示在 LCD 中,如下所示。
在 LCD 上,术语 Lt 和 Rt 分别代表左中断计数和右中断计数。您会发现这些值随着传感器检测到的每个间隙而增加。项S 表示机器人的速度,以米/秒为单位,项 D 表示以米为单位的距离。机器人的角度显示在末端,其中 0° 表示直线,逆时针旋转为负,顺时针旋转为正。
/*
* Arduino 车速、距离和角度计算器
*/
/*-------定义引脚------*/
#define LM_pos 9 // 左电机
#define LM_neg 8 // 左电机
#define RM_pos 10 // 右电机
#define RM_neg 11 // 右电机
#define joyX A2
#define joyY A3
#include
const int rs = 14, en = 15, d4 = 4, d5 = 5, d6 = 6, d7 = 7; //注明LCD连接的管脚号
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
int left_intr = 0;
int right_intr = 0;
int 角度 = 0;
/*硬件细节*/
float radius_of_wheel = 0.033; //测量你的轮子的半径并在这里输入厘米
易失字节轮换;// 中断乐趣的变量必须是 volatile
float timetaken,rpm,dtime;
浮动 v;
整数距离;
无符号长 pevtime;
void setup()
{
旋转 = rpm = pevtime = 0; //将所有变量初始化为零
Serial.begin(9600);
lcd.begin(16, 2); //初始化16*2 LCD
lcd.print("Vechile Monitor"); //介绍消息行 1
lcd.setCursor(0, 1);
lcd.print("-CircuitDigest"); //介绍消息第 2 行
延迟(2000);
lcd.clear();
lcd.print("Lt: Rt:");
lcd.setCursor(0, 1);
lcd.print("S:D:A:");
pinMode(LM_pos,输出);
pinMode(LM_neg,输出);
pinMode(RM_pos,输出);
pinMode(RM_neg,输出);
数字写入(LM_neg,低);
数字写入(RM_neg,低);
attachInterrupt(digitalPinToInterrupt(2), Left_ISR, CHANGE); //左轮传感器触发时
调用Left_ISR attachInterrupt(digitalPinToInterrupt(3), Right_ISR, CHANGE);//右轮传感器触发时调用Right_ISR
}
无效循环()
{
int xValue = 模拟读取(joyX);
int yValue = 模拟读取(joyY);
int 加速度 = 地图 (xValue, 500, 0, 0, 200);
如果(xValue<500)
{
模拟写入(LM_pos,加速度);
模拟写入(RM_pos,加速度);
}
其他
{
类比写入(LM_pos,0);
模拟写入(RM_pos,0);
}
如果(yValue>550)
模拟写入(RM_pos,80);
如果(yValue<500)
analogWrite(LM_pos,100);
/*如果车辆停止则降为零*/
if(millis()-dtime>500) //500ms 内没有发现 inetrrupt
{
rpm= v = 0; // 使 rpm 和速度为零
dtime=millis();
}
v = radius_of_wheel * rpm * 0.104;//0.033 是以米为单位的车轮半径
= (2*3.141*radius_of_wheel) * (left_intr/40);
int angle_left = (left_intr % 360) * (90/80) ;
int angle_right = (right_intr % 360) * (90/80) ;
角度 = 角度右 - 角度左;
lcd.setCursor(3, 0); lcd.print(""); lcd.setCursor(3, 0); lcd.print(left_intr);
lcd.setCursor(11, 0); lcd.print(""); lcd.setCursor(11, 0);lcd.print(right_intr);
lcd.setCursor(2, 1); lcd.print(""); lcd.setCursor(2, 1);lcd.print(v);
lcd.setCursor(9, 1); lcd.print(""); lcd.setCursor(9, 1);lcd.print(距离);
lcd.setCursor(13, 1); lcd.print(""); lcd.setCursor(13, 1);lcd.print(角度);
延迟(100);
}
void Left_ISR()
{
left_intr++;delay(10);
}
无效 Right_ISR()
{
right_intr++; 延迟(10);
旋转++;
dtime=毫秒();
if(rotation>=40)
{
timetaken = millis()-pevtime; //以毫秒为单位的时间
rpm=(1000/timetaken)*60; //计算转速的公式
pevtime = millis();
旋转=0;
}
}
评论
查看更多