使用Arduino和LM393速度传感器(H206)的移动机器人的速度,距离和角度测量

原文:https://circuitdigest.com/microcontroller-projects/speed-distance-and-angle-measurement-for-mobile-robots-using-arduino-and-lm393-h206

使用Arduino和LM393速度传感器(H206)的移动机器人的速度,距离和角度测量

ARDUINO项目

经过**阿斯温斯·拉吉(Aswinth Raj)** 2019年1月16日修改
在这里插入图片描述使用Arduino和LM393传感器(H206)的移动机器人的速度,距离和角度测量

机器人已开始慢慢进入我们的社会,以使我们的生活更简单。我们已经在英国的道路上找到了星际飞船(Starship)上的六个轮式送餐机器人,它们在平民之间巧妙地导航以到达目的地。导航到环境中的每个移动机器人都应始终了解其相对于现实世界的位置和方向。通过使用不同的技术(例如GPS,RF三角测量,加速度计,陀螺仪等),可以通过多种方法来实现这一目标。每种技术都有其自身的优势,并且自身是独一无二的。在本Arduino LM393速度传感器教程中,我们将使用简单易用的LM393速度传感器模块使用Arduino测量一些重要参数,例如速度,行进距离和机器人角度。有了这些参数,机器人将能够知道其现实状态并可以使用它进行安全导航。

Arduino是构建机器人的爱好者中最受欢迎的选择,从简单的线路跟随器到更复杂的自平衡地板清洁机器人。您可以在"机器人技术"部分中检查所有类型的机器人。

我们将建造一个由锂电池供电的小型机器人,并使用操纵杆驱动它。在运行期间,我们可以测量机器人的速度,距离和角度,并将其实时显示在与Arduino连接的LCD显示屏上。该项目仅能帮助您测量这些参数,完成此操作后,您就可以根据需要使用这些参数来自动操作机器人。听起来很有趣吧?因此,让我们开始吧。

LM393速度传感器模块(H206)

在进入该项目的电路图和代码之前,让我们了解LM393速度传感器模块,因为它在项目中起着至关重要的作用。该H206速度传感器模块包括一个红外光传感器与一个LM393电压比较IC故名LM393速度传感器集成在一起。该模块还包括一个栅板,必须将其安装到电动机的旋转轴上。下图标记了所有组件。
在这里插入图片描述
所述**红外线传感器**包括一个IR LED和由小GAB分离的光电晶体管的。整个传感器装置如上图所示放置在黑色外壳中。栅格板由狭槽组成,该板以这样的方式设置在红外传感器的间隙之间:传感器可以感应栅格板中的间隙。栅板中的每个缝隙穿过缝隙时都会触发红外传感器。然后使用比较器将这些触发器转换为电压信号。比较器不过是安森美半导体的LM393 IC。该模块具有三个引脚,其中两个用于为模块供电,一个输出引脚用于计算触发次数。

H206传感器的安装

在这里插入图片描述
安装这些类型的传感器有些棘手。它只能安装在轴的两侧都突出的电动机上。轴的一侧连接到车轮,而另一侧用于安装格栅板,如上所示。

由于车轮和板连接到相同的轴,两者均以相同的速度旋转,因此通过测量板的速度,我们可以测量车轮的速度。确保栅格板上的缝隙穿过红外传感器,只有这样,传感器才能够计算已穿过的缝隙的数量。只要满足指定条件,您还可以提出自己的机械布置来安装传感器。红外传感器通常用于许多机器人项目中,以引导机器人注意障碍物。

上面显示的栅格板有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引脚。分别使用模拟引脚A2和A3读取操纵杆的X和Y值。

众所周知,当检测到格栅板中的间隙时,H206传感器会产生触发信号。由于不应该总是准确地读取这些触发器来计算正确的速度和距离,因此两个触发器(输出)引脚都连接到Arduino板的外部中断引脚2和3。按照说明将整个电路组装在机箱上并安装速度传感器,连接完成后,我的机器人看起来如下图所示。您也可以在本页末尾观看视频,以了解传感器的安装方式。

使用Arduino和LM393传感器(H206)的移动机器人的速度,距离和角度测量

现在,硬件部分已经完成,让我们进入如何测量机器人的速度,距离和单个性的逻辑,然后继续进行编程部分。

使用LM393速度传感器模块进行速度测量的逻辑

从传感器安装设置中,您应该了解到LM393速度传感器模块(H206)仅能测量栅板上的间隙。在安装时,应确保车轮(应测量其速度)和格栅板以相同的速度旋转。像这里一样,由于我们将轮子和板都安装在同一根轴上,因此它们显然都将以相同的速度旋转。

在我们的设置中,我们为每个车轮安装了两个传感器以测量机器人的角度。但是,如果您的目的只是测量速度和距离,我们可以将传感器安装在任何一个车轮上。传感器的输出(触发信号)通常会连接到微控制器的外部中断引脚。每次检测到格栅板上的间隙时,都会触发一个中断,并执行ISR(中断服务程序)中的代码。如果我们能够计算出两个这样的触发器之间的时间间隔,我们就可以计算出车轮的速度。

在Arduino中,我们可以使用millis()函数轻松地计算该时间间隔。自打开设备电源后,此毫秒功能将保持每毫秒增加1的速度。因此,当第一次中断发生时,我们可以将millis()的值保存在一个虚拟变量中(例如此代码中的pevtime),然后当第二次中断发生时,我们可以通过从millis()中减去pevtime值来计算所需的时间。。

Time taken=current time-previous time 
timetaken =millis() - pevtime ; // timetaken在毫秒

计算完所需的时间后,我们可以使用以下公式简单地计算rpm的值,其中(1000 / timetaken)给出RPS(每秒转数),然后乘以60可将RPS转换为RPM(每分钟转数) 。

rpm =(1000 /timetaken)* 60;

在计算了转速之后,我们可以使用以下公式来**计算车辆的速度,**前提是我们知道了车轮的半径。

Velocity=2π×RPS×radius of wheel。
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)
  { 
    timelapsed = millis()-pevtime; //以毫秒为单位的时间
    rpm =(1000 / timetaken)* 60; //计算转速的公式
    pevtime = millis(); 
    rotation= 0; 
  }

这种方法的另一个缺点是,速度值不会降为零,因为中断将始终等待车轮完成一轮旋转以计算rpm值。可以通过添加一个简单的代码来监视两个中断之间的时间间隔来轻松克服此缺陷,如果该时间间隔超出正常范围,则可以强制将rpm和speed的值设置为零。在下面的代码中链接,我们使用了变量dtime来检查时间差,如果时间差超过500毫秒,则将速度和rpm的值强制设为零。

/ *要在车辆停止时降至零* / 
if(millis()-dtime> 500)//在500毫秒内未发现无扰动
{ 
  rpm = v = 0; //将rpm和 speed设置为零
  dtime = millis(); }

测量车轮行驶距离的逻辑

我们已经知道,当轮子旋转一整圈时,Arduino将感应到40个中断。因此,很明显,车轮每旋转一圈,车轮行进距离就等于车轮的周长。由于我们已经知道了车轮的半径,因此可以使用以下公式轻松计算出所覆盖的距离

Distance=2πr*number of rotations
Distance=(2 * 3.141 *radius_of_wheel)*(left_intr / 40)

使用公式2πr计算车轮周长,然后将其乘以车轮转数。

测量机器人角度的逻辑

有很多方法可以确定机器人的天使。加速度计和陀螺仪通常用于确定这些值。但是另一种便宜的方法是在两个车轮上都使用H206传感器。这样,我们将知道每个车轮转了多少圈。下图说明了如何计算角度。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IbTDoWIq-1618981064174)(C:%5CUsers%5CAdministrator%5CPictures%5Ctypora%5CLogic-Behind-Measuring-the-angle-of-Robot.png)]

初始化机器人时,其面对的角度被认为是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。一旦我们计算了左右角度,就可以通过从右角度减去左角度来简单地获得机器人所面对的有效角度。

angle = angle_right-angle_left;

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米,但根据您的机器人,半径可能会有所不同。

float radius_of_wheel = 0.033; //测量车轮的半径,并以厘米为单位在此处输入

设置功能中,我们将所有值初始化为零,然后在LCD上显示Intro Text。我们还初始化了串行监视器以进行调试。然后我们提到速度传感器H206作为外部中断连接到引脚2和3。那就是检测到中断的地方,ISR函数Left_ISRRight_ISR将相应执行。

void setup()
{
  rotation = 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"); // Intro Message Line 2 
  delay(2000); 
  lcd.clear(); 
  lcd.print(" Lt:Rt:"); 
  lcd.setCursor(0,1); 
  lcd.print(" S:D:A:");

  pinMode(LM_pos,OUTPUT); 
  pinMode(LM_neg,OUTPUT);

  pinMode(RM_pos,OUTPUT); 
  pinMode(RM_neg,输出);

  digitalWrite(LM_neg,LOW); 
  digitalWrite(RM_neg,LOW);

  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); 
}


void Right_ISR()
{ 
  right_intr ++; deoay(10);

  rotation++; 
  dtime = millis(); 
  if(rotation> = 40)
  {
    timetaken= millis()-pevtime; //以毫秒为单位的时间
    rpm =(1000 / timetaken)* 60; //计算转速的公式
    pevtime = millis(); 
    rotation= 0; 
  } 
}

在主要的无限循环函数内部,我们从操纵杆监视X和Y的值。根据值(如果移动了操纵杆),我们将相应地控制机器人。机器人的速度取决于操纵杆被推入多远。

int xValue = analogRead(joyX);
 int yValue = analogRead(joyY);

int acceleration = map (xValue, 500, 0, 0, 200);

if (xValue<500)
{
analogWrite(LM_pos, acceleration);
analogWrite(RM_pos, acceleration);
}

else
{
analogWrite(LM_pos, 0);
analogWrite(RM_pos, 0);
}

if (yValue>550)
analogWrite(RM_pos, 80);

if (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); 
angle = angle_right-angle_left;

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(distance); 
lcd.setCursor(13,1); lcd.print(“”); lcd.setCursor(13,1); lcd.print(angle);

测试Arduino机器人以测量距离,速度和角度

准备好硬件后,将代码上传到Arduino,然后使用操纵杆移动机器人。机器人的速度,机器人所覆盖的距离以及角度将在LCD上显示,如下所示。
在这里插入图片描述

在LCD上,术语Lt和Rt分别表示左中断计数和右中断计数。您会发现这些值对于传感器检测到的每个间隙都会增加。项目**S表示机器人的速度,单位为m / sec,术语D表示以米为单位的距离。**机器人的角度显示在末尾,其中0°表示直线,反方向旋转为负,顺时针旋转为正。

您也可以在本页结尾观看视频,以了解机器人的工作方式。希望您理解该项目并喜欢构建它。如果您有任何疑问,请将其留在评论部分,我会尽力答复。您也可以使用论坛来获得快速的技术帮助。

代码

/*
 * Arduino Vehicle Speed, Distance and angle calculator 
 */

/*-------defining pins------*/
#define LM_pos 9       // left motor
#define LM_neg 8       // left motor
#define RM_pos 10       // right motor
#define RM_neg 11       // right motor
#define joyX A2
#define joyY A3

#include <LiquidCrystal.h>

const int rs = 14, en = 15, d4 = 4, d5 = 5, d6 = 6, d7 = 7; //Mention the pin number for LCD connection
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

int left_intr = 0;
int right_intr = 0;
int angle = 0;

/*Hardware details*/
float radius_of_wheel = 0.033;  //Measure the radius of your wheel and enter it here in cm

volatile byte rotation; // variale for interrupt fun must be volatile
float timetaken,rpm,dtime;
float v;
int distance;
unsigned long pevtime;

void setup()
{
  rotation = rpm = pevtime = 0; //Initialize all variable to zero
  Serial.begin(9600);
  lcd.begin(16, 2); //Initialise 16*2 LCD
  lcd.print("Vechile Monitor"); //Intro Message line 1
  lcd.setCursor(0, 1);
  lcd.print("-CircuitDigest "); //Intro Message line 2
  delay(2000);
  lcd.clear();
  lcd.print("Lt:     Rt:    ");
  lcd.setCursor(0, 1);
  lcd.print("S:     D:  A:   ");

  pinMode(LM_pos, OUTPUT);
  pinMode(LM_neg, OUTPUT);
  pinMode(RM_pos, OUTPUT);
  pinMode(RM_neg, OUTPUT);

  digitalWrite(LM_neg, LOW);
  digitalWrite(RM_neg, LOW);
  
  attachInterrupt(digitalPinToInterrupt(2), Left_ISR, CHANGE); //Left_ISR is called when left wheel sensor is triggered 
  attachInterrupt(digitalPinToInterrupt(3), Right_ISR, CHANGE);//Right_ISR is called when right wheel sensor is triggered 
}

void loop()
{
 int xValue = analogRead(joyX);
 int yValue = analogRead(joyY);
  
int acceleration = map (xValue, 500, 0, 0, 200);

if (xValue<500)
{
analogWrite(LM_pos, acceleration);
analogWrite(RM_pos, acceleration);
}
else
{
analogWrite(LM_pos, 0);
analogWrite(RM_pos, 0);
}

if (yValue>550)
analogWrite(RM_pos, 80);
if (yValue<500)
analogWrite(LM_pos, 100);

/*To drop to zero if vehicle stopped*/
 if(millis()-dtime>500) //no inetrrupt found for 500ms
 {
  rpm= v = 0; // make rpm and velocity as zero
  dtime=millis();
 }
 v = radius_of_wheel * rpm * 0.104; //0.033 is the radius of the wheel in meter
 distance = (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) ;
 angle = angle_right - angle_left;

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(distance);
lcd.setCursor(13, 1); lcd.print("   "); lcd.setCursor(13, 1);lcd.print(angle);

delay(100);
  
}

void Left_ISR()
{
  left_intr++;delay(10);
}

void Right_ISR()
{
  right_intr++; delay(10);
  
  rotation++;
  dtime=millis();
  if(rotation>=40)
  {
    timetaken = millis()-pevtime; //timetaken in millisec 
    rpm=(1000/timetaken)*60;    //formulae to calculate rpm
    pevtime = millis();
    rotation=0;
  }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值