MEMS/传感技术
超声波传感器(HC-SR04)通常用于查找物体与一个特定点的距离。使用Arduino执行此操作相当容易,并且代码也非常简单。但是在本文中,我们将尝试使用这些流行的HC-SR04传感器进行一些不同的事情。我们将尝试计算两个超声波传感器之间的距离,也就是说,我们将使一个传感器充当发射器,另一个传感器充当接收器。通过这样做,我们可以使用许多超声波接收器跟踪一个发射器的位置,这种跟踪称为三角测量,可用于自动对接机器人行李跟随器和其他类似应用。找到两个美国传感器之间的距离听起来可能是一项相当简单的任务,但我遇到了一些挑战,这些挑战在本项目中进行了讨论。
本文中讨论的技术不太准确,如果不进行修改,在任何实际系统中可能都没有用。在本文档期间,我没有发现有人获得与我一样接近的结果,所以我刚刚分享了我如何让它工作的观点,以便正在尝试这个的人不需要重新发明轮子。
所需材料:
Arduino (2Nos) – 任何型号
HCSR04 模块 (2 个)
电路图:
即使我们要使一个美国(超声波)传感器用作发射器,另一个用作接收器,也必须将传感器的所有四个引脚与Arduino连接。我们为什么要这样做?稍后将讨论更多内容,但现在电路图如下
如您所见,发射器和接收器的电路图都是相同的。
HC-SR04模块的实际工作原理:
在我们继续之前,让我们了解 HC-SR04 传感器的工作原理。下面的时序图将帮助我们了解工作。
传感器有两个引脚触发和回波,用于测量距离,如时序图所示。首先要启动测量,我们应该从发射器发送超声波,这可以通过将触发引脚设置为高电平 10uS 来完成。一旦完成,发射器引脚将发送 8 次美式波声波。这个美国波将击中物体反弹并被接收器接收。
这里的时序图显示,一旦接收器接收到波,它将使Echo引脚在一段时间内变为高电平,该持续时间等于波从美国传感器传播并返回传感器所需的时间。这个时序图似乎不是真的。
我覆盖了传感器的Tx(发射器)部分,并检查了回波脉冲是否变高,是的,它确实变高了。这意味着回波脉冲不会等待美国(超声波)被它接收。一旦它传播了美国波,它就会走高并保持高位,直到波浪回来。所以正确的时序图应该是如下所示的(对不起,我的写作技巧很差)
使您的 HC-SR04 仅用作变送器:
使HC-SR04仅用作变送器非常简单。如时序图所示,您必须将触发引脚声明为输出引脚,并使其保持高电平 10 微秒。这将引发超声波爆发。因此,每当我们想要传输波时,我们只需要控制发射器传感器的触发引脚,下面给出了代码。
使您的 HC-SR04 仅用作接收器:
如时序图所示,我们无法控制Echo引脚的上升,因为它与触发引脚有关。因此,我们不可能使HC-SR04仅作为接收器工作。但是我们可以使用黑客,只需用胶带覆盖传感器的发射器部分(如下图所示)或盖上美国波无法逃逸到其发射器外壳之外,并且回声引脚不会受到此美国波的影响。
现在要使回声引脚变高,我们只需要将这个虚拟触发引脚拉高 10 微秒。一旦此接收器传感器获得发射器传感器传输的美国波,回波引脚将变为低电平。
测量两个超声波传感器之间的距离 (HC-SR04):
到目前为止,我们已经了解如何使一个传感器用作发射器,另一个传感器用作接收器。现在,我们必须从发射器传感器发射超声波并使用接收器传感器接收它,并检查波从发射器传播到接收器所需的时间听起来很容易,对吗?但可悲的是!,我们这里有一个问题,这是行不通的。
发射器模块和接收器模块相距很远,当接收器模块从发射器模块接收到美国波时,它不会知道发射器何时发送此特定波。如果不知道开始时间,我们就无法计算所花费的时间,从而无法计算距离。为了解决这个问题,当发射器模块传输美国波时,必须使接收器模块的回波脉冲精确地变高。换句话说,发射器模块和接收器模块应该同时触发。这可以通过以下方法实现。
在上图中,Tx 表示发射器传感器,Rx 表示接收器传感器。如图所示,发射器传感器将以周期性的已知延迟传输美国波,这就是它所要做的。
在接收器传感器中,我们必须以某种方式使触发引脚在发射器引脚变高时准确变高。因此,最初我们随机使接收器触发器变为高电平,该触发器将保持高电平,直到回声引脚变低。该回波引脚仅在接收到来自发射器的 US 波时才会变低。因此,一旦它变低,我们就可以假设发射器传感器刚刚被触发。现在,有了这个假设,一旦回波变低,我们就可以等待已知的延迟,然后触发接收器触发。这将部分同步发射器和接收器的触发器,因此您可以使用 pulseIn() 读取即时回波脉冲持续时间并计算距离。
变送器传感器程序:
变送器模块的完整程序可以在页面底部找到。它只定期触发变送器传感器。
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
要触发传感器,我们必须使触发引脚保持高电平 10uS。执行相同操作的代码如上所示
接收器传感器程序:
在接收器传感器中,我们覆盖了传感器的发射器眼,使其成为假人,如前所述。现在我们可以使用上面提到的技术来测量两个传感器之间的距离。本页底部给出了完整的程序。下面解释几个重要的行
Trigger_US();
while (digitalRead(echoPin)==HIGH);
delayMicroseconds (10);
Trigger_US();
duration = pulseIn(echoPin, HIGH);
最初,我们使用函数 Trigger_US() 触发美国传感器,然后使用 while 循环等到回波引脚保持高电平。一旦它变低,我们等待预先确定的持续时间,这个持续时间应该在 10 到 30 微秒之间,这可以通过反复试验来确定(或者您可以使用下面给出的即兴想法)。在此延迟之后,使用相同的函数再次触发 US,然后使用 pulseIn() 函数计算波的持续时间。
现在使用相同的旧公式,我们可以计算距离,如下所示
distance= duration*0.034;
加工:
按照程序中的说明进行连接。如图所示,盖住接收器传感器的 Tx 部分。然后将下面给出的发射器代码和接收器代码分别上传到发射器和接收器Arduino。打开接收器模块的串行监视器,您应该注意到显示的两个模块之间的距离,如下面的视频所示。
注意:此方法只是一种意识形态,可能不准确或不令人满意。但是,您可以尝试下面的即兴想法以获得更好的结果。
即兴创意 – 使用已知距离校准传感器:
到目前为止奇怪地解释的方法似乎令人满意,但对于我的项目来说已经足够了。但是,我也想分享这种方法的缺点以及克服它们的方法。这种方法的一个主要缺点是,我们假设接收器的回波引脚在发射器传感器传输美国波后立即下降,这是不正确的,因为波在发射器之间传播需要一些时间。因此,发射器的触发器和接收器的触发器不会完全同步。
为了克服这个问题,我们可以首先使用已知距离来校准传感器。如果距离已知,我们将知道美国波从发射器到达接收器所需的时间。让我们将这个时间保留为 Del(D),如下所示。
现在我们将确切地知道在多长时间后我们应该使接收器的触发引脚变高才能与发射器的触发器同步。此持续时间可以通过已知延迟 (t) – Del(D) 计算。由于时间限制,我无法测试这个想法,所以我不确定它有多准确。因此,如果您碰巧尝试,请通过评论部分让我知道结果。
接收器部分的编程代码
const int trigPin = 9;
const int echoPin = 10;
// defines variables
long duration;
int distance, Pdistance;
void setup() {
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input
Serial.begin(9600); // Starts the serial communication
}
void loop() {
Pdistance=distance;
Calc();
distance= duration*0.034;
if (Pdistance==distance || Pdistance==distance+1 || Pdistance==distance-1 )
{
Serial.print("Measured Distance: ");
Serial.println(distance/2);
}
//Serial.print("Distance: ");
//Serial.println(distance/2);
delay(500);
}
void Calc()
{
duration=0;
Trigger_US();
while (digitalRead(echoPin)==HIGH);
delay(2);
Trigger_US();
duration = pulseIn(echoPin, HIGH);
}
void Trigger_US()
{
// Fake trigger the US sensor
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
}
变送器部分的编程代码
// defines pins numbers
const int trigPin = 9;
const int echoPin = 10;
// defines variables
long duration;
int distance;
void setup() {
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input
Serial.begin(9600); // Starts the serial communication
}
void loop() {
// Sets the trigPin on HIGH state for 10 micro seconds
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
delay(2);
}
全部0条评论
快来发表一下你的评论吧 !