如果可以遠端遙控單一輸出,那要擴成到多個就不是甚麼大問題了!在上一個範例中已經介紹過,使用”dweet.io”這個雲端網站去控制網際網路上ESP8266的單一輸出腳的方法,接下來就讓我們把輸出擴充到多個(在此設定為4個輸出點)。
本範例所使用的電路如下圖所示,使用的實驗模組板是標準的NodeMcu,圖中使用了D6、D7和D8這三根接腳,如果以標準的ESP8266來說這三隻接腳分別為:
D6:GPIO12
D7:GPIO15
D8:GPIO13
而這三根輸出接腳分別接上了一顆LED,當輸出為高態時會點亮LED
,這樣我們便可以觀察到接腳的輸狀態了。至於第4顆LED,則是沿用前一個範例的GPIO2這根接腳,不過要這隻腳的LED要低態才會點亮。這樣的混搭有兩個原因,一是可以讓使用者依需要決定用低態或是高態驅動輸出電路,二是ESP8266有些接腳在開機時的狀態必須是低態或是高態,否則可能會無法開機或是進入一些特別的模式,以致無法正常的動作,其中的GPIO15就是這樣的一隻腳,它在開機時必須為LOW,否則會開機失敗!
在之前ESP8266d8單機Soft-AP模式的文章中(網址如後:”http://musthtc100.blogspot.com/2020/05/ap-5-2-esp8266.html”),曾介紹過一塊型號為ESP-202的ESP8266延伸實驗開發板(如下圖所示),圖中標記2的部分是一顆RGB三色的LED模組,它們跟本範例電路一樣分別接到了:
紅(R):GPIO12
綠(G):GPIO15
藍(B):GPIO13
這三根接腳上,而且都是用高態輸出點亮LED。至於標記1的部分則是ESP8266其他可用的輸出腳,也都分別接上了一顆藍色的LED,不過這幾根腳都是用低態來點亮LED。如果手上有這塊實驗版的話,就可以直接套用在本範例上,不用再另外接實驗電路了!
以下是本實習的完整範例程式列表:
- // Libraries
- #include <ESP8266WiFi.h>
- const char* ssid = "yourSSID"; // 換成你的WiFi SSID名稱
- const char* password = "yourPassword"; // 換成你的WiFi 密碼
- /// Host
- const char* host = "dweet.io";
- String dweeting="GET /get/latest/dweet/for/%dweets% HTTP/1.1\r\nHost:
- dweet.io\r\nConnection: close\r\n\r\n";
- String myThing= "myDweetGetTest2"; // 在Dweet.io所使用的IOT物件名稱
- const byte LED_Pin=2;
- const byte LED1=12,LED2=13,LED3=15;
- void setup() {
- // Start Serial
- Serial.begin(115200);
- pinMode(LED_Pin,OUTPUT);
- pinMode(LED1,OUTPUT);
- pinMode(LED2,OUTPUT);
- pinMode(LED3,OUTPUT);
- delay(10);
- digitalWrite(LED_Pin,1);
- Serial.println();
- Serial.print("Connecting to ");
- Serial.println(ssid);
- WiFi.begin(ssid, password);
- while (WiFi.status() != WL_CONNECTED) {
- delay(500);
- Serial.print(".");
- }
- Serial.println("");
- Serial.print("WiFi connected : ");
- Serial.println(ssid);
- Serial.println("IP address: ");
- Serial.println(WiFi.localIP());
- Serial.println("");
- }
- void loop() {
- Serial.print("Connecting to ");
- Serial.print(host);
- Serial.println(".......");
- Serial.println();
- dweeting.replace("%dweets%",myThing);
- // Serial.println(dweeting);
- // Use WiFiClient class to create TCP connections
- WiFiClient client;
- const int httpPort = 80;
- if (!client.connect(host, httpPort)) {
- Serial.println("connection failed");
- return;
- }
- client.print(dweeting);
- delay(10);
- String payLoad="";
- Serial.println();
- Serial.println("[dweet.io Response:]");
- while (client.connected())
- {
- if (client.available())
- {
- String line = client.readStringUntil('\n');
- payLoad+=line;
- Serial.println(line);
- }
- }
- Serial.println();
- Serial.println("[dweet.io Response End!]");
- client.stop();
- Serial.println("\n[Disconnected]");
- Serial.println();
- String content=payLoad.substring(payLoad.indexOf(":{")+1,payLoad.indexOf("}")+1);
- Serial.print("你的Iot ==> ");
- Serial.println(content);
- Serial.println();
- content.toUpperCase();
- Serial.println(content);
- if(content.indexOf("LED\":\"ON") >= 0)
- {
- Serial.println("LED is on!");
- digitalWrite(LED_Pin,0);
- }
- if(content.indexOf("LED\":\"OFF") >= 0)
- {
- Serial.println("LED is off!");
- digitalWrite(LED_Pin,1);
- }
- if(content.indexOf("LED1\":\"ON") >= 0) {
- Serial.println("LED1 is on!");
- digitalWrite(LED1,1);
- }
- if(content.indexOf("LED1\":\"OFF") >= 0) {
- Serial.println("LED1 is off!");
- digitalWrite(LED1,0);
- }
- if(content.indexOf("LED2\":\"ON") >= 0) {
- Serial.println("LED2 is on!");
- digitalWrite(LED2,1);
- }
- if(content.indexOf("LED2\":\"OFF") >= 0) {
- Serial.println("LED2 is off!");
- digitalWrite(LED2,0);
- }
- if(content.indexOf("LED3\":\"ON") >= 0) {
- Serial.println("LED3 is on!");
- digitalWrite(LED3,1);
- }
- if(content.indexOf("LED3\":\"OFF") >= 0) {
- Serial.println("LED3 is off!");
- digitalWrite(LED3,0);
- }
- // Repeat every 10 seconds
- delay(5000);
- }
在本小節的範例程式中,在變數設定的部分和上一小節不同之處如下:
String myThing= "myDweetGetTest2"; // 在Dweet.io所使用的IOT物件名稱
const byte LED_Pin=2;
const byte LED1=12,LED2=13,LED3=15;
一是把上傳到Dweet.io的IOT物件名稱稍作修改(加了一個‘2’),以便和上一小節不同;二是新增三根輸出接腳,分別是GPIO12、13、15。當然在初始化(setup())程式區的地方就必須把這三隻接腳設定為輸出模式了!
pinMode(LED1,OUTPUT);
pinMode(LED2,OUTPUT);
pinMode(LED3,OUTPUT);
至於主迴圈(loop())程式區部分,和前一小節的差異在87~120行,也就是輸出控制指令從一組增加為四組,即增加了LED1~LED3這三隻接腳的測試與判斷,由於語法非常類似,在此就不多做贅述了。
if(content.indexOf("LED\":\"ON") >= 0)
{
Serial.println("LED is on!");
digitalWrite(LED_Pin,0);
}
if(content.indexOf("LED\":\"OFF") >= 0)
{
Serial.println("LED is off!");
digitalWrite(LED_Pin,1);
}
if(content.indexOf("LED1\":\"ON") >= 0) {
Serial.println("LED1 is on!");
digitalWrite(LED1,1);
}
if(content.indexOf("LED1\":\"OFF") >= 0) {
Serial.println("LED1 is off!");
digitalWrite(LED1,0);
}
if(content.indexOf("LED2\":\"ON") >= 0) {
Serial.println("LED2 is on!");
digitalWrite(LED2,1);
}
if(content.indexOf("LED2\":\"OFF") >= 0) {
Serial.println("LED2 is off!");
digitalWrite(LED2,0);
}
if(content.indexOf("LED3\":\"ON") >= 0) {
Serial.println("LED3 is on!");
digitalWrite(LED3,1);
}
if(content.indexOf("LED3\":\"OFF") >= 0) {
Serial.println("LED3 is off!");
digitalWrite(LED3,0);
}
下圖是使用Google Chrome測試的過程,其中標記1是在瀏覽器的網址欄一口氣輸入了四組輸出的控制指令,即”led=on&led1=on&led2=off&led3=off”,由其內容可以看出,這四組輸出的狀態為:
LED 🡪 On
LED1 🡪 On
LED2 🡪 Off
LED3 🡪 Off
而標記則3是從Arduino IDE監控視窗看到的提示訊息,其中包括原來的IoT指令,和由ESP8266所發出的輸出狀態訊息;其中最下方的訊息就是被控制的四根接腳上所連接LED的亮滅狀態,也就是上面指令所要控制的輸出狀態。
至於下圖四組輸出的控制指令為”led=off&led1=on&led2=on&led3=o”,四組輸出的狀態為:
LED 🡪 Off
LED1 🡪 On
LED2 🡪 On
LED3 🡪 On
而標記則3是從Arduino IDE監控視窗看到的提示訊息,四根接腳上所連接LED的亮滅狀態,和上面指令所要控制的輸出狀態吻合。
下圖是使用瀏覽器只輸出兩組輸出的控制指令的情形,即” led1=off&led2=off”,由其內容可以看出,這兩組輸出的狀態為:
LED1 🡪 Off
LED2 🡪 Off
而標記則2是從Arduino IDE監控視窗看到的提示訊息,其中最下方的訊息是被控制的兩根接腳上所連接LED的亮滅狀態,也就是說我們的系統可以分別且單獨的控制特定的輸出,不一定要同時控制全部輸出。
如果用前面介紹過使用AI2設計的Dweet.io雲端網站測試APP的話,其畫面與過程如下圖所示,在圖的右方是使用電腦AI2模擬器的畫面,我們先在最上方的IoT物件名稱文字盒中入"myDweetGetTest2"這個物件特徵名稱,然後在標記1的Dweet IoT物件指令輸入區輸入相關的指令,在此為:
“Led=on&led1=off&led2=on&led3=off”
然後按下【送出】按鈕,便可以把這一串共4個輸出端控制指令一次上傳到Dweet.io雲端網站;標記3是由Dweet.io雲端網站所回傳的上傳成功訊息。至於標記2則是ESP8266定時從Dweet.io雲端網站讀取控制指令後,所萃取出的IoT物件內容,也就是由主控端所發出控制指令;我們的ESP8266系統在測試這些輸出控制指令之後,便會讓對應的輸出腳開啟或關閉。
至於下圖則是只送出兩個輸出腳控制指令的情形。
在這個AI2的APP中,實際上增加了3個可單獨控制新增的輸出腳按鈕,為了節省螢幕的空間,三個按鈕是使用切換式的方式來控制輸出。以下圖來說,標記1的按鈕本來是顯示【SW1開】,當我們按下它之後,按鈕的文字會切換成【SW1關】,為了讓使用者知道正在執行的動作,APP會在下方標記2之處顯示「開啟SW1」的訊息。標記3一樣是ESP8266定時從Dweet.io雲端網站讀取控制指令後,所萃取出的控制指令。
至於下圖,標記1的按鈕本來是顯示【SW3關】,當我們按下它之後,按鈕的文字會切換成【SW3開】,同樣的APP會在下方標記2之處顯示「關閉SW3」的訊息。標記3是ESP8266從Dweet.io雲端網站讀取控制指令後,所萃取出的控制指令,最下方則是執行這個輸出指令(LED3=OFF)後的提示訊息。
如果想把這三個按鈕新增到之前的APP上的話,可照著下面的步驟進行;首先如下圖所示,先在AI2的螢幕布局設計(Designer)頁面中插空隙加入一個水平布局元件(HorizontalArrangement5),由於一般上傳的指令內容都不會太長,為了能看到更多的回應訊息,可以適當的把標記1這個文字輸入盒(txbDweets)的高度尺寸縮小,好讓最下面的回應訊息區能顯示更多的資料。此外這個水平布局元件的水平排列屬性設定為置中對齊,這樣接下來要放進去的的3個按鈕元件便可以以置中對齊的方式排列,讓畫面看起來比較美觀。
接著的步驟就是在這個水平布局元件中放上3個按鈕元件,在此它們的名稱分別為「btnSW1」~「btnSW3」,而按鈕上初始的顯示文字則為【SW1開】~【SW3開】,這樣APP螢幕版面的設計工作就完成了。
在手機螢幕上放好新增的3個按鈕元件後,接下來就是幫這些按鈕加上程式的方塊;下圖是「btnSW1」這個按鈕的方塊程式圖,同樣的程式一開始先檢查文字盒「txbIoTName」中的IoT物件名稱是否為空白﹖如果輸入是空白,則程式會由Notifier1送出短暫的警告訊息[不要忘了輸入IoT名稱!]。
接著檢查「btnSW1」這個按鈕上的顯示文字是否為【SW1開】﹖如果是代表按鈕現在應該執行的功能是開啟開關1這根接腳,此時程式會執行部分的功能;在此程式會先將要上傳到Dweet.io雲端網站的URL內容部份打包好,並設定給Web1這個元件的Url,接著把「btnSW1」這個按鈕上的顯示文字改為【SW1關】,最後在下方標記處顯示「開啟SW1」的提示訊息。
如果「btnSW1」這個按鈕上的顯示文字不是【SW1開】,那麼程式會執行部分的功能,也就是關閉開關1這根接腳;這部份的程式動作和前面的類似,只是由開啟改成關閉而已,當然按鈕本身的顯示文字也會改為【SW1開】。最後呼叫Web1的【Get】處理副程式,執行上傳到Dweet.io雲端網站的動作。
下面的程式方塊是這個AI2的APP中另外兩個按鈕的程式方塊圖,和上面的內容是一模一樣,差別只是在於所使用的元件號碼不一樣而已,請讀者自行參考。由於主控端和被控端的ESP8266中間隔著中介的Dweet.io雲端網站,再加上上傳和下載都會花一點時間,因此這些輸出控制動作是沒有辦法及時或很快的反應,所以每次動作之間必須保留適當的間隔時間才能正確的動作。
沒有留言:
張貼留言