超聲波傳感器(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):
到目前為止,我們已經了解如何使一個傳感器用作發射器,另一個傳感器用作接收器?,F在,我們必須從發射器傳感器發射超聲波并使用接收器傳感器接收它,并檢查波從發射器傳播到接收器所需的時間聽起來很容易,對嗎?但可悲的是!,我們這里有一個問題,這是行不通的。
發射器模塊和接收器模塊相距很遠,當接收器模塊從發射器模塊接收到美國波時,它不會知道發射器何時發送此特定波。如果不知道開始時間,我們就無法計算所花費的時間,從而無法計算距離。為了解決這個問題,當發射器模塊傳輸美國波時,必須使接收器模塊的回波脈沖精確地變高。換句話說,發射器模塊和接收器模塊應該同時觸發。這可以通過以下方法實現。
在上圖中,Tx 表示發射器傳感器,Rx 表示接收器傳感器。如圖所示,發射器傳感器將以周期性的已知延遲傳輸美國波,這就是它所要做的。
在接收器傳感器中,我們必須以某種方式使觸發引腳在發射器引腳變高時準確變高。因此,最初我們隨機使接收器觸發器變為高電平,該觸發器將保持高電平,直到回聲引腳變低。該回波引腳僅在接收到來自發射器的 US 波時才會變低。因此,一旦它變低,我們就可以假設發射器傳感器剛剛被觸發?,F在,有了這個假設,一旦回波變低,我們就可以等待已知的延遲,然后觸發接收器觸發。這將部分同步發射器和接收器的觸發器,因此您可以使用 pulseIn() 讀取即時回波脈沖持續時間并計算距離。
變送器傳感器程序:
變送器模塊的完整程序可以在頁面底部找到。它只定期觸發變送器傳感器。
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
要觸發傳感器,我們必須使觸發引腳保持高電平 10uS。執行相同操作的代碼如上所示
接收器傳感器程序:
在接收器傳感器中,我們覆蓋了傳感器的發射器眼,使其成為假人,如前所述?,F在我們可以使用上面提到的技術來測量兩個傳感器之間的距離。本頁底部給出了完整的程序。下面解釋幾個重要的行
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);
}
?
評論