Christmas tree 2019 sketch è la parte del progetto natalizio dedicata al programma che puoi caricare sull’esp8266.
Se hai letto i precedenti articoli dedicati a questo progetto sai già dove trovare il codice per realizzare una interfaccia grafica web e come verrà il progetto:
oggi procedi oltre nel progetto con il codice christmas tree 2019 sketch che potrai caricare nel tuo ESP8266 a cui collegarti con lo smartphone per visualizzare l’interfaccia web:
Prima di procedere con la descrizione del codice, ci sono alcuni passaggi preliminari da eseguire.
Ricorda che il progetto, completo di sketch e web interface modificabile, è condiviso sul mio gitHub ed in particolare nella cartella esp8266 trovi le parti relative allo sketch.
Passaggi preliminari del progetto
usando i tool per sfruttare la SPIFF della esp8266, leggi nel link come usarla e come caricare i tools.
Ora che sai come funziona la SPIFF e come caricarla ricorda di eseguire questi semplici passaggi:
- crea uno sketch vuoto in cui inserirai il codice che leggi nel paragrafo successivo;
- salva lo sketch tra i tuoi progetti personali;
- accedi al path in cui hai salvato lo sketch ( solitamente sotto Documenti\Arduino\…. );
- crea una cartella chiamata data in questa posizione;
- copia i file common.css e colorpicker.js nella dir data;
otterrai una situazione simile alla seguente:
in cui lo sketch lo puoi chiamare come desideri, l’importante è che la cartella data sia presente sotto il medesimo path del Christmas tree 2019 sketch.
Ricordati quindi di eseguire il passaggio di upload dei file tramite l’esptool:
Christmas tree 2019 sketch
Ecco finalmente il christmas tree 2019 sketch, ossia il programma che puoi caricare sulla tua esp8266 per visualizzare l’interfaccia web di controllo:
#include <FastLED.h> FASTLED_USING_NAMESPACE #include "ESP8266WiFi.h" #include <ESP8266WebServer.h> #include <DNSServer.h> #include <WiFiClient.h> #include <ESP8266mDNS.h> // NEW #include <FS.h> /****************************************************************************************/ const byte DNS_PORT = 53; // NEW DNSServer dnsServer; // NEW ESP8266WebServer server(80); IPAddress apIP(192, 168, 4, 1); // NEW IPAddress netMsk(255, 255, 255, 0); // NEW WiFiClient espClient; /****************************************************************************************/ const char* wifi_ssid = "christmas"; const char* wifi_password = "2019"; unsigned char red,green,blue; /****************************************************************************************/ #if defined(FASTLED_VERSION) && (FASTLED_VERSION < 3001000) #warning "Requires FastLED 3.1 or later; check github for latest code." #endif #define DATA_PIN 2 //#define CLK_PIN 4 #define LED_TYPE WS2811 #define COLOR_ORDER GRB #define NUM_LEDS 40 CRGB leds[NUM_LEDS]; #define BRIGHTNESS 96 /****************************************************************************************/ void handle_root() { Serial.println("Handle Root"); server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); server.sendHeader("Pragma", "no-cache"); server.sendHeader("Expires", "-1"); String html = "<!DOCTYPE html> <html lang=\"en\"> <head> <title>Color Picker</title> <meta charset=\"UTF-8\"/> <link href=\"common.css\" rel=\"stylesheet\" /> <script src=\"colorpicker.js\"></script> <style>.inputs-list {margin-top: 34px\; \n }</style> </head>\n"; html += "<body> <div class=\"example-wrap\"> <div class=\"inputs-list\"> "; html += "<input type=\"hidden\" id=\"blackCode\" value=\"#000000\" /> "; html += "<input type=\"hidden\" id=\"oldHexCode\" value=\"\" /> "; html += "<input type=\"button\" onclick=\"sendData(getElementById('blackCode'))\" onchange=\"\" class=\"io-input\" style=\"background-color:#000\; border: 2px solid #fff\; color: #fff\; \" value=\"0\" /> "; html += "<input type=\"button\" onclick=\"sendData(getElementById('oldHexCode'))\" onchange=\"\" class=\"io-input\" style=\"background-color:#fff\; border: 2px solid #fff\; color: #000\; \" value=\"1\" /> "; html += "</div> <canvas id=\"canvas\"></canvas> <div class=\"inputs-list\"> "; html += "<input type=\"button\" onclick=\"sendData(event.target)\" onchange=\"picker.editInput(event.target)\" class=\"multi-input input-quad\" value=\"#8825eb\" />"; html += "<input type=\"button\" onclick=\"sendData(event.target)\" onchange=\"picker.editInput(event.target)\" class=\"multi-input input-quad\" value=\"#2439eb\" />"; html += "<input type=\"button\" onclick=\"sendData(event.target)\" onchange=\"picker.editInput(event.target)\" class=\"multi-input input-quad\" value=\"#24e9eb\" />"; html += "<input type=\"button\" onclick=\"sendData(event.target)\" onchange=\"picker.editInput(event.target)\" class=\"multi-input input-quad\" value=\"#eb9524\" />"; html += "<input type=\"button\" onclick=\"sendData(event.target)\" onchange=\"picker.editInput(event.target)\" class=\"multi-input input-quad\" value=\"#eb2497\" />"; html += "</div> <div class=\"inputs-list\">"; html += "<input type=\"button\" onclick=\"sendData(event.target)\" onchange=\"picker.editInput(event.target)\" class=\"multi-input input-quad\" value=\"#ffffff\" />"; html += "<input type=\"button\" onclick=\"sendData(event.target)\" onchange=\"picker.editInput(event.target)\" class=\"multi-input input-quad\" value=\"#ffe83f\" />"; html += "<input type=\"button\" onclick=\"sendData(event.target)\" onchange=\"picker.editInput(event.target)\" class=\"multi-input input-quad\" value=\"#ff0000\" />"; html += "<input type=\"button\" onclick=\"sendData(event.target)\" onchange=\"picker.editInput(event.target)\" class=\"multi-input input-quad\" value=\"#00ff00\" />"; html += "<input type=\"button\" onclick=\"sendData(event.target)\" onchange=\"picker.editInput(event.target)\" class=\"multi-input input-quad\" value=\"#0000ff\" />"; html += "</div> </div> \n"; html += "<script> var picker = new KellyColorPicker({ place : 'canvas', size : 700, userEvents : { change : function(self) { if (!self.selectedInput) return\; \n if (self.getCurColorHsv().v < 0.5) { self.selectedInput.style.color = \"#FFFFFF\"\; \n } else { self.selectedInput.style.color = \"#000000\"\; \n } self.selectedInput.value = self.getCurColorHex()\; \n self.selectedInput.style.background = self.selectedInput.value\; \n } } })\; \n picker.editInput = function(target) { if (picker.selectedInput) picker.selectedInput.classList.remove('selected')\; \n if (target) picker.selectedInput = target\; \n if (!picker.selectedInput) return false\; \n picker.selectedInput.classList.add('selected')\; \n picker.setColor(picker.selectedInput.value)\; \n picker.selectedInput.style.color=picker.selectedInput.value\; \n } \n"; html += "var mInputs = document.getElementsByClassName('multi-input')\; \n for (var i = 0\; \n i < mInputs.length\; \n i++) { picker.editInput(mInputs[i])\; \n } \n"; html += "picker.getWheel().width += 60\; \n picker.getSvFigCursor().radius += 15\; \n picker.getWheelCursor().height += 15\; \n var alpha = picker.getAlphaFig()\; \n picker.updateView(true)\; \n \n"; html += "</script> </body> </html>"; server.send(200, "text/html", html); delay(100); } void handle_outputs() { Serial.print("Handle output"); // Strings to strore the client output String RMsg; String GMsg; String BMsg; // Parse client output RMsg=server.arg("r"); GMsg=server.arg("g"); BMsg=server.arg("b"); Serial.print(" RMsg: "); Serial.print(RMsg); Serial.print(" GMsg: "); Serial.print(GMsg); Serial.print(" BMsg: "); Serial.print(BMsg); Serial.print("\n"); // Convert to number to pass to Neopixel library red=RMsg.toInt(); green=GMsg.toInt(); blue=BMsg.toInt(); String result = "<!DOCTYPE html> <html lang=\"en\"> <head> <title>Color Picker</title> </head> <body>message</body> </html>"; server.send(200, "text/html", result); } void getSpiffFile(String path, String TyPe) { if(SPIFFS.exists(path)){ File file = SPIFFS.open(path, "r"); server.streamFile(file, TyPe); file.close(); } } // Initialize WiFi, web server and handles void setup() { Serial.begin(115200); Serial.println("Setup start execution"); WiFi.mode(WIFI_AP); //Only Access point WiFi.softAPConfig(apIP, apIP, netMsk); // NEW WiFi.softAP(wifi_ssid, wifi_password); //Start HOTspot removing password will disable security dnsServer.setErrorReplyCode(DNSReplyCode::NoError); // NEW dnsServer.start(DNS_PORT, "*", apIP); // NEW red=127; green=127; blue=127; FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip); FastLED.setBrightness(BRIGHTNESS); server.on("/", handle_root); server.on("/common.css", []() { getSpiffFile("/common.css", "text/css"); } ); server.on("/colorpicker.js", []() { getSpiffFile("/colorpicker.js", "application/javascript"); } ); server.on("/setcolor.html", handle_outputs); //server.onNotFound( handle_root ); server.begin(); SPIFFS.begin(); setColorPixel(); Serial.println("Setup successfully executed"); } void loop() { server.handleClient(); dnsServer.processNextRequest(); setColorPixel(); FastLED.show(); } void setColorPixel() { Serial.print(" R: "); Serial.print(red); Serial.print(" G: "); Serial.print(green); Serial.print(" B: "); Serial.print(blue); Serial.print("\n"); for(int i=0;i<NUM_LEDS;i++){ leds[i] = CRGB( red, green, blue); FastLED.show(); FastLED.delay(1000/30); } }
il listato è molto lungo e ci concentreremo solo sulle parti fondamentali che ti consentono il cerretto funzionamento e l’eventuale modifica dello sketch.
Le parti non descritte sono già state analizzate in tanti altri articoli e non costituiscono parte fondamentale dello sketch.
Inizia dalla linea 001: includi la libreria FastLED.h che userai per gestire i led WS2812B ( vedi articoli dedicati a tale libreria in questo blog );
linee 005-009: includi le librerie necessarie alla connessione WiFi e la gestione del web server ( vedi articoli dedicati al wifi per esp8266 e relativo web server );
linea 010: includi la libreria FS.h che ti permette la gestione del FileSystem ( FS appunto ) SPIFF come descritto negli articoli citati al paragrafo precedente;
linee 013-021: definisci le istanzse per la prte WiFi e la generazione del WebServer;
linee 025-026: definisci SSID e Pass da passare alla libreria WiFi per collegarsi alla tua rete wifi, io hoscelto di usare la modalità AP ( Access Point ) facendogli generare un SSID alla ESP8266 a cui collegarti;
linea 027: definisci le tre variabili per i tre colori primari che userai per accendere i led;
linee 029-039: definisci alcune costanti necessarie al corretto funzionamento della FastLED;
linea 040: crea l’istanza leds che userai per comunicare con i led WS2812B;
linea 042: definisci una costante per la luminosità dei led fissa a 96;
linee 046-079: definisci la funzione handle_root() che sarà richiamata quando ti collegherai alla root “/” del web server e che compone ed espone la pagina visualizzata che hai già visto nel dettagli descritta nel precedente articolo;
linea 081: definisci la funzione handle_output() che ti permette la vera e propria interazione con i led, viene richiamata dal web server quando richiami la pagina setcolor.html e riceve in get i parametri che gli passi;
linee 090-092: usando il metodo arg della classe server recuperi i parametri in GET che desideri utilizzare;
linee 100-102: converti in intero il valore di ciascuno dei parametri ricevuti dalla climata get HTTP;
linea 104: definisci la stringa di risposta che invierai alla chiamata Ajax fatta dalla pagine Web;
linea 105: invia il risultato in risposta all’interfaccia web;
linee 108-114: imposta la funzione getSpiffFile() che richiamerai tutte le volte che ti serve recuperare un file dalla SPIFF precedentemente salvato ( vedi paragrafo “passaggi preliminari del progetto” ). Devi passarle il path ( percorso ) in cui trova il file, comprensivo di nome del file e la tipologia di file;
linee 117-133: definisci tutte le inizializzazioni relative al WiFi, FastLed e valori di default per le tre componenti colore come decsritto in tanti altri articoli dedicati alle singole definizioni;
linea 135: imposta la risposta quando il server riceve la chiamata per la pagina root “/”, come leggi, richiami la funzione handle_root vista prima;
linee 136-137: definisci due linee simili in cui definsci la funzione da chiamare quando ricevi la richiesta di servire una pagina presente nella SPIFF ( ad esempio: /common.css). Ricordi che le due pagine common.css e colopicker.js le hai salvate nella SPIFF, quindi è da quel path che dovrai andare a richiamarla. Tale funzione è la getSpiffFile();
linea 138: definisci che funzione chiamare quando ti arriva la richiesta per la pagina /setcolor.html, nota che si tratta della handle_outputs() vista sopra;
linee 141-144: usa i metodi begin per il webserver e la spiff e avvia la funzione setColorPixel() per inizializzare i led del colore di default impostato alle linee 128-130;
linee 149-154: nella funzione loop() avvia tutti i processi che devono essere eseguiti ciclicamente relativamente al server, dnsServer e FastLED;
linea 156: definisci la funzione setColorPixel() con cui imposti il colore dei led;
linee 163-167: con un ciclo for imposta il colore di ciascun led partendo dal primo all’ultimo;
Il video
Di seguito il video del christmas tree 2019 sketch
in cui puoi vedere come funziona lo sketch;
Buon anno.