我的ESP32實做書籍:https://youyouyou.pixnet.net/blog/post/121105860
博客來網址:https://www.books.com.tw/products/0010901195


 超音波與蜂鳴器:倒車雷達

現在的汽車大部分都有配備倒車雷達,就是倒車時,會依據車子與障礙物之間的距離發出不同頻率的嗶嗶聲,用來指引駕駛避免撞到別人的車子,而這套倒車雷達我們也可以使用ESP32來實做。本章分成兩個部份,第一節我們先來了解超音波測距的原理,第二節再實做蜂鳴器與倒車雷達。

 超音波距離感測

爬山時,如果我們對著遠處的山頭大喊「你好」,過了幾秒就會聽到有人也對你喊著「你好」,筆者小時候一直以為是對面的登山客跟你在打招呼,後來才知道這叫做回音。

image

圖 回音的原理

那麼回音與超音波距離感測器有什麼關係呢?

所謂的回音就是聲音傳遞路徑上有障礙物時,聲音就會反彈到原來發出聲音的人,而聲音在空氣中傳遞的速度約340公尺/秒,因此若我們計算發出(trigger)時間與聽到回音(echo)的時間差,就可以大致推算出發聲者與障礙物之間的距離了,我們可以將公式表示為:

距離(m)=(時間(s) x 340 / 2

數字340是音速,而要除2則是因為聲音去一次、回一次,一共跑了兩次所以要除2,而這也就是後來在二次大戰中廣泛使用的雷達的原理,不同的地方是雷達用的是電磁波,而我們在本次實驗用是超音波(Ultrasound)模組,所謂的「超」音波是指「超出人類可以聽到的聲音頻率」,一般人類的耳朵可以聽到的聲音頻率是在16Hz~20KHz之間,而超音波測距模組則設計使用20KHz以上的頻率,目的是不要在測距時發出惱人的噪音,也因為這樣這個測量距離的模組就稱為超音波測距模組,市面上常見的型號是HC-SR04如下圖。

image

HC-SR04超音波模組

超音波感測器有兩個大大的「眼睛」,很多機器人或小車結構都會利用這個感測器做避障功能,不過其實與其說是眼睛,不如說是「耳朵」,左下角標示的「T」是TX的意思,代表左邊的孔負責傳送(Transport)超音波,而右下角標示「R」是RX代表右側的耳朵負責接收(Receive)超音波回音,也就是左側是嘴巴負責發出聲音,而右側是耳朵負責聽回音,兩者缺一不可。

下方四個腳位則依序為VCCTrigEchoGND,其中Trig代表嘴巴,決定何時發出聲音,Echo則代表耳朵,用來計算聽到回音的時間,再透過公式就可以計算距離了,而VCCGND則與以往相同,接在5VGND腳位,這裡說明一下目前超音波有多個版本,有少數版本僅能使用5V,而大多數是5V3.3V都可用,因此個人建議接在5V的位置。

另外一個要注意的地方是超音波感測器可量測的範圍約在2cm~500cm之間,低於2cm則無法感測,超過500cm則會相當不準確,還有就是如果現場有多個超音波感測器同時作用,則會造成聲波之間的互相干擾,因此不要讓多個超音波同時進行測距。

本節我們就使用超音波感測器來製作倒車雷達,也就是說,利用超音波測量距離,並利用蜂鳴器發出聲音來指引駕駛,讓駕駛知道車子與障礙物之間的距離。不過我們先分別測試超音波與蜂鳴器是否正常,然後再將功能合併。

一、超音波測量距離

本部份我們先展示如何使用超音波模組進行距離測量,接線部份請參考圖

image

超音波距離測量

除了VCCGND之外,我們將Trig接在GPIO12(麵包版左側7),而Echo接在GPIO14(麵包版左側8),程式的概念則是在Trig發出一小段音波後,就在Echo等候回音回傳,若收到回音,則Echo腳位會發出高電位,因此我們測量Echo轉成高電位的時間,最後再利用公式換算即可。

本案例有兩個新的語法,delayMicrosecondspulseIn,分別介紹如下:

  • 暫停n微秒:delayMicroseconds(n);

之前我們常用的暫停是delay(1000),在delay內的數字是毫秒ms(MilliSeconds),也就是1/1000秒,因此delay(1000)是暫停1秒,但是若我們需要暫停時間比1/1000還小時,就要改用delayMicroseconds(n),而內部數字n代表的是微秒(百萬分之一秒),通常用來進行更精確測量,例如本次使用超音波測距,常溫下音速每秒約340公尺,若使用1/1000秒,誤差將會超過30cm,因此須改用百萬分之一秒為單位進行測量。範例:

delayMicroseconds(5);//暫停百萬分之5=5微秒

  • 計算腳位的收到符合電壓的時間差:pulseIn(腳位,電壓);

pulseIn就是用來計算時間,例如說當程式執行到pulseIn(14, HIGH);時,代表我們要詢問14號腳位何時收到高電位,以本例而言,當超音波模組收到回音時,就會將EchoHIGH,因此我們利用這個語法,就可以求得收到回音的時間,此語法所取得的時間值單位為微秒。範例:

EchoTime=pulseIn(14, HIGH);//計算14號腳位收到高電位的時間

了解本次的兩個新程式語法後,我們將程式完成如下:

 

 

int Trig =12;//發出聲波

int Echo =14;//接收聲波

void setup(){

  Serial.begin(115200);

  pinMode(Trig, OUTPUT);

  pinMode(Echo, INPUT);

}

 

void loop() {

  digitalWrite(Trig, LOW); //關閉

  delayMicroseconds(5);

  digitalWrite(Trig, HIGH);//啟動

  delayMicroseconds(10); 

  digitalWrite(Trig, LOW); //關閉

  float EchoTime = pulseIn(Echo, HIGH); //傳回時間

  float CMValue = EchoTime * 34 / 1000 / 2; //轉換成距離

  Serial.println(CMValue);

  delay(50);

}

 

loop內,我們先將trig關閉5微秒,然後開啟10微秒,之後就立即關閉,這個「關、開、關」的步驟的目的讓超音波模組初始化避免受到干擾,完成後之後便會發出一段超音波,接下來就是利用pulseIn計算收到回音的時間,最後再利用公式將時間轉換程距離即可。

CMValue = EchoTime * 34 / 1000 / 2

這裡的公式內的"34"是轉換成每1/1000秒,音速能跑約34公分,而除1000則是將百萬分之一秒轉成1/1000秒,最後再除2則是因為聲音去一次、回一次花了兩倍距離,除2就可以得到真實的距離。

下圖為本次計算的結果,使用者可以用手放在超音波模組的前方,並前後移動來觀測所獲得的距離。

image

二、倒車雷達

要完成倒車雷達就必須再安裝一個新的感測器,就是蜂鳴器Buzzer,蜂鳴器在我們日常生活中很常見,例如電腦開機時會嗶一聲,或者火災時超級大聲的警報也是一種蜂鳴器,目前市面上實驗用的蜂鳴器可分成兩種無源蜂鳴器及有源蜂鳴器,兩者的主要差異在於發出聲音的結構不同,此處所謂的無「源」或有「源」的源是指「電源」的意思,無源蜂鳴器是利用供電的頻率(PWM)來改變蜂鳴器的聲音,因為不須接VCC,因此被稱為無源,另一種有源蜂鳴器則是接上VCC就會叫,聲音頻率是固定的,兩種各有用途,而本例則是採用無源蜂鳴器。

有源及無源蜂鳴器兩者外觀上沒有差異,因此購買前請跟賣家確認規格,避免買錯材料。其外觀如下圖,一般上方可能會有一張貼紙,記得實驗前先用筆戳破中間的洞即可,若完全撕開可能會在發低音時破音,蜂鳴器有兩隻腳,有些蜂鳴器會透過長短腳來區分正負極(長正短負),如果您所購買的沒有分長短腳,可觀察正面會標示+的符號,也可區分正負極。

image

無源蜂鳴器外觀

要控制蜂鳴器發出的聲音就要使用到另外一個程式庫:ESP32Servo,這也是一個控制PWM的工具,除了要用來控制蜂鳴器之外,後續我們也會使用他控制伺服馬達Servo來模擬開門,請選擇上方功能表/草稿碼/匯入程式庫/管理程式庫,開啟程式庫管理員如下圖,在上方關鍵字處輸出"ESP32Servo",便可找到本程式庫,點選下方的安裝後,等候約一分鐘即可完成安裝。

image

程式庫管理員安裝ESP32Servo程式庫

 

程式庫安裝完畢後,我們先寫一個簡單能發出「小蜜蜂」音樂的程式進行聲音測試,在ESP32Servo中,控制蜂鳴器的語法是tone,說明如下

  • 發出一段時間的聲音:tone(pin, frequency, ms);

tone語法一共有三個參數,第一個是腳位pin,就是指蜂鳴器接在ESP32的哪一個腳位,第二個參數是frequency,則代表發出某個頻率的聲音,一般我們會用音樂的音階Do Re Mi來代表,關於音階與頻率之間的變換,可參考下表,例如中音Do頻率就是262Re就是294,而Me則是330,因此發出Do, Re, Mi各半秒鐘,其程式如下所示:

tone(pin, 262, 500);//發出Do

tone(pin, 294, 500);//發出Re

tone(pin, 330, 500);//發出Me

 

頻率音階對照表

音名

C

C#

D

D#

E

F

F#

G

G#

A

A#

B

音階

Do

 

Re

 

Mi

Fa

 

So

 

La

 

Si

低音

 

 

 

 

中音

 

 

 

 

 

 

高音

33

35

37

39

41

44

46

49

52

55

58

62

65

69

73

78

82

87

93

98

104

110

117

123

131

139

147

156

165

175

185

196

208

220

233

247

262

277

294

311

330

349

370

392

415

440

466

493

523

554

587

622

659

698

740

784

831

880

932

988

1046

1109

1175

1245

1319

1397

1480

1568

1661

1760

1864

1976

2093

2217

2349

2489

2637

2794

2960

3136

3322

3520

3729

3951

4186

4435

4699

4978

5274

5588

5920

6272

6645

7040

7459

7902

 

 

接下來我們將蜂鳴器接上ESP32,我們將蜂鳴器+腳接在GPIO 17,也就是麵包版右側編號9的位置,而另外一隻腳則接在GND的位置。

我們先透過一個簡單範例,發出小蜜蜂的第一段來檢查蜂鳴器是否正常,小蜜蜂的第一段為:

G E E -F D D -C D E FG G G -

 

 

#include <ESP32Servo.h>

int buzzer= 17;

void setup() {

  Serial.begin(115200);

}

 

void loop() {

  tone(buzzer, 392, 500);//G(So)

  tone(buzzer, 330, 500);//E(Me)

  tone(buzzer, 330, 500);//E(Me)

  delay(500);

  tone(buzzer, 349, 500);//F(Fa)

  tone(buzzer, 294, 500);//D(Re)

  tone(buzzer, 294, 500);//D(Re)

  delay(500);

  tone(buzzer, 262, 500);//C(Do)

  tone(buzzer, 294, 500);//D(Re)

  tone(buzzer, 330, 500);//E(Me)

  tone(buzzer, 349, 500);//F(Fa)

  tone(buzzer, 392, 500);//G(So)

  tone(buzzer, 392, 500);//G(So)

  tone(buzzer, 392, 500);//G(So)

  delay(3000);

}

 

上述程式測試成功後,我們則來整合超音波感測及蜂鳴器來製作倒車雷達,為了簡化實驗,我們將超音波所檢測的距離分成四種狀態

安全:100cm內無障礙物,不發出聲音

注意:距離100~50cm之間,發出低音Do提醒使用者

小心:距離50~10cm之間,發出中音Do提醒使用者

危險:距離100cm之間,發出高音Do提醒使用者

透過改變聲調來提醒使用者,音調越高代表障礙物越接近,可避免撞到造成造成損失。本部份的程式如下

 

 

#include <ESP32Servo.h>

int Trig = 12; //發出聲波

int Echo = 14; //接收聲波

int buzzer = 17;//蜂鳴器

void setup() {

  Serial.begin(115200);

  pinMode(Trig, OUTPUT);

  pinMode(Echo, INPUT);

  pinMode(buzzer, OUTPUT);

}

 

void loop() {

  //步驟1:使用超音波測量距離

  digitalWrite(Trig, LOW); //關閉

  delayMicroseconds(5);

  digitalWrite(Trig, HIGH);//啟動

  delayMicroseconds(10);

  digitalWrite(Trig, LOW); //關閉

  float EchoTime = pulseIn(Echo, HIGH); //傳回時間

  float CMValue = EchoTime * 34 / 1000 / 2; //轉換成距離

  Serial.println(CMValue);

  //步驟2:使用蜂鳴器發出指定聲音

  if (CMValue < 100 && CMValue >= 50) {

    tone(buzzer, 33, 100); //注意:發出低音Do

  }

  if (CMValue < 50 && CMValue >= 10) {

    tone(buzzer, 523, 100); //小心:發出中音Do

  }

  if (CMValue < 10) {

    tone(buzzer, 4186, 100); //危險:發出高音Do

  }

  delay(50);

}

 

除了改變高低音調提醒使用者之外,也可以利用距離改變發出聲音的間隔,例如距離比較遠時就每次嗶聲之間間隔較久,而很接近時,發出的嗶聲音較為緊湊,例如:

tone(buzzer, 4186, CMValue);

也就是發出的聲音間隔剛好是距離,此時很靠近時就可以發出幾乎連續的嗶聲,這也是另外一種常見的方式。

arrow
arrow

    夜市 小霸王 發表在 痞客邦 留言(0) 人氣()