发布于 2017 年 12 月 13 日 5

如何使用 Arduino 测量两个超声波传感器之间的距离
Ultrasonic sensor (HC-SR04) is commonly used to find the distance of an object from one particular point. It has been fairly easy to do this with the Arduino and the code is also pretty simple. But in this article we are going to try something different with these popular HC-SR04 sensors. We will try calculating the distance between two Ultrasonic sensors that is, we will make one sensor to act as transmitter and the other sensor to act as receiver. By doing this we can track the location of one transmitter using many ultrasonic receivers this tracking is called triangulation and can be used for automatic docking robots luggage followers and other similar application. Finding the distance between two US sensors might sound to be a fairly simple task but I faced few challenges which are discussed in this project.
超声波传感器(HC-SR04)通常用于测量物体与特定点之间的距离。使用 Arduino 和相对简单的代码就可以轻松完成这项任务。但在本文中,我们将尝试使用这些流行的 HC-SR04 传感器做一些不同的事情。我们将尝试计算两个超声波传感器之间的距离,即让一个传感器作为发射器,另一个传感器作为接收器。通过这种方式,我们可以使用多个超声波接收器来追踪一个发射器的位置,这种追踪称为三角定位,可以用于自动对接机器人、行李跟踪器以及其他类似的应用。找到两个超声波传感器之间的距离听起来可能是一项相对简单的任务,但我遇到了一些挑战,这些挑战在本文中有所讨论。
The technique discussed in this article is not fairly accurate and might not be useful in any real systems without modifications. During the time of this documentation I did not find anyone getting results as close as mine so I have just shared my views on how I got it to work so that people who are trying this need not re-invent the wheel.
本文中讨论的技术并不十分准确,如果没有修改,可能在任何实际系统中都不实用。在撰写本文档期间,我没有发现有人得到的结果与我的如此接近,所以我只是分享了我是如何实现的,以便尝试这项任务的人不必重新发明轮子。
Materials Required: 所需材料:
- Arduino (2Nos) – Any model
Arduino(2 个) – 任意型号 - HCSR04 Module (2Nos) HCSR04 模块(2 个)
Circuit Diagram: 电路图:
Even though we are going to make one US (Ultrasonic) sensor to work as transmitter and the other as receiver it is mandatory connect all the four pins of the sensors with the Arduino. Why should we? More of that will be discussed later, but for now the circuit diagram will be as follows
即使我们将一个超声波传感器用作发射器,另一个用作接收器,也必须将所有四个传感器引脚连接到 Arduino 上。为什么呢?这将在后面详细讨论,但目前电路图如下所示
As you can see the circuit diagram for both Transmitter and receiver are both identical. Also check: Arduino Ultrasonic Sensor Interfacing
如你所见,发射器和接收器的电路图完全相同。另外,请参阅:Arduino 超声波传感器接口
How HC-SR04 module actually works:
HC-SR04 模块的工作原理:
Before we proceed any further let us understand how the HC-SR04 sensor works. The below timing Diagram will help us understand the working.
在继续之前,让我们先了解一下 HC-SR04 传感器的工作原理。下面的时间图将帮助我们理解其工作原理。

The sensor has two pins Trigger and Echo which is used to measure distance as shown in the timing diagram. First to initiate measurement we should send an Ultrasonic wave from the transmitter, this can be done by setting the trigger pin high for 10uS. As soon as this is done the transmitter pin will send 8 sonic burst of US waves. This US wave will hit an object bounce back and will be received by the receiver.
传感器有两个引脚,触发(Trigger)和回声(Echo),用于测量距离,如时间图所示。首先,要启动测量,我们需要从发射器发送超声波。这可以通过将触发引脚设置为高电平 10 微秒来实现。一旦完成,发射器引脚将发送 8 次超声波脉冲。这些超声波脉冲会击中物体并反弹,然后被接收器接收。
Here the timing diagram shows that once the receiver receives the wave it will make the Echo pin go high for a duration of time which is equal to the time taken for the wave to travel from US sensor and reach back to the sensor. This timing diagram does not seem to be true.
这里的时间图显示,一旦接收器接收到波,它会将回声(Echo)引脚保持高电平一段时间,该时间等于波从超声波传感器发出并返回到传感器所需的时间。但这个时间图似乎并不准确。
I covered the Tx (transmitter) part of my sensor and checked if the Echo pulse got high, and yes it does go high. This means that the Echo pulse does not wait for the US (ultrasonic) wave to be received by it. Once it transmits the US wave it goes high and stays high until the wave returns back. So the correct timing diagram should be something like this shown below (Sorry for my poor writing skills)
我遮住了传感器的发射器(Tx)部分,并检查了回声脉冲是否变高,是的,它确实变高了。这意味着回声脉冲并不等待超声波(US)波被接收器接收到。一旦发射器发送超声波脉冲,回声脉冲就会变高并保持高电平,直到波返回。因此,正确的时序图应该是如下所示(抱歉我的书写技能不好)

Making your HC-SR04 to work as Transmitter only:
仅让 HC-SR04 工作为发射器:
It is pretty much straight forward to make a HC-SR04 to work as transmitter only. As shown in the timing diagram you have to declare the Trigger pin as output pin and make it stay high for 10 Microseconds. This will initiate the Ultrasonic wave burst. So whenever we want to transmit the wave we just have to control the trigger pin of the Transmitter sensor, for which the code is given below.
将 HC-SR04 设置为仅作为发射器使用非常简单。如图所示,您需要将触发引脚设置为输出引脚,并使其保持高电平 10 微秒。这将触发超声波脉冲。因此,每当我们要发射波时,只需控制发射传感器的触发引脚即可,相关的代码如下所示。
Making your HC-SR04 to work as Receiver only:
将 HC-SR04 设置为仅作为接收器使用:
As shown in the timing diagram we cannot control the rise of the Echo pin as it is related to trigger pin. So there is no way we could make the HC-SR04 to work as receiver only. But we can use a hack, by just covering the Transmitter part of the sensor with tape (as shown in the picture below) or cap the US wave cannot escape outside its Transmitter casing and the Echo pin will not be affected by this US wave.
如图所示,我们无法控制回声引脚的上升沿,因为它与触发引脚相关。因此,我们无法使 HC-SR04 仅作为接收器使用。但我们可以通过一个巧妙的方法来实现,只需用胶带覆盖传感器的发射部分(如图所示),或者封住超声波使其无法从发射器外壳中逸出,这样回声引脚就不会受到这个超声波的影响。

Now to make the echo pin go high we just have to pull this dummy trigger pin high for 10 Microseconds. Once this Receiver sensor gets the US wave transmitted by the Transmitter sensor the echo pin will go low.
现在,只要将这个假的触发引脚拉高 10 微秒,回声引脚就会变高。一旦接收传感器接收到发射传感器发射的超声波,回声引脚就会变低。
Measuring distance between two Ultrasonic sensors (HC-SR04):
两个超声波传感器(HC-SR04)之间的距离测量:
So far we have understood how to make one sensor work as transmitter and the other sensor to work as receiver. Now, we have to transmit the ultrasonic wave from transmitter sensor and receive it with the receiver sensor and check the time taken for the wave to travel from transmitter to receiver sounds easy right?? But sadly!, we have a problem here and this will not work.
到目前为止,我们已经了解了如何让一个传感器作为发射器,另一个传感器作为接收器。现在,我们需要从发射器传感器发射超声波,并由接收器传感器接收,并检查波从发射器传到接收器所花费的时间,这听起来是不是很简单??但遗憾的是,我们这里有一个问题,这种方法是行不通的。
The Transmitter module and Receiver module are far apart and when the receiver module receives the US wave from the transmitter module it will not know when the transmitter sent this particular wave. Without knowing the start time we cannot calculate the time taken and thus the distance. To solve this problem the Echo pulse of the receiver module must be made to go high exactly when the Transmitter module has transmitted the US wave. In other words, the Transmitter module and the receiver module should trigger at the same time. This can be achieved by the following method.
发射器模块和接收器模块相距较远,当接收器模块接收到发射器模块发射的超声波时,它无法知道发射器何时发射了这一特定波。如果我们不知道发射时间,就无法计算出所花费的时间,从而无法得出距离。为了解决这个问题,接收器模块的回声脉冲必须在发射器模块发射超声波的同一时刻变为高电平。换句话说,发射器模块和接收器模块应该同时触发。这可以通过以下方法实现。

In the above diagram, the Tx represents Transmitter sensor and Rx represents Receiver sensor. As shown the Transmitter sensor will be made to transmit US waves at a periodic known delay, this is all it has to do.
在上图中,Tx 代表发射传感器,Rx 代表接收传感器。如图所示,发射传感器将在已知的周期性延迟下发射超声波,这就是它需要做的全部。
In the Receiver sensor we have to somehow make the trigger pin go high exactly during when the transmitter pin goes high. So initially we randomly make the Receivers Trigger to go high which will and stay high till the echo pin goes low. This echo pin will go low only when it receives a US wave from the transmitter. So as soon as it goes low we can assume that the Transmitter sensor just got triggered. Now, with this assumption as soon as the echo goes low we can wait for the known delay and then trigger the receivers trigger. This would partially sync the trigger of both the Transmitter and receiver and hence you can read the immediate echo pulse duration using pulseIn() and calculate the distance.
在接收传感器中,我们需要以某种方式使触发引脚在发射引脚变高时也变高。因此,最初我们随机使接收传感器的触发引脚变高,该引脚将保持高电平,直到回声引脚变低。回声引脚只有在接收到发射传感器发出的超声波时才会变低。因此,一旦回声引脚变低,我们可以假设发射传感器刚刚被触发。现在,基于这一假设,一旦回声引脚变低,我们就可以等待已知的延迟,然后触发接收传感器的触发引脚。这将部分同步发射器和接收器的触发,因此你可以使用 pulseIn() 读取回声脉冲的持续时间并计算距离。
Program for Transmitter Sensor:
发射传感器程序:
The complete program for the transmitter module can be found at the bottom of the page. It does nothing but trigger the transmitter sensor at a periodic interval.
完整的发射模块程序可以在页面底部找到。它所做的只是在周期性的时间间隔触发发射传感器。
digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW);
To trigger a sensor we have to make the trigger pin to stay high for 10uS. The code to do the same is shown above
要触发传感器,我们需要让触发引脚保持高电平 10 微秒。实现相同功能的代码如上所示
Program for Receiver Sensor:
接收传感器的课程:
In the receiver sensor we have cover the Transmitter eye of the sensor to make it dummy as discussed earlier. Now we can use the above mentioned technique to measure distance between two sensors. The complete program is given at the bottom of this page. Few important lines are explained below
在接收传感器中,我们需要遮住传感器的发射窗口,使其成为假的,如前所述。现在我们可以使用上述方法来测量两个传感器之间的距离。完整的程序在本文末尾给出。以下是几个重要的代码行的解释
Trigger_US(); while (digitalRead(echoPin)==HIGH); delayMicroseconds (10); Trigger_US(); duration = pulseIn(echoPin, HIGH);
Initially we trigger the US sensor by using the function Trigger_US() and then wait till the echo pin stays high using a while loop. Once it gets low we wait for pre-determined duration, this duration should be somewhere between 10 to 30 microseconds which can be determined using trial and error (Or you can use improvised idea given below). After this delay trigger the US again using the same function and then use the pulseIn() function to calculate the duration of the wave.
最初,我们通过调用`Trigger_US()`函数触发超声波传感器,然后使用`while`循环等待回声引脚变为高电平。一旦回声引脚变为低电平,我们等待预设的持续时间,这个时间应在 10 到 30 微秒之间,可以通过试错来确定(或者你可以使用下面给出的临时想法)。在等待结束后,再次使用`Trigger_US()`函数触发超声波传感器,然后使用`pulseIn()`函数计算波的持续时间。
Now using the same old formulae we can calculate the distance as below
现在我们可以使用相同的公式计算距离,如下所示:
distance= duration*0.034;
Working: 工作原理:
Make the connections as explained in the program. Cover the Tx part of the receiver sensor as shown in the picture. Then upload the Transmitter code and receiver code which are given below to the transmitter and receiver Arduino respectively. Open the serial monitor of the receiver module and you should notice the distance between two modules being displayed as shown in the video below.
按照课程中所述进行连接。如图所示遮住接收传感器的 Tx 部分。然后分别将传发射代码和接收代码上传到传发射器和接收器的 Arduino 上。打开接收模块的串行监视器,你应该会看到两个模块之间的距离如下面的视频所示。
Note: This method is just an ideology and might not be accurate or satisfying. However you can try the improvised idea below to get better results.
注意:此方法仅是一种思路,可能不够准确或令人满意。但是你可以尝试下面的临时想法以获得更好的结果。

Improvised Idea – calibrating the sensor using a known distance:
临时想法 – 使用已知距离校准传感器:
The method that was explained so far oddly seems to be satisfying, yet it was sufficient for my project. However I would also like to share the drawbacks of this method and a way to overcome them. One major drawback of this method is that we assume that the Echo pin of the receiver falls low immediately after the Transmitter sensor has transmitted the US wave which is not true since the wave will take some time to travel from transmitter to receiver. Hence the Trigger of the transmitter and the trigger of the receiver will not be in perfect sync.
到目前为止所解释的方法似乎很合适,而且也足够满足我的项目需求。然而,我也想分享这种方法的缺点以及克服这些缺点的方法。这种方法的一个主要缺点是,我们假设接收器的 Echo 引脚会在发射器传感器发射超声波后立即变为低电平,但实际上波从发射器传到接收器需要一些时间,因此发射器和接收器的触发信号不会完全同步。
To overcome this we can calibrate the sensor using a know distance initially. If the distance is know we will know the time taken for the US wave to reach the receiver from the transmitter. Let’s keep this time taken as Del(D) as shown below.
为了解决这个问题,我们可以先用已知的距离对传感器进行校准。如果距离已知,我们就能知道超声波从发射器传到接收器所需的时间。让我们将这个时间记为 Del(D),如下所示。

Now we will exactly know after how much time we should make the Trigger pin of the Receiver to high to get sync with the trigger of the Transmitter. This duration can be calculated by Known Delay (t) – Del(D). I was not able to test this idea due to time limitations so I am not sure how accurate it would work. So if you happen to try it do let me know the results through the comment section.
现在我们就能确切知道应该在多长时间后将接收器的触发引脚设置为高电平,以与发射器的触发同步。这个时间可以通过已知延迟(t)- Del(D) 来计算。由于时间限制,我没有测试这个想法,所以不确定它的准确性。所以如果你尝试了,请通过评论部分告诉我结果。
Complete Project Code 完整项目代码
Programming code for Receiver part
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);
}
Programming code for Transmitter part
// 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);
}Comments 评论
I started trying to figure out this circuit about 2 years ago and threw in the towel. Thanks for posting this!
I used one arduino and the Ping example code (Arduino main menu: Files->Example->Sensors->Ping) , and instead of it switching pin 7 from output to input, I used another pin for output (added some Digital pin (e.g. 8) and called it rtnPin).
我使用了一个 Arduino,并使用了 Ping 示例代码(Arduino 主菜单:文件->示例->传感器->Ping),而不是将引脚 7 从输出切换为输入,我使用了另一个引脚作为输出(添加了一些数字引脚,例如 8,并将其命名为 rtnPin)。
const int pingPin = 7;
const int rtnPin = 8;
And then commented out the reassign statement at line 49/50 and changed the PulseIn function argument to read rtnPin instead of pingPin.
然后注释掉第 49/50 行的重新赋值语句,并将 PulseIn 函数的参数改为 rtnPin 而不是 pingPin。
//pinMode(pingPin, INPUT);
duration = pulseIn(rtnPin, HIGH);
Then connected pin 7 to the "trig" input of the transmitter sensor on the breadboard and then ran a wire from there to the "trig" pin of receiver sensor, that way they are synced. I then connected pin 8 to the echo pin of the receiver sensor. The "Vcc" and "gnd" pins were shared same as the "trig" pin. So far it's pretty accurate in terms of syncing, unless I'm missing something. Let me know if that's the case.
然后将引脚 7 连接到面包板上发射传感器的 "trig" 输入端,再用导线将 "trig" 端子连接到接收传感器的 "trig" 引脚,这样它们就同步了。然后将引脚 8 连接到接收传感器的 "echo" 引脚。"Vcc" 和 "gnd" 引脚也共享,与 "trig" 引脚相同。目前为止,同步效果相当准确,除非我遗漏了什么。如果有问题,请告诉我。
What is the maximum distance that can be measured with this? If one of these sensors has a range of 2 meters, does using 2 sensors double it to 4 meters?
使用这个方法能测量的最大距离是多少?如果其中一个传感器的量程为 2 米,使用两个传感器是否可以将量程扩展到 4 米?
Hello sir, 您好,
do the transmitter and the receiver have to be in front of each other?
发射器和接收器一定要面对面吗?
assume attaching a transmitter to a wall in the height of 1 meter and a receiver to a robot moving to the wall in the height of 0.5 meters. is it possible to measure the distance between them in this situation?
假设将发射器固定在高度为 1 米的墙上,接收器安装在机器人上,机器人高度为 0.5 米,朝墙移动。在这种情况下,能否测量它们之间的距离?


Hello sir, 您好,
i am working follow me robot. i see your video and code. i try to transmitter and reciver communicate. but i use 2 arduino uno and i try your code but i cannot measur distance. i have some problem. please help me sir!