作者:尤濬哲
藍芽與 WiFi 都是用來通訊的,藍芽通常用於近端點對點通訊,所謂的點對點就像是藍芽無線耳機與手機連接,用來播放音樂,又如藍芽滑鼠鍵盤功能是輸入文字,它只是一種序列通訊,功能較為簡單,而 WiFi 則常用來連入網際網路,相比之下 WiFi 需要比較複雜的設定,而藍芽只需配對就能取用服務。
與藍芽同位階的應該算是紅外線,不過紅外線有方向性,必須對準裝置才能傳輸,其速度慢不說,距離大概不能超過 10 公尺,而藍芽無方向性,因此不用對準,且傳輸距離遠,速度也比紅外線快很多。
本章先簡介 ESP32 的藍牙通訊設定與使用,由於它是藍芽內建的,所以不用接線或設定 AT COMMAND,也不用宣告 TXRX 相關的通訊協定,值得一提的是,而且它屬於低功率藍芽(BLE:Bluetooth Low Energy),耗電量較少外,傳輸距離理論可達 300 公尺遠,實際測試 30 公尺也沒問題,相對常見搭配 UNO 使用的 HC-05 屬於藍芽 2.1,理論傳輸距離只有 10 公尺。
藍芽單向傳輸
這邊會說明如何使用 ESP32 藍芽將資訊傳遞給藍芽裝置(手機)進行接收,另由於 bluetooth 函式庫與 iOS 手機不相容的原因,接下來都將使用 Android 裝置進行解說。
ESP32 藍芽的開啟僅需幾個步驟:
- 使用藍芽函式庫:#include <BluetoothSerial.h>
- 宣告藍芽序列通訊物件:BluetoothSerial BT;//BT 為藍芽通訊物件
- 在 Setup 中開啟藍芽:BT.begin(“BTName”);// BTName 為藍芽廣播名稱
- 當要傳輸資訊時:BT.print(“要傳輸的文字”);//println 則是換行
我們先來做一個簡單的測試,就是每秒傳輸一次「Hello World!」到手機中,程式如下:
#include <BluetoothSerial.h> BluetoothSerial BT;//宣告藍芽物件,名稱為BT void setup() { Serial.begin(115200); BT.begin("Eric1030");//請改名例如英文+生日,以免與其他同學名稱重複 } void loop() { BT.println("Hello World!"); delay(1000); }
完成程式上傳後,我們來處理手機的部份,請開啟 Android 手機的 App store,並搜尋 Arduino Bluetooth Control,其圖示如下,APP Store 有很多類似的 APP,功能也都差不多,但是我們選定的這個 APP 有提供語音辨識的功能;若無法找到該 APP,可能是版本不相容,但可以從我的雲端空間下載備份 APK 檔案。

Arduino Bluetooth Control(圖片來源:Google Play)
手機安裝好 APP 後,啟動藍芽連線設定,如果未在「可用裝置」中出現,請點選「不常用類型裝置」。

開啟藍芽設定(圖片來源:尤濬哲提供)
您就會看到您所設定的 ESP32 藍芽名稱,接著點選您的 ESP 裝置。

藍芽不常用裝置列表(圖片來源:尤濬哲提供)
接著會出現配對訊息,點選下方的配對即可完成配對。

開始配對(圖片來源:尤濬哲提供)
完成配對後,開啟剛剛安裝的 Arduino Bluetooth Control APP,如果沒有自動連線,請點選上方的箭頭圖示,選擇本次要連線的 ESP32 裝置。

開啟 APP 連線藍芽裝置(圖片來源:尤濬哲提供)
連線成功時,下方會出現「Connected to 裝置名稱」的訊息。

連線成功等候連線成功(圖片來源:尤濬哲提供)
此時再點選序列通訊的功能,即可看到每秒一次的「Hello World!」訊息。

點選右上序列通訊功能(圖片來源:尤濬哲提供)

觀察傳入的資訊(圖片來源:尤濬哲提供)
接下來我們將使用 DHT11 溫濕度計為範例,將溫濕度的值傳入手機中,另外記得每次 ESP32 更新程式重新啟動時,都必須按一下連線的圖示 ,重新與裝置建立連線,才能讀取資訊。
#include <SimpleDHT.h> #include <BluetoothSerial.h> BluetoothSerial BT; int pinDHT11 = 25; //本例請將溫度計S腳接在左11 (GPIO25) SimpleDHT11 dht11(pinDHT11); void setup() { Serial.begin(115200); BT.begin("Eric1030");//請改名 } void loop() { // start working... Serial.println("================================="); Serial.println("Sample DHT11..."); // read without samples. byte temperature = 0; byte humidity = 0; int err = SimpleDHTErrSuccess; if ((err = dht11.read(&temperature, &humidity, NULL)) != SimpleDHTErrSuccess) { Serial.print("Read DHT11 failed, err="); Serial.println(err); delay(1000); return; } //將溫濕度傳輸到藍芽裝置 BT.print((int)temperature); BT.print(" *C,"); BT.print((int)humidity); BT.println(" H"); delay(1000); //休息1秒 }

利用藍芽傳輸 DHT11 溫濕度(圖片來源:尤濬哲提供)
藍芽雙向傳輸
ESP32 能傳送資料到手機,那可以反過來讓手機傳資料到 ESP32 嗎?當然可以,而且更好玩!這部份 ESP32 的流程是:
1.檢測藍芽是否有資料:BT.available()
2.如果有資料,我們就把資料讀出:BT.readString()
3.將資料從電腦的序列視窗(Serial)中印出來
程式如下:
#include <BluetoothSerial.h> BluetoothSerial BT; void setup() { Serial.begin(115200); BT.begin("Eric1030");//請改名 } void loop() { //檢查藍芽內是否有資料 while (BT.available()) { //讀取藍芽資料 String BTdata=BT.readString(); //顯示在序列視窗 Serial.println(BTdata); } delay(1); }
連線成功後,一樣點選右上序列通訊功能後,在下方的空白處輸入文字並按鍵盤的 Done 或 Enter 送出,我們就能在電腦的序列通訊視窗中收到手機傳來的訊息。

在手機輸入訊息(圖片來源:尤濬哲提供)

ESP32 的序列視窗中讀取訊息(圖片來源:尤濬哲提供)
不過這樣單方面只有手機講話有點孤單,要怎麼讓 ESP32 也能打字回覆呢?其實語法很類似,只是與藍芽的方向相反,就是檢查序列是否有資料輸入 Serial.available();當 Serial.available() 用Serial.readString() 將資料讀入後,再用 BT.println() 將資料送到手機,不過 ESP32 要在哪裡打字呢?是透過序列通訊視窗上面的空白處,本部份程式如下:
#include <BluetoothSerial.h> BluetoothSerial BT; void setup() { Serial.begin(115200); BT.begin("Eric1030");//請改名 } void loop() { //檢查序列內是否有資料 while (Serial.available()) { //讀取序列資料 String Sdata = Serial.readString(); //傳輸給藍芽 BT.println(Sdata); } //檢查藍芽內是否有資料 while (BT.available()) { //讀取藍芽資料 String BTdata = BT.readString(); //顯示在序列視窗 Serial.println(BTdata); } delay(1); }

ESP32 在序列視窗輸入訊息(圖片來源:尤濬哲提供)

雙向資料傳輸(圖片來源:尤濬哲提供)
藍芽指令與語音辨識
這樣的程式只能用來藍芽聊天嗎?不,這其實已經足夠我們用來遙控一些東西囉!例如我們可以用簡單的 LED 燈測試,將 LED 依照前面的內容依序將綠黃紅放置在 GPIO 4,16,17(麵包板右 7,8,9)位置,接下來我們假設 ESP32 從藍芽接到傳來「1」時,就開啟綠 LED,而「2」代表關閉綠 LED,其餘雷同(「3」、「4」代表開啟及關閉黃 LED,「5」、「6」代表開啟及關閉紅 LED),這樣我們就可以用手機來遙控三個燈號了。完整程式如下:
#include <BluetoothSerial.h> BluetoothSerial BT; void setup() { Serial.begin(115200); BT.begin("Eric1030");//請改名 pinMode(15, OUTPUT); //綠色LED pinMode(2, OUTPUT); //黃色LED pinMode(4, OUTPUT); //紅色LED } void loop() { //檢查序列內是否有資料 while (Serial.available()) { //讀取序列資料 String Sdata = Serial.readString(); //傳輸給藍芽 BT.print(Sdata); } //檢查藍芽內是否有資料 while (BT.available()) { //讀取藍芽資料 String BTdata = BT.readString(); //顯示在序列視窗 Serial.println(BTdata); //檢查藍芽資料及相對的指令 if (BTdata == "1") { //1:開綠燈 digitalWrite(15, HIGH); } if (BTdata == "2") { //2:關綠燈 digitalWrite(15, LOW); } if (BTdata == "3") { //3:開黃燈 digitalWrite(2, HIGH); } if (BTdata == "4") { //4:關綠燈 digitalWrite(2, LOW); } if (BTdata == "5") { //5:開紅燈 digitalWrite(4, HIGH); } if (BTdata == "6") { //6:關紅燈 digitalWrite(4, LOW); } } delay(1); }
我們將數字 1~6 按過一次,會發現燈號依序亮起熄滅,代表藍芽傳輸正常。

輸入數字 1-6,查看燈號變化(圖片來源:尤濬哲提供)
除了使用序列通訊用自己打字的方式外,也可以使用 APP 上的其他功能。

APP上的所有功能(圖片來源:尤濬哲提供)
我們先來看看左側上方的方向鍵,當我們點選不同方向時,會發現每個方向對應的都是一個數字(如圖17)

方向鍵功能(圖片來源:尤濬哲提供)
因此按下不同方向,剛好可以控制燈號,例如「^」對應數字「1」,所以按「^」就會開啟綠燈(在按鈕時,請記得慢慢按不要太急,否則它會將很多數字合成一個字串才送出,例如一直按往上「^」會送出「11111」,而我們的程式無法判讀這個東西,因為我們是用字串比對,而非字元比對)。
在加速器上,對應的方向與上面的方向鍵是相同的,不過它是透過手機的傾斜方向來控制送出訊號,例如你將手機向前傾斜一秒鐘後復原水平狀態,手機會對 ESP32 送出一連串的「11111111」,向後則會送出「2222222」等,但有些手機硬體沒有支援加速器,就不會送出任何資料;與上面相同的,我們的程式是以字串比對,所以這個功能無法控制燈號。

加速器功能(透過傾斜你的手機來觸發)(圖片來源:尤濬哲提供)

接收到的資料(圖片來源:尤濬哲提供)
按鈕的功能如下圖,不過這個 APP 有一個小 bug,就是 5、6 是標錯的,預設標成 4、4,因此我們要進入設定進行修改。

按鈕的功能(圖片來源:尤濬哲提供)
點選右上機器人圖示按鈕進入設定功能,尋找「Command button configuration」,點選 Button E,然後修改對應的值從 4 改為 5,相同的步驟,請設定 Button F 對應的值為 6,完成修改後,依序點選按鈕,也可以觀察到燈號的變化。

將 Button E 改為 5(圖片來源:尤濬哲提供)
最後是右下角的功能語音指令(Voice Control),也就是透過語音辨識來控制傳輸,不過我們必須先設定語音及所對應的文字,例如當我們說「開綠燈」,手機就送出「1」到 ESP32,而根據判斷 ESP32 獲得 1 就會開啟綠色 LED。
我們先點選右上角的機器人圖示來設定語音指令,進入設定後往下拉到底,可以找到「Vocal Command Configuration」的功能。

設定語音指令(圖片來源:尤濬哲提供)
進入設定畫面後,該 APP 一共提供 10 個語音指令。

一共有 10 組語音指令(圖片來源:尤濬哲提供)
設定方式如下,我們點選第一個語音指令「Vocal Command no 1」後,一共有兩個值要設定,第一個 Vocal command 代表要講的話,第二個 Data to send 則是要在藍芽發送的文字;舉例來說,要講的話就是「開綠燈」,而要在藍芽發送的文字則是「1」,這樣當手機聽到我們講「開綠燈」時,就會發送 1 到 ESP32,而依據程式的判斷,收到 1 就會開啟綠燈。

設定語音命令為「開綠燈」(圖片來源:尤濬哲提供)

設定要送出的文字「1」(圖片來源:尤濬哲提供)
其餘的語音指令則可以依照相同的方式設定,例如「Vocal Command no 2」的 Vocal command 設定為「關綠燈」、Data to send 設定為「2」,而「Vocal Command no 3」的 Vocal command 設定為「開黃燈」、Data to send 設定為「3」等。
接下來我們就可以利用手機語音辨識的功能來控制燈號開關。回到 APP 首頁畫面後,點選右下角的「Voice Control」語音按鈕就會跳出麥克風圖示,點選麥克風後,說出設定好的語音指令,例如「開綠燈」,在手機辨識「開綠燈」成功後,就會在藍芽送出「1」給 ESP32,ESP32 就會開啟綠燈。

點選右下角的 Voice Control(圖片來源:尤濬哲提供)
小結
本練習只運用 ESP32 的藍牙通訊來開啟或關閉 LED,是有點大材小用,但讀者可以自行開發新功能,例如透過繼電器來開啟或關閉電風扇、檯燈、冷氣等家電,達到簡易的智慧家電的功能,以下影片是之前做過的作品。
(本文經作者同意轉載自夜市小霸王部落格、原文連結;責任編輯:賴佩萱)
- 舊瓶裝新酒還是新瓶裝舊酒?Jetson Orin Super效能實測 - 2025/03/12
- 低成本空氣品質感測器 – 夏普 GP2Y10開箱實驗 - 2023/03/16
- 【ESP32專欄】ESP32 MQTT與深度睡眠 - 2022/06/20
訂閱MakerPRO知識充電報
與40000位開發者一同掌握科技創新的技術資訊!