最近想做一個小夜燈,可以用手機的網頁控制顏色,找出之前做的 Arduino筆記(26):控制圓形16位元5050全彩LED 看一下如何連接到 Arduino。這個實作改用 NodeMCU 連接,透過網頁設定RGB顏色值,再控制環形的16個 LED燈亮這個 RGB 顏色。轉一圈後,第二圈以隨機的方式產生顏色值,讓環形 LED 燈看起來有比較多的變化。以下是實作過程與紀錄:
• 先到 Github 下載 Adafruit_NeoPixel,按右邊綠色選項「Clone or download」,再選「Download ZIP」。
• 將下載的壓縮檔解壓縮,放在 Arduino 主程式下的 libraries目錄內,以我的電腦來說,Arduino安裝在 C:\User\[登入的帳號]\Documents\Arduino,點進目錄有一個 libraries的子目錄,下載後解壓縮的目錄,整個放進 libraries 目錄,重新啟動 Arduino即可。
• FC-102 16 LED 環形模組 x 1
• 連接線 x 3
[安裝Adafruit_NeoPixel Library]
Adafruit_NeoPixel 函式庫提供 LED 顯示的顏色、亮度等控制項目。• 先到 Github 下載 Adafruit_NeoPixel,按右邊綠色選項「Clone or download」,再選「Download ZIP」。
• 將下載的壓縮檔解壓縮,放在 Arduino 主程式下的 libraries目錄內,以我的電腦來說,Arduino安裝在 C:\User\[登入的帳號]\Documents\Arduino,點進目錄有一個 libraries的子目錄,下載後解壓縮的目錄,整個放進 libraries 目錄,重新啟動 Arduino即可。
[材料]
• NodeMCU V3 x 1• FC-102 16 LED 環形模組 x 1
• 連接線 x 3
[線路圖]
NodeMCU
|
16 LED 環形模組
|
VIN
|
VCC
|
GND
|
GND
|
D2
|
DOUT
|
[程式]
#include <ESP8266WiFi.h> #include <Adafruit_NeoPixel.h> // 設定網路基地台SSID跟密碼 const char* ssid = "MyHome"; const char* password = "ceiling4895"; // Set web server port number to 80 WiFiServer server(80); // HTTP GET 的值 String redString = "0"; String greenString = "0"; String blueString = "0"; int pos1 = 0; int pos2 = 0; int pos3 = 0; int pos4 = 0; // 儲存 HTTP 需求的值 String header; const int PIN = 4; // NodeMCU 的 D2 pin const int NUMPIXELS = 16; // 環形LED燈數 // 目前時間 unsigned long currentTime = millis(); // 前次時間 unsigned long previousTime = 0; // 定義 timeout 時間, 以 milliseconds 表示(example: 2000ms = 2s) const long timeoutTime = 2000; Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); void setup() { Serial.begin(115200); // Wi-Fi 連線 Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } // 列出取得的 IP address 並啟用 Web Server Serial.println(""); Serial.println("WiFi connected."); Serial.println("IP address: "); Serial.println(WiFi.localIP()); server.begin(); pixels.begin(); // 初始化 LED NeoPixel 物件 pixels.setBrightness(40); } void loop(){ WiFiClient client = server.available(); // 等待 clients 連線 if (client) { // 假使新的用戶端連線 currentTime = millis(); previousTime = currentTime; Serial.println("New Client."); // 列印新連線 String currentLine = ""; // 等待從用戶端輸入的值 while (client.connected() && currentTime - previousTime ≤ timeoutTime) { // 當 client 繼續連線持續執行迴圈 currentTime = millis(); if (client.available()) { // 如果從 Client 端讀到位元 char c = client.read(); // 讀取位元 Serial.write(c); // 印出到串列 Console header += c; if (c == '\n') { // 假使是換行符號 // 假使目前的一行是空白且有兩個新行,就結束 client HTTP 的要求 if (currentLine.length() == 0) { // HTTP 表頭開始時,會有回應碼 response code (如: HTTP/1.1 200 OK) client.println("HTTP/1.1 200 OK"); client.println("Content-type:text/html"); client.println("Connection: close"); client.println(); // 顯示 HTML 網頁 client.println("<!DOCTYPE html><html>"); client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"); client.println("<link rel=\"icon\" href=\"data:,\">"); client.println("<link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css\">"); client.println("<script src=\"https://cdnjs.cloudflare.com/ajax/libs/jscolor/2.0.4/jscolor.min.js\"></script>"); client.println("</head><body<div class=\"container\"><div class=\"row\"><h1>ESP Color Picker</h1></div>"); client.println("<a class=\"btn btn-primary btn-lg\" href=\"#\" id=\"change_color\" role=\"button\">Change Color</a> "); client.println("<input class=\"jscolor {onFineChange:'update(this)'}\" id=\"rgb\"></div>"); client.println("<script>function update(picker) {document.getElementById('rgb').innerHTML = Math.round(picker.rgb[0]) + ', ' + Math.round(picker.rgb[1]) + ', ' + Math.round(picker.rgb[2]);"); client.println("document.getElementById(\"change_color\").href=\"?r\" + Math.round(picker.rgb[0]) + \"g\" + Math.round(picker.rgb[1]) + \"b\" + Math.round(picker.rgb[2]) + \"&\";}</script></body></html>"); // HTTP 回應結束時,給一個空的新行 client.println(); // 回應需求範例 : /?r201g32b255& // Red = 201 | Green = 32 | Blue = 255 if(header.indexOf("GET /?r") ≥ 0) { pos1 = header.indexOf('r'); pos2 = header.indexOf('g'); pos3 = header.indexOf('b'); pos4 = header.indexOf('&'); redString = header.substring(pos1+1, pos2); greenString = header.substring(pos2+1, pos3); blueString = header.substring(pos3+1, pos4); int ired = redString.toInt(); int igreen = greenString.toInt(); int iblue = blueString.toInt(); for(int i=0; i<NUMPIXELS; i++) { // 每一個 LED 燈 // pixels.Color() 設定 RGB 的值, 從 0,0,0 到 255,255,255 pixels.setPixelColor(i, pixels.Color(ired, igreen, iblue)); pixels.show(); // 送出更新的色表值到給硬體 delay(100); // 等待 0.1秒 } // 隨機產生不同顏色 for(int i=0; i<NUMPIXELS; i++) { // 每一個 LED 燈 ired += random(0,255); igreen += random(0,255); iblue += random(0,255); if (ired > 255) { ired = ired - 255;} if (igreen > 255) { igreen = igreen - 255;} if (iblue > 255) { iblue = iblue - 255;} pixels.setPixelColor(i, pixels.Color(ired, igreen, iblue)); pixels.show(); // 送出更新的色表值到給硬體 delay(100); // 等待 0.1秒 } } break; } else { // 假使有新的一行, 清除目前這一行 currentLine = ""; } } else if (c != '\r') { /// 讀取到的不是換行符號 currentLine += c; // 增加一個字元在本行最後 } } } // 清除表頭變數 header = ""; // 關閉連線 connection client.stop(); Serial.println("Client disconnected."); Serial.println(""); } }
[實作結果]
[參考資料]
- Randomnerdtutorials:ESP32/ESP8266 RGB LED Strip with Color Picker Web Server
張貼留言