網頁最後修改時間:2019/04/04
在這篇網頁中,我們會利用手機作為人機介面並與 ESP8266 做 Wi-Fi 通訊,負責傳送 LED 樣式或流星燈色,讓 ESP8266 控制 WS2812 完成不同 LED 燈光變化的效果。
*********************************************************************************
網頁中用到的零件可到下面網址購買:
- ESP8266 ESP01/01S WS2812 單線式全彩(RGB)LED (控制底板)模組
- V2.1 版 { 萬物皆聯網-ESP8266 IoT(Internet of Things)入門學習套件 }
- ( 5 片一標 ) WS2812B 焊接電路板- [單線式通訊] 內置 WS2811 晶片並整合 RGB LED 一體全彩驅動
- (5 片一標) WS2812B 黑色焊接電路板-[單線式通訊] 內置 WS2811晶片並整合 RGB LED 一體全彩驅動
【展示影片】
透過影片中的展示可以很清楚的看到,每個功能選擇後 LED 所展現的亮燈效果。
** NOTE **
影片中所出現的 Alert 提示視窗,表示 ESP8266 有收到手機所送出去的資料且執行之後返回的訊息;如果沒有出現這視窗,表示手機所送出去的資料沒有被 ESP8266 收到,這是故意為之寫在手機端程式裡面的。
【檔案下載】
展示影片使用的手機 APP 與韌體檔案可至下面連結下載:
- 手機 APP(Android)下載
手機 "安全性" 要開啟 允許安裝來源不明的應用程式 - ESP8266/ESP8285 韌體(燒錄地址:0x00000)
建議使用 flash download tools 燒錄韌體
/*-/--*-*/*/*/*/***//-*-*-**-*/*-*-/*/*/*-*-/-////--/**/**--**/--///--//**----**//--**//**----***//*-**//*
如果使用 flash download tool 燒錄出現問題,可查看另一個視窗是否出現下面的訊息:
/*-/--*-*/*/*/*/***//-*-*-**-*/*-*-/*/*/*-*-/-////--/**/**--**/--///--//**----**//--**//**----***//*-**//*
如果使用 flash download tool 燒錄出現問題,可查看另一個視窗是否出現下面的訊息:
[ERROR]: ESP8266 Chip efuse check error esp_check_mac_efuse.可試著使用下面的指令進行燒錄(系統內要有 python 2.7 和 esptool)
$> pip install esptool
$> esptool.py -p com8 -b 921600 write_flash 0x0 esp01-dio-512k64.bin其中,com8 是要指定的 COM Port 號碼;921600 是燒錄的速度(這是套件中燒錄底板所用的速度,請依實際使用的硬體做調整);esp01-dio-512k64.bin 是燒錄的檔案。至於其他的,esptool 會自己偵測目標的設定。
/*-/--*-*/*/*/*/***//-*-*-**-*/*-*-/*/*/*-*-/-////--/**/**--**/--///--//**----**//--**//**----***//*-**//*
ESP8266 Core for Arduino 編譯的版本使用的是 V2.5.0,需要的函式庫名稱與版本:
- V3.2.6, FastLED
- V1.2.0, ESPAsyncTCP
- V1.2.0, ESP Async WebServer
- V0.20, ESPAsyncWiFiManager
【接線說明】
WS2812 與 ESP8266 的接線很簡單,只需要一根資料通訊接腳就能完成整串 LED 燈的樣式變化控制;在這個例子選用的是 <GPIO2> ,可適用於 ESP8266 的任何模組型式。
參考電路圖 |
* 電源問題:
當 ESP8266 外接耗電量大的週邊時,若是沒有處理好電源的問題,那麼動作出現不正常的時候,即便選項是二選一,也是很難抓到癥結點所在。因此,適量的減少 LED 燈數量來進行動作的驗證是個比較好的選擇!待通過後,再一次使用全部的 LED 做測試,很容易在電源問題出現時得知問題的癥結所在;要不然,一但錯誤的懷疑是程式時出問題時,就麻煩了!
電路圖使用的圓環有 16 顆 LED 燈(仔細看是 6-pin 的 WS2812,不是 4-pin 的 WS2812B,但兩者通訊協議是一樣的),每一顆最大耗電量為 60mA @ 5V,因此至少要能提供 960mA 的電源輸入才行。
為了方便展示,我使用麵包板電源供應模組接了一個 5V/2A 的電源作為輸入供給 LED 圓環電源。若看倌的電源不能提供足夠的電流,那麼不是減少程式中 NUM_LEDS 的數量,就是減少實體 LED 的數量,來達到電路中需要的電流需求。
/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
* 實際接線照片:
下面給出兩種實際作為測試與接線的照片,看倌可依照照片中的接線方式進行實際配置。
** 第一種:燒錄與測試接線 **
使用下面這種接線方式,程式撰寫好,馬上燒錄、馬上測試,但需要注意的是,LED 圓環的電源要比 ESP8266 先開啟再插上 USB 通訊/燒錄底座到電腦上,否則 ESP8266 會無法動作和燒錄。但像照片中這樣開啟之後,可以直接重置 ESP826 也不會有任何問題,這一點需要記住!
若是不清楚上面所說的,燒錄的時候拔掉 <GPIO2> 接線就不需要注意上面的問題;待燒錄完成後斷電再插上<GPIO2> 就可進行測試。
ESP8266 + WS2812 實際燒錄與測試接線照片 |
WS2812 閃爍樣式測試-A-01 |
展示影片是使用這種接線方式,有幾個部分要特別提出來說明一下:
中間使用的是套件 V2.1 版本的轉接底板,不管是 ESP-01/ ESP-01S 插上都可直接且正常使用。
若是使用 V2.0 的轉接底板,ESP-01 需要另外把 <RST> 和 <EN>(<CH_PD>)接至 <VCC>,但 ESP-01S 插上就能直接使用。
ESP8266 + WS2812 實際測試與展示影片中使用的接線方式的照片 |
WS2812 閃爍樣式測試-B-01 |
WS2812 閃爍樣式測試-B-02 |
WS2812 閃爍樣式測試-B-03 |
程式架構示意圖 |
如上圖所示,程式主要分為手機端以及 ESP 裝置端,兩者經由無線網路以 HTTP GET 互相傳遞資料。
ESP 裝置端啟動後會自動以上次儲存的 WiFi SSID 名稱與密碼進行連線,如果不成功,則會切換進入到 AP 模式,此時利用手機加入到 espws2812 的 AP 名稱下(連線密碼:123456789),打開網頁連線到 http://192.168.4.1 就能進行無線網路的設置,預設手機端與 ESP 裝置端都是連線到同一個 AP 後再互相通訊,而不是透過連線到 ESP 裝置端的 AP 再進行通訊。
一但手機端與 ESP 裝置端同時加入到同一個 AP 後,第一個步驟就是要在手機端設定好 ESP 裝置端的 IP 地址,之後就能在其他畫面開始遠端操作 ESP 裝置端的 WS2812 LED 燈的樣式效果,或是選擇流星燈色。
/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
* 手機端 APP GUI :
操作的手機軟體檔案大概 2 點多 MB,安裝後打開可看到如下的四個畫面。
手機端 APP 畫面 |
- 連線設定
用來設定 ESP 裝置端的 IP 地址。 - 燈變化樣式
LED 閃爍樣式列表,有七種(包括關閉 LED 燈),利用 HTTP GET 發送操作者的選擇。 - 流星燈色環
進入到此一畫面,操作者可以利用色環來選擇想要的流星燈顏色,在色環上按下選擇顏色後釋放,會以 HTTP GET 發送操作者的選擇。按下滑動的同時,色環右邊會出現此時滑動到的顏色。而釋放後,上方不但會顯示出選擇的顏色,也會將顏色碼以 16 進制的方式顯示出來。
/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
* HTTP GET 參數:
資料傳送的參數格式依據畫面不同而採用不同參數,如下所述。
** 燈變化樣式:
<ip>/sendstyle?style=## :表示選擇的樣式代表號碼,不可為零,從 1 開始計數,對應到 ESP 裝置端的樣式表。
** 流星燈色環:
<ip>/sendstyle?color=############:000000 ~ ffffff,代表 16 進位,前面不需要再加 0x。
利用這樣的方式,即便沒有手機 APP 也可以使用瀏灠器直接測試或是操作。
例如,
192.168.11.9/sendstyle?style=1表示選擇 "rainbow" 的閃爍效果。
192.168.11.6/sendstyle?style=00ff00表示流星燈的顏色為綠色。
【ESP8266 Arduino 程式碼】
程式架構大致可區分為三個主要部分:
- 無線網路配置
這個部分只在 setup() 進行,完成之後儲存連線資料,並往下繼續執行;否則重新啟動 ESP8266 再次進行配置。 - Web Server 配置
客戶端 HTTP GET 的接收與回應處理。 - WS2812 閃爍效果
閃爍效果的實現程式碼。
/*-/--*-*/*/*/*/***//-*-*-**-*/*-*-/*/*/*-*-/-////--/**/**--**/--///--//**----**//--**//**----***//*-**//*
這小節的程式碼說明沒有包含流星燈的部分,請參考部落格另一篇文章自行加入。
這小節的程式碼說明沒有包含流星燈的部分,請參考部落格另一篇文章自行加入。
/*-/--*-*/*/*/*/***//-*-*-**-*/*-*-/*/*/*-*-/-////--/**/**--**/--///--//**----**//--**//**----***//*-**//*
程式碼的參考架構來自於 {FastLED}/examples/DemoReel100 這個程式,它裡面已經包含六種 LED 閃爍樣式,所以不用額外再撰寫這部分的程式碼;重新命名為 ESPDemoReel100 ,再加入無線網路以及 Web Server 的支援,整個程式就完成。
接下來把程式碼切分為四個部分來做說明,分別是:LED 閃爍效果、loop()、標頭檔與變數宣告、setup()。
/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
* LED 閃爍效果:
利用 FastLED 內建的函式,可以快速且容易的建立出多個 LED 閃爍效果的程式碼,至於實際的閃爍效果,看展示影片會比用文字描述得來的清楚,所以就不多加解釋。若是想要了解這些函式的用法,可到它的 WiKi 網頁去看說明。
- line 3:空函式 dryRun(),關閉 LED 後執行的函式但不執行任何指令,使其不在 loop() 中停下。
- line 56...62:用來關閉現在 LED 的閃爍效果,並設定主要的變數回初始值。
ESPDemoReel100.ino, 1 of 4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | /** LED styles */ void dryRun(){} void rainbow() { // FastLED's built-in rainbow generator fill_rainbow( leds, NUM_LEDS, gHue, 7); } void rainbowWithGlitter() { // built-in FastLED rainbow, plus some random sparkly glitter rainbow(); addGlitter(80); } void addGlitter( fract8 chanceOfGlitter ) { if( random8() < chanceOfGlitter) { leds[ random16(NUM_LEDS) ] += CRGB::White; } } void confetti() { // random colored speckles that blink in and fade smoothly fadeToBlackBy( leds, NUM_LEDS, 10); int pos = random16(NUM_LEDS); leds[pos] += CHSV( gHue + random8(64), 200, 255); } void sinelon() { // a colored dot sweeping back and forth, with fading trails fadeToBlackBy( leds, NUM_LEDS, 20); int pos = beatsin16( 13, 0, NUM_LEDS-1 ); leds[pos] += CHSV( gHue, 255, 192); } void juggle() { // eight colored dots, weaving in and out of sync with each other fadeToBlackBy( leds, NUM_LEDS, 20); byte dothue = 0; for( int i = 0; i < 8; i++) { leds[beatsin16( i+7, 0, NUM_LEDS-1 )] |= CHSV(dothue, 200, 255); dothue += 32; } } void bpm() { // colored stripes pulsing at a defined Beats-Per-Minute (BPM) uint8_t BeatsPerMinute = 62; CRGBPalette16 palette = PartyColors_p; uint8_t beat = beatsin8( BeatsPerMinute, 64, 255); for( int i = 0; i < NUM_LEDS; i++) { //9948 leds[i] = ColorFromPalette(palette, gHue+(i*2), beat-gHue+(i*10)); } } void ledOff() { FastLED.clear(); FastLED.show(); // set current pattern to dryRun() gCurrentPatternNumber = 0; gHue = 0; } |
/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
* loop():
這部分的程式碼主要重複執行兩個部分:LED 閃爍樣式(line 3...8)和 HSV 的色調(Hue)更新。
- line 3:gPatterns 是一個函式陣列,裡面所包含的就是 LED 閃爍效果的函式名稱;選擇執行哪一個函式,則是由 gCurrentPatternNumber 這個索引值做決定,這個索引值在接收到 HTTP GET 要求時才會做變更。
- line 8:多久更新與執行一次 LED 閃爍效果函式。
- line 11...13:多久更新一次 gHue 色調值;這裡用的是 20 ms。
ESPDemoReel100.ino, 2 of 4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | void loop() { // 執行選定的樣式函式 gPatterns[ gCurrentPatternNumber ](); // 顯示 LED 燈樣式 FastLED.show(); // 插入延遲以保持畫面播放速率適中 FastLED.delay( 1000 / FRAMES_PER_SECOND ); // 做一些定期更新 EVERY_N_MILLISECONDS( 20 ) { gHue++; } } |
/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
* 標頭檔與變數宣告:
- line 1:加這行可讓 LED 閃爍效果更加穩定,詳請請看 FastLED Issues #306。
- line 2...6:程式裡需要的標頭檔。
- line 7...9:不加這些程式碼也 OK,主要是用來提醒 FastLED 的版本的使用至少要大於 V3.1。
- line 12:用來計算陣列大小。
- line 13...21:函式提前宣告給函式陣列用。
- line 23...42:全局變數宣告用,重點說明如下:
- line 25...26:作為 AP 模式時,AP 的名稱以及要加入此 AP 的密碼為何。沒有無線網路連線資訊或連不上預先儲存的 SSID 名稱與密碼時,ESP8266 才會切換到此模式,使用者此時可連線至此 AP 後開啟瀏灠器輸入 http://192.168.4.1 手動設定無線網路連線的相關資訊;
AP 模式下的操作,看網頁最下方 AsyncWiFiManager (V0.20) AP 模式組態畫面 的說明。 - line 28:建立 Web Server,使用 Port 80;
- line 32:基本上不限定使用 ESP8266 哪一根接腳,但有疑慮時請自行參閱函式庫的說明文件;為了適用於所有的 ESP8266 模組型號,選用 <GPIO2>
- line 33:要控制的 WS2812 LED 燈數量;
- line 34:設定整體亮度,255 最大;
- line 35:設定每秒的動作次數,用於調整 LED 閃爍效果的順暢度;
- line 36:建立 LED 像素陣列;
- line 38...39:建立一個函數陣列;
- line 41:函數陣列的索引值;
- line 42:HSV 的色調值;
ESPDemoReel100.ino, 3 of 4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | #define FASTLED_ALLOW_INTERRUPTS 0 #include <ESP8266WiFi.h> #include <ESPAsyncTCP.h> #include <ESPAsyncWebServer.h> #include <ESPAsyncWiFiManager.h> #include <FastLED.h> #if defined(FASTLED_VERSION) && (FASTLED_VERSION < 3001000) #warning "Requires FastLED 3.1 or later; check github for latest code." #endif //* 函式宣告 * #define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0])) void dryRun(void); void rainbow(void); void rainbowWithGlitter(void); void addGlitter( fract8 chanceOfGlitter ); void confetti(void); void sinelon(void); void juggle(void); void bpm(void); void ledOff(void); //* 全局變數 * // ESP8266 AP 名稱與連線密碼 const char* ESP_AP_NAME = "espws2812"; const char* ESP_AP_PASS = "123456789"; // Async Web Server AsyncWebServer WEBSERVER(80); DNSServer DNS; // LED 燈串數量 #define DIN_PIN 2 // ESP8266/ESP8285 GPIO2 #define NUM_LEDS 16 #define BRIGHTNESS 96 #define FRAMES_PER_SECOND 120 CRGBArray<NUM_LEDS> leds; typedef void (*SimplePatternList[])(); SimplePatternList gPatterns = { dryRun ,rainbow, rainbowWithGlitter, confetti, sinelon, juggle, bpm, ledOff }; uint8_t gCurrentPatternNumber = 0; uint8_t gHue = 0; |
/*--*//**---/*///**---*-*////***--*/*///***----*///--*/*///**--*/*//**--**/*//
* setup():
setup() 中主要處理:WS2812 LED 燈的初始化設定、無線網路的連線或配置和 Web Server 的設置這三個部分,其中:
- line 5...7:WS2812 LED 燈的初始化設定。
- line 13...22:無線網路的連線或配置;
- line 14:設定最小的訊號品質,預設 < 8% 的訊號品質不輸出;
- line 15:連線逾時的時間設定(秒);
- line 16:自動連線,若失敗首先啟用 AP 模式,AP 模式下的名稱為 ESP_AP_NAME,密碼為 ESP_AP_PASS 變數所指定的字串,若再失敗則重啟 ESP8266。
ESPDemoReel100.ino, 4-1 of 4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | void setup() { delay(3000); /** FastLED 初始化 */ FastLED.addLeds<WS2812B, DIN_PIN, GRB>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip); FastLED.setBrightness( BRIGHTNESS ); ledOff(); Serial.begin( 115200 ); Serial.print( "\n\n" ); /** Async WiFi Manager */ AsyncWiFiManager wifiManager( &WEBSERVER, &DNS ); wifiManager.setMinimumSignalQuality(); wifiManager.setTimeout(120); if ( !wifiManager.autoConnect( ESP_AP_NAME, ESP_AP_PASS ) ) { Serial.println("failed to connect and hit timeout"); delay(3000); // Reset and try again, or maybe put it to deep sleep ESP.reset(); delay(5000); } // 到這裡已經完成無線網路的連線 Serial.print( "\nWiFi Connected.\n" ); |
Web Server 的設置只列出了 LED 樣式(sendstyle)的部分;流星燈挑色(sendcolor)的部分只留下了回覆的訊息部分,避免手機端操作時出現錯誤,此處留待看倌自己實現。
- line 30...63:Web Server 的設置;
- line 30...51:LED 閃爍效果的處理;
- line 53...55:流星燈挑色處理的程式碼,此處只留下接收到訊息後回覆的處理機制。
首先確認是否包含參數 style(line 33): - 有的話(line 34...44)將參數的值讀入並轉換形態到整數(line 34),然後將值輸出(line 35)。接著檢查轉換後的樣式值,它必須大於 0 於函數陣列的數目,才算是有效值(line 38...42),才可以將此值指定給函數陣列索引值(line 40)和初始化 HSV 色調值(line 41);否則將錯誤的訊息填入到回覆訊息字串中(line 43)。
- 沒有的話(line 46...49),輸出訊息並將錯誤的訊息填入到回覆訊息字串中(line 48)。
- line 58...60:沒有符合的 HTTP GET 要求時就會由這邊的程式碼做處理;
- line 63:啟動 Web Server;
ESPDemoReel100.ino, 4-2 of 4
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | /** Web Server Events Handle */ /// 1. LED 樣式選擇 /// HTTP GET <IP>/sendstyle?style=#, # 樣式數字 /// WEBSERVER.on( "/sendstyle", HTTP_GET, [](AsyncWebServerRequest *request) { uint8_t style; String replymsg; if( request->hasParam( "style" ) ) { style = request->getParam( "style" )->value().toInt(); Serial.printf( "style:%d\n", style ); /// 樣式指定 if( style > 0 && style < ARRAY_SIZE(gPatterns) ) { replymsg = "done"; gCurrentPatternNumber = style; gHue = 0; } else { // non-integer number. replymsg ="non-integer number."; } } else { Serial.println( "style:" ); replymsg = "style-failed"; } request->send( 200, "text/plain", replymsg ); }); WEBSERVER.on( "/sendcolor", HTTP_GET, [](AsyncWebServerRequest *request) { request->send( 200, "text/plain", "done" ); }); // 處理找不到對應的網頁 WEBSERVER.onNotFound( [] ( AsyncWebServerRequest *request ) { request->send( 404, "test/plain", "Not found." ); }); // Start web server WEBSERVER.begin(); } |
【AsyncWiFiManager (V0.20) AP 模式組態畫面 】
第一次或是在陌生的無線網路環境下通電裝置端後,ESP8266 的輸出訊息大概會像下面一樣。其中,反色的部分是提示使用者此時的 ESP8266 AP 的名稱與連線密碼。
ESP8266 WiFi 連線輸出 log - 01 |
AsyncWiFiManager 無線網路操作畫面 - 01 |
點選 "Configure WiFi" 按鈕,進入到無線網路掃描之後的畫面,在此畫面中選擇所要連線的 SSID 並且輸入連線密碼,按下 "Save" 按鈕,如果 SSID 與密碼匹配的話,就會出現接下來的視窗,並且重啟 ESP8266 自動連線到剛剛指定的無線網路中。
AsyncWiFiManager 無線網路操作畫面 - 02 |
ESP8266 WiFi 連線輸出 log - 02 |
在這個網頁,展示了手機端與裝置端之間藉由 HTTP GET 通訊方式來控制 LED 燈閃爍的效果,利用這種方式可擴展非常多不同的閃爍樣式,看倌可自己再做其他的嘗試。
流星燈挑色的部分,手機 APP 提供了調色環的介面,使用者的選擇會以 16 進制的字串形式傳送到裝置端,用戶可依自己的創意再加以實現,不一定非要是流星燈!
手機 APP 比較美中不足的部分,就是無線網路連線之後沒有回傳裝置端連線 IP 地址的功能,使用者必須進入 AP 操作網頁或是經由 UART 輸出畫面才能得知裝置端的 IP 地址;即便已試過其他的方式,但用起來現在還是這款比較好,所以在沒有比較好的選擇下,先用著吧!
手機 APP 大致上是根據裝置端的韌體下去寫的,因此有點畫地自限!比較好的方式是可以自建與儲存 LED 閃爍效果,這樣就能無限擴充而不會受限於特定韌體。
<< 部落格相關文章 >>
到最後一部之前都很順利,但是連線成功後沒有跳出ip位址,而是出現Handle not found,請問是甚麼原因呢?應該要如何改善?
回覆刪除說清楚一點,不曉得你的問題點在哪裡?
刪除