[Arduino][ESP8266]
ESP8266 Event-Driven & Callback Method
前言
在前篇” ESP8266 開發指南 – 軟體架構篇” 的文章末段,我針對ESP8266提出了
3點結論及4點撰寫程式碼( Coding ) 的建議,其目的就是告訴大家請用
“ callback function” 以及 “ event-driven”來撰寫ESP8266的程式碼。
所以,這篇文章就讓我來說明 “ Event-Driven Method”。
ESP8266 的Event-Driven & Callback Method
Event-driven 有各種作法,常見的有:
- Flag 機制 : 就是透過設定Flag 來傳達 Event,這種做法一般多用在super-loop 的程式架構。
- Event -Task : 這做法是架構在RTOS ,也就是透過Event的傳遞,來做到工作分派及Task的切換。
- Event-Callback : 這做法是透過註冊 Callback function 來傳遞 Event,但這做法必須結合 (借助) 第一或第二做法。
ESP8266 的核心雖然可以處理3個Task,但WiFi-MAC, Timer Task以及User_Task
至少使用掉2個,所以,使用者能使用event-driven的方法就剩第一及第三的做法。
以下是我建議使用event-driven的流程:
Step1: 註冊 Callback function。
Step2: 透過Callback function 傳遞來的Event,然後設定Flag,或直接在Callback 處理(註1)。
Step3: 在User_Task (也就loop()迴圈) 判斷Flag狀態,適時機處理Event。
註1: 程式碼短小為佳,避免影響Task scheduling。
整個運作流程就如下圖所示:
範例:WiFi Event
瞭解了 ESP8266 event-driven 的做法後,這章節就讓我以實際的程式碼來做說明。
底下的程式碼是來自ESP8266內建的 WiFiEvent 範例,但是為了好說明,我修改了
部分的程式碼。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- #include
- #include
-
- const char* ssid = "esp8266";
- const char* password = "12345678";
-
- WiFiEventHandler stationConnectedHandler;
- WiFiEventHandler stationDisconnectedHandler;
-
- bool blinkFlag;
-
- void setup() {
-
- Serial.begin(115200);
- pinMode(LED_BUILTIN, OUTPUT);
- digitalWrite(LED_BUILTIN, HIGH);
- blinkFlag = false;
-
-
- WiFi.persistent(false);
-
-
- WiFi.mode(WIFI_AP);
- WiFi.softAP(ssid, password);
-
-
-
-
- stationConnectedHandler = WiFi.onSoftAPModeStationConnected(&onStationConnected);
-
-
- stationDisconnectedHandler = WiFi.onSoftAPModeStationDisconnected(&onStationDisconnected);
- }
-
- void onStationConnected(const WiFiEventSoftAPModeStationConnected& evt) {
- Serial.print("Station connected: ");
- Serial.println(macToString(evt.mac));
-
- blinkFlag = true;
- }
-
- void onStationDisconnected(const WiFiEventSoftAPModeStationDisconnected& evt) {
- Serial.print("Station disconnected: ");
- Serial.println(macToString(evt.mac));
- blinkFlag = true;
- }
-
- void loop() {
- if (blinkFlag) {
-
- blinkFlag = false;
- digitalWrite(LED_BUILTIN, LOW);
- delay(200);
- digitalWrite(LED_BUILTIN, HIGH);
- delay(200);
- digitalWrite(LED_BUILTIN, LOW);
- delay(200);
- digitalWrite(LED_BUILTIN, HIGH);
- }
- }
-
- String macToString(const unsigned char* mac) {
- char buf[20];
- snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
- mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
- return String(buf);
- }
-
程式碼說明:
Line 16 : 為了使用ESP8266 WiFi Classes ,必須 include WiFi Library – ESP8266WiFi.h
Line 19, 20 : 在這範例裡,ESP8266會被設定成 AP mode (Access-Point),
這兩行是設定這AP 的名稱 (ssid) 及他的連接密碼 (password)
Line 22 : 宣告一個 WiFi class 的 Event Handler 名為”stationConnectdHandler”
Line 44 : 則是註冊 stationConnectdHandler 為onSoftAPModeStationConnected()
函數的event handler,他的callback function 為 onStationConnected()
Line 22 及 Line 44 就是我在前面提到的 Step1: 註冊 Callback function
Line 23, 47 : 相同於 Line 22, 44,差異只是在一個是 connected 的 event handler /
callback function, 另一個是disconnected 的 event handler / callback function
Line 25 : 宣告一個LED blink 的旗標,作為 LED 是否要閃爍的依據
Line 29 : 設定UART baudrate 為115200bps
Line 30~32 : 設定LED及旗標的初始狀態
Line 38, 39:設定ESP8266為 AP mode以及他的AP名稱 (ssid)和密碼 (password)
Line 50~55 : Connected 的callback function,也就是當有裝置連結上這AP時,
WiFi-MAC就會呼叫onStationConnected()這個函數,在這函數中只是簡單的列印
出連接上的裝置 mac address 以及設定blinkFlag 為 true
Line 50 ~ Line 55 就是我在前面提到的 Step2 : 透過Callback function 傳遞來的
Event,然後設定Flag
Line 63~75 : loop() 函數,也就是User-Task的主程式,程式中就是簡單的判斷blinkFlag ,
若為true ,LED閃兩次,然後清掉旗標。
Line 63 ~ Line 75 就是我在前面提到的 Step3 : 在User_Task判斷Flag狀態,
適時機處理Event
Why use Event-Driven
瞭解了 ESP8266 event-driven 的做法,也看完了實際範例的說明,
想必大家會使用了吧!? 若有疑問或哪裡要加強說明,請留言給我。
另外,這時候你或許會問我底下這問題,
”若我不用event-driven 或 callback function 來寫ESP8266的程式碼,不行嗎? “
我的答案是 “ 可以的”,
但我也必須告訴你一個事實,就是你的ESP8266再呼叫WiFi Classes時 ,
CPU會一直在做虛功,這會讓你覺得ESP8266跑不動你的程式碼,
或甚至你會覺得你要換顆更強的CPU 了,例如雙核的ESP32 !
下一篇,就讓我以實際範例來告訴你這個事實吧 !
敬請期待!!!
延伸閱讀