本系列文章為作者原創,未經作者書面同意,不得轉載!
首先,我們來了解一下超聲波,科學家們將每秒鐘振動的次數稱為聲音的頻率,它的單位是赫茲(Hz)。我們人類耳朵能聽到的聲波頻率為20Hz-20000Hz。因此,我們把頻率高於20000赫茲的聲波稱為“超聲波”。
超聲波方向性好,穿透能力強,易於獲得較集中的聲能,在水中傳播距離遠,可用於測距、測速、清洗、焊接、碎石、殺菌消毒等。在醫學、軍事、工業、農業上有很多的應用:
在動物的世界裡,超聲波也起著不可替代的作用:
蝙蝠和海豚就是依靠自身發出的超聲波來定位捕獲獵物。
超聲波測距儀就是根據超聲波的特點設計而成:
我們今天的專案就是製作一個數字超聲波測距儀。
在這個專案中,您將學到的
- 學會使用超聲波測距感測器
- 學習使用四位數碼管
另外,透過這個專案您也會學習到LED顯示模組的一般驅動原理。
我們選用Arduino Uno作為數字超聲波測距儀的主控板,還會用到一個超聲波測距模組和一個共陰四位數碼顯示模組,由於我們採用的超聲波測距模組最大測距為4.5米,精度為0.2釐米,考慮到我們的顯示模組為4位,所以我們將顯示距離的單位設定為釐米,前三位顯示整數部分,最後一位顯示小數部分,正好能夠滿足超聲波測距模組的精度要求。
工具和元件
2.1 工具列表
本專案不需要額外的工具。
2.2 元器件列表
2.3.1 SR-04超聲波測距模組
SR-04超聲波測距模組效能穩定,測度距離精確,盲區小,關鍵是還很便宜,在創客圈應用最為廣泛,包括:機器人避障、物體測距、液位檢測等等。
2.3.1.1 技術引數
- 使用電壓DC 5V
- 靜態電流小於2mA
- 感應角度不大於15度
- 探測距離2cm-450cm
- 探測精度0.2cm
2.3.1.2 引腳說明
- VCC:供電 5V DC
- TRIG:控制端
- ECHO:接收端
- GND:接地,電源負極
2.3.1.3 工作原理
- 採用IO口TRIG觸發測距,給至少10us的高電平訊號;
- 模組自動傳送8個40khz的方波,自動檢測是否有訊號返回;
- 有訊號返回,透過IO口ECHO輸出一個高電平,高電平持續的時間就是超聲波從發射到返回的時間。
測試距離 = (高電平時間 * 聲速(340M/S)) / 2
所以這個模組的使用方法還是比較簡單的,在TRIG控制口發一個10US以上的高電平,就可以在ECHO接收口等待高電平輸出,一有輸出就可以開定時器計時,當此口變為低電平時就可以讀定時器的值,此時就為此次測距的時間,根據上面的公式即可計算出距離。
小知識:
聲音的傳播需要物質,物理學中把這樣的物質叫做介質。
聲音在不同的介質中的傳播速度:
真空 0m/s(也就是不能傳播)
空氣(15℃) 340m/s
空氣(25℃) 346m/s
軟木 500m/s
煤油(25℃) 1324m/s
蒸餾水(25℃) 1497m/s
海水(25℃) 1531m/s
銅(棒) 3750m/s
大理石 3810m/s
鋁(棒) 5000m/s
鐵(棒) 5200m/s
聲音在不同的物質中的傳播速度不同。
2.3.2 共陰四位數碼管
數碼管是一種半導體發光器件,數碼管可分為七段數碼管和八段數碼管,區別在於八段數碼管比七段數碼管多一個用於顯示小數點的發光二極體單元DP(decimal point),其基本單元是發光二極體。
共陰四位數碼管是一種數字顯示屏,由4個八段數碼管組成,能夠顯示4個數字,支援顯示小數點和時間格式。
數碼管是一種半導體發光器件,其基本單元是發光二極體。因此也需要串聯電阻,以防電流過大。
2.3.2.1 引腳說明
如下圖所示:abcdefgh 為數碼管LED引腳,每個數字由7條線(LED)組成,用a-g控制,h控制小數點;同時透過1-4引腳控制當前設定的四個數字中的哪一個。
3 電路設計
3.1 電路圖
根據我們的專案需求,設計電路圖如下:
3.2 電路原理
由於四位數碼管基本上用掉了所有數字口,除了0、1之外,由於0、1這兩個引腳是UNO連線電腦的串列埠,為了方便透過串列埠列印除錯資訊,一般儘量少佔用,所以超聲波測距模組在這裡使用了模擬口A4和A5。
知識點:
Arduino UNO電路板的數字口有13個,但有的專案我們可能需要更多的數字口,當我們數字埠不夠用時,該怎麼辦呢?當然,您可以購買效能更為強大的Arduino電路板,如MEGA 2560,但有沒有其它辦法呢?
其實Arduino電路板的模擬輸入口可以很方便的當數字口用,以UNO為例,對應的GPIO:A0=14、A1=15、A2=16......以此類推,使用方法和使用數字埠一樣。
4 程式設計
4.2 主程式設計
/*
*名稱:超聲波測距儀
*功能:
*作者:YXK
*時間:2018.6.5
*/
const int trigPin = 18; //定義超聲波測距模組trig引腳 A4
const int echoPin = 19; //定義超聲波測距echo引腳 A5
const int led[8] = {2,3,4,5,6,7,8,9}; //定義數碼管的LED引腳
const int com[4] = {13,12,11,10}; //定義數碼管的數字位引腳
float checkDistance(int trig, int echo); //超聲波測距函式
int firstBit,secondBit,thirdBit,fourthBit; //定義四位數碼管每位要顯示的值,依次是第1、2、3、4位
float distFloat; //宣告一個浮點型距離變數
int distInt; //宣告一個整形距離變數
int eyeDelay=500; //視覺延遲時間,單位微秒
//數碼管0-F .碼值表
unsigned char num[17][8] =
{
//a b c d e f g h
{1, 1, 1, 1, 1, 1, 0, 0}, //0
{0, 1, 1, 0, 0, 0, 0, 0}, //1
{1, 1, 0, 1, 1, 0, 1, 0}, //2
{1, 1, 1, 1, 0, 0, 1, 0}, //3
{0, 1, 1, 0, 0, 1, 1, 0}, //4
{1, 0, 1, 1, 0, 1, 1, 0}, //5
{1, 0, 1, 1, 1, 1, 1, 0}, //6
{1, 1, 1, 0, 0, 0, 0, 0}, //7
{1, 1, 1, 1, 1, 1, 1, 0}, //8
{1, 1, 1, 1, 0, 1, 1, 0}, //9
{1, 1, 1, 0, 1, 1, 1, 1}, //A
{1, 1, 1, 1, 1, 1, 1, 1}, //B
{1, 0, 0, 1, 1, 1, 0, 1}, //C
{1, 1, 1, 1, 1, 1, 0, 1}, //D
{1, 0, 0, 1, 1, 1, 1, 1}, //E
{1, 0, 0, 0, 1, 1, 1, 1}, //F
{0, 0, 0, 0, 0, 0, 0, 1}, //.
};
void setup()
{
for(int i=0;i<8;i++)
pinMode(led[i],OUTPUT);
for(int i=0;i<4;i++)
pinMode(com[i],OUTPUT);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}
void loop()
{
distFloat = checkDistance(trigPin, echoPin);
distInt = (int)distFloat*10;
//將距離顯示在四位數碼管上,需要將dist變數拆分成第一位、第二位、第三位、第四位
firstBit = distInt/1%10;
secondBit = distInt/10%10;
thirdBit = distInt/100%10;
fourthBit = distInt/1000%10;
for(int i=0;i<=500;i++){ //開始在數碼管上進行顯示
display(2,16); //顯示小數點
display(1,firstBit); //顯示第一位,即整數部分的百位
delayMicroseconds(eyeDelay); //做了一個視覺延遲
display(2,secondBit);
delayMicroseconds(eyeDelay);
display(3,thirdBit);
delayMicroseconds(eyeDelay);
display(4,fourthBit);
delayMicroseconds(eyeDelay);
}
}
void display(unsigned char d,unsigned char n) //顯示函式,d可選數值範圍1-4,n可選數值範圍0-16,16為小數點
{
for(int i=0;i<8;i++) //去除餘暉
digitalWrite(led[i],LOW);
switch(d) //選通位選
{
case 1:
digitalWrite(com[0],LOW); //選擇位1
digitalWrite(com[1],HIGH);
digitalWrite(com[2],HIGH);
digitalWrite(com[3],HIGH);
break;
case 2:
digitalWrite(com[0],HIGH);
digitalWrite(com[1],LOW); //選擇位2
digitalWrite(com[2],HIGH);
digitalWrite(com[3],HIGH);
break;
case 3:
digitalWrite(com[0],HIGH);
digitalWrite(com[1],HIGH);
digitalWrite(com[2],LOW); //選擇位3
digitalWrite(com[3],HIGH);
break;
case 4:
digitalWrite(com[0],HIGH);
digitalWrite(com[1],HIGH);
digitalWrite(com[2],HIGH);
digitalWrite(com[3],LOW); //選擇位4
break;
default:break;
}
for(int i=0;i<8;i++)
digitalWrite(led[i],num[n][i]); //按照碼值表進行顯示
}
float checkDistance(int trig, int echo) //超聲波測距函式
{
digitalWrite(trig, LOW); //控制端TRIG先發一個低電平,2微妙
delayMicroseconds(2);
digitalWrite(trig, HIGH); //控制端TRIG先一個高電平,2微妙
delayMicroseconds(10);
digitalWrite(trig, LOW);
float distance = pulseIn(echo, HIGH)/58; //根據接收端ECHO獲得的高電平時長計算距離
delay(10);
return distance;
}
這個程式就不再解釋了,程式中的註釋已經非常清楚了!
4 安裝除錯
下面我們根據電路圖將兩個模組跟UNO連線上:
測試一下,效果不錯!這裡稍微提醒一下,由於超聲波本身的特性,對於測試軟目標距離,如衣物,會有一定誤差,對於硬目標距離的測試,如牆壁,會比較準確,您可以測試測試!
5 總結擴充套件
為了能夠讓大家明白LED顯示模組的一般驅動原理,這個專案我沒有使用任何庫,您會發現主程式比較長,看起來似乎也比較複雜,關鍵是還不能複用。
您能夠根據這個主程式,為超聲波測距模組和四位數碼管寫兩個庫嗎?後續,如果有專案中也需要它們,您就可以很方便的複用了!
後面我們還會採用採用基於I2C介面的四位數碼管制作一個超聲波測距儀!
如果您喜歡本文,您可以點選一下下面的喜歡按鈕,您也可以關注我,謝謝您的支援!
