超聲波傳感器(HC-SR04)通常用于查找物體與一個(gè)特定點(diǎn)的距離。使用Arduino執(zhí)行此操作相當(dāng)容易,并且代碼也非常簡(jiǎn)單。但是在本文中,我們將嘗試使用這些流行的HC-SR04傳感器進(jìn)行一些不同的事情。我們將嘗試計(jì)算兩個(gè)超聲波傳感器之間的距離,也就是說(shuō),我們將使一個(gè)傳感器充當(dāng)發(fā)射器,另一個(gè)傳感器充當(dāng)接收器。通過(guò)這樣做,我們可以使用許多超聲波接收器跟蹤一個(gè)發(fā)射器的位置,這種跟蹤稱(chēng)為三角測(cè)量,可用于自動(dòng)對(duì)接機(jī)器人行李跟隨器和其他類(lèi)似應(yīng)用。找到兩個(gè)美國(guó)傳感器之間的距離聽(tīng)起來(lái)可能是一項(xiàng)相當(dāng)簡(jiǎn)單的任務(wù),但我遇到了一些挑戰(zhàn),這些挑戰(zhàn)在本項(xiàng)目中進(jìn)行了討論。
本文中討論的技術(shù)不太準(zhǔn)確,如果不進(jìn)行修改,在任何實(shí)際系統(tǒng)中可能都沒(méi)有用。在本文檔期間,我沒(méi)有發(fā)現(xiàn)有人獲得與我一樣接近的結(jié)果,所以我剛剛分享了我如何讓它工作的觀點(diǎn),以便正在嘗試這個(gè)的人不需要重新發(fā)明輪子。
所需材料:
Arduino (2Nos) – 任何型號(hào)
HCSR04 模塊 (2 個(gè))
電路圖:
即使我們要使一個(gè)美國(guó)(超聲波)傳感器用作發(fā)射器,另一個(gè)用作接收器,也必須將傳感器的所有四個(gè)引腳與Arduino連接。我們?yōu)槭裁匆@樣做?稍后將討論更多內(nèi)容,但現(xiàn)在電路圖如下
如您所見(jiàn),發(fā)射器和接收器的電路圖都是相同的。
HC-SR04模塊的實(shí)際工作原理:
在我們繼續(xù)之前,讓我們了解 HC-SR04 傳感器的工作原理。下面的時(shí)序圖將幫助我們了解工作。
傳感器有兩個(gè)引腳觸發(fā)和回波,用于測(cè)量距離,如時(shí)序圖所示。首先要啟動(dòng)測(cè)量,我們應(yīng)該從發(fā)射器發(fā)送超聲波,這可以通過(guò)將觸發(fā)引腳設(shè)置為高電平 10uS 來(lái)完成。一旦完成,發(fā)射器引腳將發(fā)送 8 次美式波聲波。這個(gè)美國(guó)波將擊中物體反彈并被接收器接收。
這里的時(shí)序圖顯示,一旦接收器接收到波,它將使Echo引腳在一段時(shí)間內(nèi)變?yōu)楦唠娖?,該持續(xù)時(shí)間等于波從美國(guó)傳感器傳播并返回傳感器所需的時(shí)間。這個(gè)時(shí)序圖似乎不是真的。
我覆蓋了傳感器的Tx(發(fā)射器)部分,并檢查了回波脈沖是否變高,是的,它確實(shí)變高了。這意味著回波脈沖不會(huì)等待美國(guó)(超聲波)被它接收。一旦它傳播了美國(guó)波,它就會(huì)走高并保持高位,直到波浪回來(lái)。所以正確的時(shí)序圖應(yīng)該是如下所示的(對(duì)不起,我的寫(xiě)作技巧很差)
使您的 HC-SR04 僅用作變送器:
使HC-SR04僅用作變送器非常簡(jiǎn)單。如時(shí)序圖所示,您必須將觸發(fā)引腳聲明為輸出引腳,并使其保持高電平 10 微秒。這將引發(fā)超聲波爆發(fā)。因此,每當(dāng)我們想要傳輸波時(shí),我們只需要控制發(fā)射器傳感器的觸發(fā)引腳,下面給出了代碼。
使您的 HC-SR04 僅用作接收器:
如時(shí)序圖所示,我們無(wú)法控制Echo引腳的上升,因?yàn)樗c觸發(fā)引腳有關(guān)。因此,我們不可能使HC-SR04僅作為接收器工作。但是我們可以使用黑客,只需用膠帶覆蓋傳感器的發(fā)射器部分(如下圖所示)或蓋上美國(guó)波無(wú)法逃逸到其發(fā)射器外殼之外,并且回聲引腳不會(huì)受到此美國(guó)波的影響。
現(xiàn)在要使回聲引腳變高,我們只需要將這個(gè)虛擬觸發(fā)引腳拉高 10 微秒。一旦此接收器傳感器獲得發(fā)射器傳感器傳輸?shù)拿绹?guó)波,回波引腳將變?yōu)榈碗娖健?/p>
測(cè)量?jī)蓚€(gè)超聲波傳感器之間的距離 (HC-SR04):
到目前為止,我們已經(jīng)了解如何使一個(gè)傳感器用作發(fā)射器,另一個(gè)傳感器用作接收器?,F(xiàn)在,我們必須從發(fā)射器傳感器發(fā)射超聲波并使用接收器傳感器接收它,并檢查波從發(fā)射器傳播到接收器所需的時(shí)間聽(tīng)起來(lái)很容易,對(duì)嗎?但可悲的是!,我們這里有一個(gè)問(wèn)題,這是行不通的。
發(fā)射器模塊和接收器模塊相距很遠(yuǎn),當(dāng)接收器模塊從發(fā)射器模塊接收到美國(guó)波時(shí),它不會(huì)知道發(fā)射器何時(shí)發(fā)送此特定波。如果不知道開(kāi)始時(shí)間,我們就無(wú)法計(jì)算所花費(fèi)的時(shí)間,從而無(wú)法計(jì)算距離。為了解決這個(gè)問(wèn)題,當(dāng)發(fā)射器模塊傳輸美國(guó)波時(shí),必須使接收器模塊的回波脈沖精確地變高。換句話說(shuō),發(fā)射器模塊和接收器模塊應(yīng)該同時(shí)觸發(fā)。這可以通過(guò)以下方法實(shí)現(xiàn)。
在上圖中,Tx 表示發(fā)射器傳感器,Rx 表示接收器傳感器。如圖所示,發(fā)射器傳感器將以周期性的已知延遲傳輸美國(guó)波,這就是它所要做的。
在接收器傳感器中,我們必須以某種方式使觸發(fā)引腳在發(fā)射器引腳變高時(shí)準(zhǔn)確變高。因此,最初我們隨機(jī)使接收器觸發(fā)器變?yōu)楦唠娖?,該觸發(fā)器將保持高電平,直到回聲引腳變低。該回波引腳僅在接收到來(lái)自發(fā)射器的 US 波時(shí)才會(huì)變低。因此,一旦它變低,我們就可以假設(shè)發(fā)射器傳感器剛剛被觸發(fā)?,F(xiàn)在,有了這個(gè)假設(shè),一旦回波變低,我們就可以等待已知的延遲,然后觸發(fā)接收器觸發(fā)。這將部分同步發(fā)射器和接收器的觸發(fā)器,因此您可以使用 pulseIn() 讀取即時(shí)回波脈沖持續(xù)時(shí)間并計(jì)算距離。
變送器傳感器程序:
變送器模塊的完整程序可以在頁(yè)面底部找到。它只定期觸發(fā)變送器傳感器。
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
要觸發(fā)傳感器,我們必須使觸發(fā)引腳保持高電平 10uS。執(zhí)行相同操作的代碼如上所示
接收器傳感器程序:
在接收器傳感器中,我們覆蓋了傳感器的發(fā)射器眼,使其成為假人,如前所述?,F(xiàn)在我們可以使用上面提到的技術(shù)來(lái)測(cè)量?jī)蓚€(gè)傳感器之間的距離。本頁(yè)底部給出了完整的程序。下面解釋幾個(gè)重要的行
Trigger_US();
while (digitalRead(echoPin)==HIGH);
delayMicroseconds (10);
Trigger_US();
duration = pulseIn(echoPin, HIGH);
最初,我們使用函數(shù) Trigger_US() 觸發(fā)美國(guó)傳感器,然后使用 while 循環(huán)等到回波引腳保持高電平。一旦它變低,我們等待預(yù)先確定的持續(xù)時(shí)間,這個(gè)持續(xù)時(shí)間應(yīng)該在 10 到 30 微秒之間,這可以通過(guò)反復(fù)試驗(yàn)來(lái)確定(或者您可以使用下面給出的即興想法)。在此延遲之后,使用相同的函數(shù)再次觸發(fā) US,然后使用 pulseIn() 函數(shù)計(jì)算波的持續(xù)時(shí)間。
現(xiàn)在使用相同的舊公式,我們可以計(jì)算距離,如下所示
distance= duration*0.034;
加工:
按照程序中的說(shuō)明進(jìn)行連接。如圖所示,蓋住接收器傳感器的 Tx 部分。然后將下面給出的發(fā)射器代碼和接收器代碼分別上傳到發(fā)射器和接收器Arduino。打開(kāi)接收器模塊的串行監(jiān)視器,您應(yīng)該注意到顯示的兩個(gè)模塊之間的距離,如下面的視頻所示。
注意:此方法只是一種意識(shí)形態(tài),可能不準(zhǔn)確或不令人滿(mǎn)意。但是,您可以嘗試下面的即興想法以獲得更好的結(jié)果。
即興創(chuàng)意 – 使用已知距離校準(zhǔn)傳感器:
到目前為止奇怪地解釋的方法似乎令人滿(mǎn)意,但對(duì)于我的項(xiàng)目來(lái)說(shuō)已經(jīng)足夠了。但是,我也想分享這種方法的缺點(diǎn)以及克服它們的方法。這種方法的一個(gè)主要缺點(diǎn)是,我們假設(shè)接收器的回波引腳在發(fā)射器傳感器傳輸美國(guó)波后立即下降,這是不正確的,因?yàn)椴ㄔ诎l(fā)射器之間傳播需要一些時(shí)間。因此,發(fā)射器的觸發(fā)器和接收器的觸發(fā)器不會(huì)完全同步。
為了克服這個(gè)問(wèn)題,我們可以首先使用已知距離來(lái)校準(zhǔn)傳感器。如果距離已知,我們將知道美國(guó)波從發(fā)射器到達(dá)接收器所需的時(shí)間。讓我們將這個(gè)時(shí)間保留為 Del(D),如下所示。
現(xiàn)在我們將確切地知道在多長(zhǎng)時(shí)間后我們應(yīng)該使接收器的觸發(fā)引腳變高才能與發(fā)射器的觸發(fā)器同步。此持續(xù)時(shí)間可以通過(guò)已知延遲 (t) – Del(D) 計(jì)算。由于時(shí)間限制,我無(wú)法測(cè)試這個(gè)想法,所以我不確定它有多準(zhǔn)確。因此,如果您碰巧嘗試,請(qǐng)通過(guò)評(píng)論部分讓我知道結(jié)果。
接收器部分的編程代碼
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);
}
?
評(píng)論
查看更多