Realizziamo una stazione meteo Wi-Fi con display touch-screen Nextion che fornisce anche le fase lunari

Andiamo a realizzare una stazione meteo con touch-screen che andrà a sostituire la vecchia versione realizzata qualche tempo fa e che vi abbiamo mostrato in questo ARTICOLO. Non adopereremo un Arduino Mega, ma un più economico e performante NodeMCU con chip ESP8266. Alla scheda collegheremo un display Nextion da 3,5″, un sensore SHT31 per avere una doppia misurazione: temperatura interna e temperatura prelevata da Internet.

Progetto

Il progetto di questa stazione meteo non prevede solo di rilevare e stampare su display i dati che preleveremo dal sensore e da Internet, ma si promette di mostrare le condizioni metereologiche e le fasi lunari. Stiamo cercando di realizzare un progetto completo e alla portata di tutti, che adoperi molte delle componenti che abbiamo già visto su questo sito e di cui abbiamo apprezzato l’utilità. Soprattutto il display Nextion sarà molto utile, alleggerendo il compito della ESP8266, la quale si limiterà a leggere i dati e ad inviarli al display, mentre esso si occuperà di ogni altro aspetto, compreso quello grafico. Infatti, non si limiterà a stampare i dati, ma si occuperà della loro gestione e di modificare le icone del meteo e delle fasi lunari a seconda degli input ricevuti.

Componenti

Nel progetto adopereremo un NodeMCU con chip ESP8266 a cui abbiamo saldato i pin header maschi curvi, per ridurre al minimo l’ingombro dovuto dai jumper. Alla dev-board collegheremo un sensore di temperatura e umidità già visto in questo ARTICOLO: il sensore digitale SHT31. Oltre alla comodità di collegarlo tramite interfaccia I2C, il sensore ci permetterà di misurare la temperatura automaticamente in Celsius e Fahrenheit, mentre l’umidità sia assoluta che relativa. Sempre alla dev-board collegheremo un display Nextion da 3,5″, sul quale appariranno i dati rilevati, le icone e le animazioni di cui avremo bisogno.

Lista componenti su Amazon:

Lista componenti su Aliexpress:

Collegamenti

Partiamo dall’alimentazione: alimenteremo il sistema adoperando il connettore USB in dotazione con il display Nextion, il quale darà 5V sia al display, che al NodeMCU, il quale poi alimenterà il sensore coi 3,3V. Sarà sufficiente un cavo USB con connettore Micro-USB ed un qualsiasi caricabatterie da smartphone. Venendo ai collegamenti dati, useremo i pin digitali D1 e D2 per collegarci i pin SCL e SDA del sensore SHT31. Per collegare il Nextion, usiamo il pin D5 a cui collegheremo il pin TX del display, mentre il D6 per il pin RX.

Stazione

Codice Nextion

Non vi spiegheremo come abbiamo realizzato la GUI del progetto, anche perché parte di essa deriva da alcuni argomenti già affrontati. Quello che vi spiegheremo sarà solamente la parte relativa al cambio delle icone. Il progetto prevede tre pagine: la prima (page 0) si occuperà della riproduzione di una GIF animata (abbiamo spiegato come fare in questo ARTICOLO), il cui scopo sarà dare il tempo al NodeMCU di connettersi tramite Wi-Fi e ricavare i dati da Internet; la seconda pagina (page 1) mostrerà la temperatura e l’umidità rilevati dal sensore SHT31 e la temperatura con le condizioni meteo prelevate tramite API; l’ultima pagina (page 2) mostrerà i dati di pressione, umidità e velocità del vento, ricavati da API, e le fasi lunari, indicando anche la luminosità della Luna. L’icona del meteo, se premuta ci condurrà alla page 2, invece l’icona della fase lunare ci porterà alla page 1.

Vediamo ora il codice che abbiamo adoperato per permettere all’icona del meteo di cambiare. Abbiamo avuto bisogno di creare 3 variabili: tm0 (timer), va0 (variabile intera) e va1 (stringa). Abbiamo poi assegnato all’immagine p1 dell’icona un valore numero preciso (1), che corrisponde all‘ID dell’icona del Sereno. Ogni volta che il display riceverà dal NodeMCU un numero intero compreso fra 1 e 7, il Nextion assegnerà il valore ricevuto all’immagine p1 in modo che cambi l’icona del meteo e modifichi anche la relativa scritta che appare sotto l’icona.


p1.pic=va0.val
t14.txt=va1.txt
if(va0.val==1)
{
va1.txt="Sereno"
}
if(va0.val==2)
{
va1.txt="Parz. Nuvoloso"
}
if(va0.val==3)
{
va1.txt="Nebbia"
}
if(va0.val==4)
{
va1.txt="Pioggia"
}
if(va0.val==5)
{
va1.txt="Neve"
}
if(va0.val==6)
{
va1.txt="Temporale"
}
if(va0.val==7)
{
va1.txt="Nuvoloso"
}

Stessa identica procedura per il cambio della fase lunare, che cambierà sia l’icona che il relativo nome da assegnare.

p2.pic=va2.val
t23.txt=va3.txt
if(va2.val==10)
{
va3.txt="Mezzaluna Crescente"
}
if(va2.val==11)
{
va3.txt="Primo Quarto"
}
if(va2.val==12)
{
va3.txt="Gibbosa Crescente"
}
if(va2.val==13)
{
va3.txt="Plenilunio"
}
if(va2.val==14)
{
va3.txt="Gibbosa Calante"
}
if(va2.val==15)
{
va3.txt="Ultimo Quarto"
}
if(va2.val==16)
{
va3.txt="Mezzaluna Calante"
}
if(va2.val==9)
{
va3.txt="Novilunio"
}

Acquisizione della API Key

Per prima cosa sarà necessario ottenere una API-Key dal sito www.openweathermap.org; una volta registrati, effettuate l’accesso e entrate nella scheda API keys per ottenere la vostra chiave API. Rammentate che è segreta e non dovrete condividerla con nessuno. Fatto questo, tornate nella Homepage del sito e nella casella di ricerca, cercate la vostra città e conservate le cifre che appaiono nell’URL, ad esempio per Milano appaiono così https://openweathermap.org/city/3173435.

Codice ESP8266

Non analizzeremo tutto il codice, ma solo le parti che riteniamo importanti. Potete scaricare tutti i file da GitHub,  compresi il codice, librerie e i file del Nextion a questo LINK. Iniziamo con le librerie; per questo progetto utilizzeremo la libreria ArduinoJson.h, ESP8266WiFi.hESPHTTPClient.h per la connessione, recezione ed elaborazione dei dati, la libreria time.h e Astronomy.h per il calcolo delle fasi lunari, la libreria SoftwareSerial.h per la comunicazione con il Nextion e la libreria SHT3x.h per il sensore.


#include <ESP8266WiFi.h>
#include <ArduinoJson.h>
#include <ESPHTTPClient.h>
#include <time.h>
#include <SoftwareSerial.h>
#include "Astronomy.h"
#include <SHT3x.h>

Andiamo poi a inserire nel codice il nome e password della rete Wi-Fi e la informazioni ricavate da OpenWeatherMap (API key e ID Città).


const char* ssid = "xxxxxxxxxxxxxx"; // SSID Wi-Fi
const char* password = "xxxxxxxxxxx"; // Password Wi-Fi

const String city_id = "xxxxxxx"; // ID Città
const String apikey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; //API Key

Nel VOID SETUP inizializziamo il Monitor seriale per stampare i dati elaborati, avviamo il seriale via software, specificando la frequenza (9600) e i pin che adopereremo, infine inizializziamo il sensore digitale.


Serial.begin(115200);
myPort.begin(9600, SWSERIAL_8N1, RX_PIN, TX_PIN, false);
Sensor.Begin();

Nel VOID LOOP andiamo a vedere un esempio di come la ESP8266 interagisce con il Nextion per il cambio icona del meteo. Durante il processo in cui ricaviamo e elaboriamo i dati ottenuti tramite API Key (Deserializzazione della stringa), otteniamo un ID specifico per le condizioni metereologiche. Se otteniamo l’ID specifico per la condizione meteo di “Soleggiato”, invieremo un numero intero alla variabile va0, vista nella parte del codice del Nextion, tramite il seriale. Il display otterrà questo numero che corrisponderà all’icona specifica.


if (icon == "01d" || icon == "01n"){
myPort.print("va0.val=");
myPort.print(1);
myPort.write(0xff);
myPort.write(0xff);
myPort.write(0xff); // soleggiato
}

Lo stesso procedimento accade per le fasi lunari. Solo che invece di un ID otteniamo una stringa riportante la nomenclatura della fase lunare. Come prima, viene inviato uno specifico numero intere corrispondente all’icona che deve essere mostrata.


if (MOON == "Novilunio"){
myPort.print("va2.val=");
myPort.print(9);
myPort.write(0xff);
myPort.write(0xff);
myPort.write(0xff); // Novilunio
}

Il calcolo della fase lunare è estremamente complesso, quindi abbiamo deciso di affidarci ad una libreria, con la quale otteniamo la data corrente e ricaviamo la fase, la quale, inizialmente è semplicemente un numero intero, compreso tra 1 e 8.


time_t now = time(nullptr);
struct tm * timeinfo = localtime (&now);

uint8_t phase = astronomy.calculateMoonPhase(timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday);
String MOON = MOON_PHASES[phase].c_str();
Serial.print("Moon Phase: ");
Serial.println(MOON);

Astronomy::MoonData moonData = astronomy.calculateMoonData(timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday);
Serial.printf("Moon Phase: %s\n", MOON_PHASES[moonData.phase].c_str());
Serial.printf("Illumination: %f\n", moonData.illumination * 100.00);

Durante la sua elaborazione, questo numero viene associato ad una stringa che abbiamo (MOON_PHASE).


const String MOON_PHASES[] = {"Novilunio", "Mezzaluna Crescente", "Primo Quarto", "Gibbosa Crescente",
"Plenilunio", "Gibbosa Calante", "Ultimo Quarto", "Mezzaluna Calante"};

Dopo aver chiarito questo punto, andiamo a caricare lo sketch, selezionando come scheda NodeMCU 1.0 (ESP-12E Module).