# 第13週- IoT 無線遠距控制 ###### tags: `Bluetooth` `BLE` `IoT` `遠距控制` 終於到了遙控 ESP32 IoT 的課程,可以開始遠距讀取並控制 ESP32 的數值和動作。 ## 遠距控制的方式: **1) 紅外線** [(第12週課程)](https://hackmd.io/@smile2307/H1AzS7he3) * ESP32 至少需加裝 1838B 紅外線發射接收器 * 傳輸速度與距離成反比,最快 16Mbps * 工作功率極低,但容易被阻擋 * 較便宜 * 需額外的紅外線遙控器 ![](https://hackmd.io/_uploads/BJ6kpFnrh.png) **2) 藍牙**(第13週課程) * ESP32 已內含BLE硬體,並具有天線 * 傳輸頻寬為 1Mbps * 工作功率低,但ISM頻段 2.4GHz 容易受干擾 * 較貴 * 需藍牙連線的控制設備,如手機當 host 並配對 ![](https://hackmd.io/_uploads/BJmKaFhr2.png) **3) WiFi網路**(第14、15週課程) * ESP32 已內含WiFi硬體,並具有天線 * 傳輸頻寬為 1-11Mbps(2.4GHz)/1-500Mbps(5GHz) * 工作功率較高,使用 ISM 頻段中的 2.4G/5GHz 雙頻 * 較貴 * 可以當成是工作站或熱點、或兩者同時,構成 IoT 普通採用的行動隨意網路 (MANET, Mobile ad‐hoc network) 或無線隨意網路 (WANET, Wireless ad‐hoc network) * 可以證書方式認證並加密 ![](https://hackmd.io/_uploads/BkCGAY2r2.png) ## ESP32 藍牙實作: ### 實作一: 啟動 ESP32 藍牙功能 >1. 依課本 p.86 的硬體需求 >1. 依課本 p.87,上傳程式 >1. 需一部 Android 手機,並下戴安裝 "Arduino Bluetooth Control" >1. Android 手機需先開藍牙設定、開啟、配對新裝置 >1. 依 p.89 所示,連接 ESP32 藍牙裝置 :::warning hint: BluetoothSerial 宣告為 BT,BT.begin() 和 BT.println() :::spoiler ```javascript= #include <BluetoothSerial.h> BluetoothSerial BT;//宣告藍芽物件,名稱為BT void setup() { Serial.begin(115200); BT.begin("");//請改名 } void loop() { BT.println("Hello World!"); delay(1000); } ``` ::: :::success 觀察:當打開 App terminal 後,連續收到 "Hello World"。 ::: ### 實作二::wink:延伸整合題 ESP32 透過藍牙將溫濕度數值,向手機傳送 >1. 增加 DHT11 硬體,訊號線接 GPIO 4 >1. 依課本 p.91,上傳程式 >1. App 連接 ESP32 藍牙裝置 :::warning hint: 將 DHT11 練習的 Serial.println() 改為 BT.println() :::spoiler ```javascript= #include <SimpleDHT.h> #include <BluetoothSerial.h> BluetoothSerial BT; int pinDHT11 = 4; //本例請將溫度計S腳接在GPIO 4 SimpleDHT11 dht11(pinDHT11); void setup() { Serial.begin(115200); BT.begin("");//請改名 } 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秒 } ``` ::: :::success 觀察:當打開 App terminal 後,連續收到溫濕度數值。 ::: :::info 已經擺脫 LCD 液晶顯示幕,可以遠距觀察環境即時變化。 ::: ### 實作三: 手機透過藍牙,反向對 ESP32 遠距傳輸 >1. 依課本 p.93,上傳程式 >1. App 連接 ESP32 藍牙裝置 :::warning hint: BT.readString() :::spoiler ```javascript= #include <BluetoothSerial.h> BluetoothSerial BT; void setup() { Serial.begin(115200); BT.begin("");//請改名 } void loop() { //檢查藍芽內是否有資料 while (BT.available()) { //讀取藍芽資料 String BTdata=BT.readString(); //顯示在序列視窗 Serial.println(BTdata); } delay(1); } ``` ::: :::success 觀察:當在 App terminal 輸入後,電腦連續收到手機的訊息。 ::: ### 實作四: 透過藍牙,手機和 ESP32 雙向溝通 >1. 依課本 p.94,上傳程式 >1. App 連接 ESP32 藍牙裝置 :::warning hint: Serial.readString() 和 BT.readString() :::spoiler ```javascript= #include <BluetoothSerial.h> BluetoothSerial BT; void setup() { Serial.begin(115200); BT.begin("");//請改名 } void loop() { //檢查序列監控視窗是否有輸入資料 while (Serial.available()) { //讀取序列資料 String Sdata = Serial.readString(); //傳輸給藍芽 BT.println(Sdata); //顯示在序列視窗 Serial.println(Sdata); } //檢查藍芽內是否有資料 while (BT.available()) { //讀取藍芽資料 String BTdata = BT.readString(); //顯示在序列視窗 Serial.println(BTdata); } delay(1); } ``` ::: :::success 觀察:同時在 App terminal 和手機App看到雙向訊息。 ::: ### 實作五: 透過手機藍牙向 ESP32 傳送控制指令 >1. 將綠、黃、紅 LED 分別連接至GPIO 15、2、4 位置 >1. 依課本 p.95,上傳程式 >1. App 連接 ESP32 藍牙裝置 >1. 在 App terminal 輸入數字 :::warning :::spoiler ```javascript= #include <BluetoothSerial.h> BluetoothSerial BT; void setup() { Serial.begin(115200); BT.begin("");//請改名 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); //檢查藍芽資料及相對的指令 //接收到"1":開綠燈 if (BTdata == "1") { digitalWrite(15, HIGH); } //接收到"2":關綠燈 if (BTdata == "2") { digitalWrite(15, LOW); } //接收到"3":開黃燈 if (BTdata == "3") { digitalWrite(2, HIGH); } //接收到"4":關黃燈 if (BTdata == "4") { digitalWrite(2, LOW); } //接收到"5":開紅燈 if (BTdata == "5") { digitalWrite(4, HIGH); } //接收到"6":關紅燈 if (BTdata == "6") { digitalWrite(4, LOW); } } delay(1); } ``` ::: :::success 觀察:輸入數字1~6後,查看燈號變化 現在可以手機藍牙遠距手動控制燈號了。 ::: ### 實作六: 透過設定語音指令,以語音向 ESP32 傳送控制指令 >1. 依課本 p.100,輸入語音指令 >1. App 連接 ESP32 藍牙裝置 >1. 對手機 App 麥克風說話 :::success 觀察:當語音指令正確接受後,查看燈號變化 ::: ## :bulb:程式語法思考題 如何同時使用手機 App 和 電腦序列視窗,雙向輸入控制指令? :::warning 建議:是否該去理解C/C++的程式語言? ::: ### 思考題 參考程式 :::success hint: 以 char 宣告 Serial 讀取字串, char 讀 'x', String 讀 "xx" [參考 ~[C語言_01]字元陣列,字串傻傻分不清楚?by_Andy_Cheng~](https://medium.com/andy的趣味程式練功坊/c語言-01-字元陣列-字串傻傻分不清楚-45089f69f6be) :::spoiler ### 思考題 參考程式(一) ```javascript= #include <BluetoothSerial.h> BluetoothSerial BT; char Sdata; void setup() { Serial.begin(115200); BT.begin("");//請改名 pinMode(15, OUTPUT); //綠LED, pin#15 pinMode(2, OUTPUT); //黃LED, pin#2 pinMode(4, OUTPUT); //紅LED, pin#4 } void loop() { while (Serial.available()>0) { //讀取序列資列 Sdata = Serial.read(); Serial.print(Sdata); if (Sdata == '1') {digitalWrite(15,HIGH);} if (Sdata == '2') {digitalWrite(15,LOW);} if (Sdata == '3') {digitalWrite(2,HIGH);} if (Sdata == '4') {digitalWrite(2,LOW);} if (Sdata == '5') {digitalWrite(4,HIGH);} if (Sdata == '6') {digitalWrite(4,LOW);} //傳輸給藍牙 BT.print(Sdata); } delay(1); //檢查藍牙內是否有資料 while (BT.available()) { //讀取藍牙資料 String BTdata=BT.readString(); //顯示在序列視窗 Serial.println(BTdata); //檢查藍牙資料及相對的指示 if (BTdata == "1") {digitalWrite(15,HIGH);} if (BTdata == "2") {digitalWrite(15,LOW);} if (BTdata == "3") {digitalWrite(2,HIGH);} if (BTdata == "4") {digitalWrite(2,LOW);} if (BTdata == "5") {digitalWrite(4,HIGH);} if (BTdata == "6") {digitalWrite(4,LOW);} } delay(1); } ``` ::: :::success hint: 讀取序列字串 Serial.readStringUntil(),Terminal 輸出以 '\n' 結尾 :::spoiler ### 思考題 參考程式(二) ```javascript= #include <BluetoothSerial.h> BluetoothSerial BT; void setup() { Serial.begin(115200); BT.begin("");//請改名 pinMode(15, OUTPUT); //綠LED, pin#15 pinMode(2, OUTPUT); //黃LED, pin#2 pinMode(4, OUTPUT); //紅LED, pin#4 } void loop() { while (Serial.available()) { //讀取序列資列 String Sdata = Serial.readStringUntil('\n'); Serial.println(Sdata); if (Sdata == "1") {digitalWrite(15,HIGH);} if (Sdata == "2") {digitalWrite(15,LOW);} if (Sdata == "3") {digitalWrite(2,HIGH);} if (Sdata == "4") {digitalWrite(2,LOW);} if (Sdata == "5") {digitalWrite(4,HIGH);} if (Sdata == "6") {digitalWrite(4,LOW);} //傳輸給藍牙 BT.print(Sdata); } delay(1); //檢查藍牙內是否有資料 while (BT.available()) { //讀取藍牙資料 String BTdata=BT.readString(); //顯示在序列視窗 Serial.println(BTdata); //檢查藍牙資料及相對的指示 if (BTdata == "1") {digitalWrite(15,HIGH);} if (BTdata == "2") {digitalWrite(15,LOW);} if (BTdata == "3") {digitalWrite(2,HIGH);} if (BTdata == "4") {digitalWrite(2,LOW);} if (BTdata == "5") {digitalWrite(4,HIGH);} if (BTdata == "6") {digitalWrite(4,LOW);} } delay(1); } ``` ::: :::success hint: 以自建函式庫 function :::spoiler ### 思考題 參考程式(三) ```javascript= #include <BluetoothSerial.h> BluetoothSerial BT; void setup() { Serial.begin(115200); BT.begin("");//請改名 pinMode(15, OUTPUT); //綠LED, pin#15 pinMode(2, OUTPUT); //黃LED, pin#2 pinMode(4, OUTPUT); //紅LED, pin#4 } void loop() { while (Serial.available()) { //讀取序列資列 String Sdata = Serial.readStringUntil('\n'); Serial.println(Sdata); //檢查藍牙資料及相對的指示 judgeled(Sdata); //傳輸給藍牙 BT.print(Sdata); } delay(1); //檢查藍芽內是否有資料 while (BT.available()) { //讀取藍芽資料 String BTdata=BT.readString(); //顯示在序列視窗 Serial.println(BTdata); //檢查藍牙資料及相對的指示 judgeled(BTdata); } delay(1); } void judgeled(String input) { if (input == "1") {digitalWrite(15,HIGH);} if (input == "2") {digitalWrite(15,LOW);} if (input == "3") {digitalWrite(2,HIGH);} if (input == "4") {digitalWrite(2,LOW);} if (input == "5") {digitalWrite(4,HIGH);} if (input == "6") {digitalWrite(4,LOW);} } ``` ::: ## :wink:自主練習題 如何以語音啟動三種不同亮燈模式的 WS2812? >閃綠圈 >閃黃圈 >閃紅圈 > ## 參考資料 >1)IOT物聯網應用第七章 – 尤濬哲(夜市小霸王) 編著 >2)[Infrared Remote & Receiver Module](https://www.jsumo.com/infrared-remote-receiver-module) >3)[ESP32 Bluetooth Low Energy By Fernando Koyanagi in Circuits](https://www.instructables.com/ESP32-Bluetooth-Low-Energy/) >4)[MANET Network in Internet of Things System WRITTEN BY Rasa Bruzgiene, Lina Narbutaite and Tomas Adomkus](https://www.intechopen.com/chapters/53178) >5) [[C語言_01] 字元陣列,字串傻傻分不清楚?by Andy Cheng](https://medium.com/andy的趣味程式練功坊/c語言-01-字元陣列-字串傻傻分不清楚-45089f69f6be)