Stazione meteo con ESP8266 e display TFT: monitoraggio in tempo reale delle previsioni meteo

Introduzione

Questo progetto di una stazione meteo con ESP8266 e display TFT è proprio ciò di cui hai bisogno se hai mai desiderato avere accesso immediato alle previsioni meteorologiche per la tua zona senza dover aprire un’applicazione sul tuo telefono o un sito web. Con l’aiuto di una ESP8266, un potente microcontroller Wi-Fi, e un display TFT da 1.8 pollici, potrai creare una stazione meteo in grado di fornirti informazioni dettagliate sul meteo in tempo reale direttamente sul tuo banco o scrivania.

In questo articolo, ti guiderò passo dopo passo nella creazione di questo dispositivo, che interroga un servizio di previsioni meteorologiche tramite un’API REST per ottenere dati aggiornati sulla temperatura, umidità, pressione atmosferica, descrizione del meteo e orario delle previsioni. Oltre a fornire un accesso rapido alle previsioni, questo progetto è un ottimo esempio di come le moderne tecnologie IoT (Internet of Things) possano rendere la nostra vita quotidiana più semplice ed efficiente.

Scoprirai come stabilire una connessione Wi-Fi con la tua ESP8266, come inviare richieste all’API di OpenWeatherMap, e come analizzare il documento JSON restituito per estrarre i dati di interesse. Infine, imparerai come visualizzare queste informazioni in modo chiaro e leggibile sul tuo display TFT.

Anche in questo progetto utilizzeremo come IDE l’ottimo PlatformIO.

Pronto a immergerti nell’interessante mondo della creazione di dispositivi IoT personalizzati? Allora procediamo con la realizzazione di questa stazione meteo intelligente.

OpenWeatherMap

OpenWeatherMap è una risorsa affidabile e fondamentale per gli appassionati di meteorologia, sviluppatori e creatori di progetti legati alle condizioni atmosferiche. Si tratta di un servizio di previsioni meteorologiche online che offre dati meteo accurati e aggiornati in tempo reale da tutto il mondo. Fondata nel 2012, OpenWeatherMap fornisce una vasta gamma di informazioni meteorologiche, tra cui temperature, umidità, pressione atmosferica, vento e molto altro. Ma ciò che rende OpenWeatherMap davvero straordinario è l’accesso gratuito all’API (Interfaccia di Programmazione delle Applicazioni), che consente ai programmatori e agli hobbisti di integrare queste preziose informazioni nei loro progetti personali. L’API di OpenWeatherMap offre un’ampia gamma di dati meteo, consentendo agli sviluppatori di creare applicazioni, dispositivi IoT e servizi che offrono previsioni meteo locali e globali. La sua facilità d’uso, unita alla copertura globale e all’accuratezza dei dati, lo rendono uno strumento insostituibile per chiunque abbia interesse nel monitoraggio e nell’analisi delle condizioni meteorologiche attuali e future.

Le API REST

Le API REST (Application Programming Interface – Representational State Transfer) sono un fondamentale standard di comunicazione nel mondo del software e dell’informatica. Questo approccio architetturale è progettato per consentire la comunicazione e lo scambio di dati tra sistemi software, applicazioni e servizi in modo efficace ed efficiente. Le API REST si basano su alcuni principi chiave:

  1. Rappresentazione dei dati: le risorse (dati) vengono rappresentate in un formato standard, spesso utilizzando JSON o XML, che è facilmente comprensibile da parte delle applicazioni.
  2. Statelessness (stato zero): ogni richiesta tra client e server è autosufficiente e non dipende dallo stato precedente. Questo significa che ogni richiesta contiene tutte le informazioni necessarie per essere elaborata con successo.
  3. Operazioni standard: le API REST utilizzano metodi HTTP standard, come GET (per recuperare dati), POST (per creare nuove risorse), PUT (per aggiornare risorse esistenti) e DELETE (per rimuovere risorse).
  4. URI (Uniform Resource Identifier): ogni risorsa è identificata da un URI univoco, che consente di accedere direttamente a specifici dati o servizi.

Le API REST sono ampiamente utilizzate in applicazioni web, servizi cloud, app mobili e sistemi IoT. Consentono l’integrazione e lo scambio di dati tra diverse piattaforme e linguaggi di programmazione. Le API REST sono altamente scalabili e affidabili, il che le rende ideali per applicazioni che richiedono prestazioni elevate e che devono servire un gran numero di utenti.

Inoltre, le API REST promuovono una separazione chiara tra il frontend (interfaccia utente) e il backend (logica di business), il che semplifica lo sviluppo, la manutenzione e l’aggiornamento delle applicazioni. Questa architettura ha rivoluzionato il modo in cui le applicazioni interagiscono tra loro e con i dati, contribuendo alla creazione di un ecosistema di servizi interconnessi che alimenta gran parte del mondo digitale in cui viviamo.

Il formato JSON

JSON, acronimo di “JavaScript Object Notation”, è un formato di scambio dati leggero e altamente flessibile. È diventato uno standard de facto per la trasmissione e lo scambio di informazioni tra applicazioni e servizi su Internet. Le sue caratteristiche chiave includono:

Semplicità e leggibilità: il formato JSON è basato su una struttura di coppie chiave-valore ed è scritto in un linguaggio leggibile dall’uomo. È molto simile alla sintassi degli oggetti in JavaScript, il che facilita la comprensione da parte degli sviluppatori.

Struttura gerarchica: JSON supporta dati strutturati e gerarchici. Gli oggetti JSON possono contenere altri oggetti o array, consentendo di rappresentare dati complessi in un formato ben organizzato.

Indipendenza dal linguaggio: JSON è indipendente dal linguaggio di programmazione, il che significa che può essere utilizzato in una vasta gamma di linguaggi, tra cui JavaScript, Python, Java, C#, e molti altri.

Ampia adozione: JSON è ampiamente utilizzato in applicazioni web, servizi RESTful, API, e in molte altre situazioni in cui è necessario lo scambio di dati.

Compatibilità con i browser: poiché JSON è nativamente supportato nei browser web, è un formato ideale per la trasmissione di dati tra client e server in applicazioni web.

Rappresentazione dei dati: JSON può rappresentare una varietà di dati, tra cui numeri, stringhe, booleani, oggetti, array e valori null. Questa flessibilità lo rende adatto per una vasta gamma di applicazioni.

Convenienza nell’elaborazione: la natura leggibile di JSON facilita l’elaborazione dei dati sia da parte delle applicazioni che degli sviluppatori umani. Molte lingue offrono librerie o moduli per analizzare e generare dati JSON.

In sintesi, JSON è un formato dati altamente versatile e universalmente accettato che semplifica la comunicazione e lo scambio di dati tra applicazioni eterogenee. La sua semplicità e flessibilità lo rendono uno strumento essenziale per lo sviluppo di applicazioni web e servizi web.

I display TFT

I display TFT (Thin-Film Transistor) rappresentano una categoria di schermi a cristalli liquidi (LCD) avanzati che si sono affermati come una delle tecnologie di visualizzazione più diffuse e versatili. Ecco alcuni punti chiave da considerare:

Qualità delle immagini: i display TFT sono noti per offrire immagini di alta qualità con colori brillanti e dettagli nitidi. Questo li rende ideali per una vasta gamma di applicazioni, dalla visualizzazione di foto e video all’interfaccia utente delle applicazioni.

Retroilluminazione: la maggior parte dei display TFT utilizza retroilluminazione a LED, che fornisce una fonte luminosa uniforme e consente di visualizzare le immagini anche in ambienti luminosi. Questa retroilluminazione è regolabile in base alle esigenze, il che contribuisce a risparmiare energia.

Risoluzione: i display TFT sono disponibili in varie risoluzioni, dalle piccole schermate da 1.8 pollici con risoluzione QVGA alle schermate più grandi con risoluzioni Full HD o superiori. La scelta della risoluzione dipende dalle esigenze specifiche dell’applicazione.

Touchscreen: molti schermi TFT sono dotati di tecnologia touchscreen capacitivo o resistivo, che consente l’interazione diretta dell’utente con il display. Questo è ampiamente utilizzato in dispositivi mobili, tablet, ATM e altri dispositivi interattivi.

Ampia applicabilità: i display TFT sono utilizzati in una vasta gamma di dispositivi, tra cui smartphone, tablet, monitor, televisori, orologi intelligenti, strumenti di diagnostica medica, GPS, dispositivi di automazione industriale e molto altro.

Connessioni e controlli: i display TFT sono progettati per l’integrazione con vari tipi di controller e microcontroller. Ciò li rende ideali per l’implementazione in progetti di elettronica fai da te e applicazioni personalizzate.

Consumo energetico: la tecnologia TFT è progettata per mantenere un basso consumo energetico quando possibile, il che la rende adatta per dispositivi alimentati a batteria.

Scelta del tipo: oltre ai display TFT a colori, esistono anche display TFT in scala di grigi, monocromatici e ad alta luminosità progettati per applicazioni specifiche.

In conclusione, i display TFT sono una scelta popolare e affidabile per molte applicazioni, grazie alla loro qualità dell’immagine, versatilità e facilità di integrazione. Sono diventati parte integrante della nostra vita quotidiana, contribuendo all’esperienza visiva in dispositivi di ogni genere.

Iscrizione al servizio Openweathermap

Prima di tutto ti dovrai iscrivere gratuitamente al servizio Openweathermap. Una volta sulla home page dovrai cliccare sulla voce “Sign in”:

Clicca su Sign in
Clicca su Sign in

Alla pagina successiva clicca su Create an Account:

Clicca su Create an Account
Clicca su Create an Account

Dopo aver completato l’operazione di creazione dell’account vai sulla Home page e clicca su API keys:

Clicca su API keys
Clicca su API keys

Arriverai alla pagina principale da cui dovrai copiare la tua key:

Copia la tua key
Copia la tua key

Conserva questa key perché la dovrai utilizzare successivamente nello sketch che caricherai sulla ESP8266 in modo da essere identificato dal servizio come utente registrato.

Testa l’API di Openweathermap

Per essere sicuri che tutto funzioni correttamente, puoi preventivamente testare l’API di Openweathermap in maniera molto semplice sul tuo browser.

Devi innanzitutto comporre l’url da sottoporre al browser. Essa avrà la seguente struttura:

https://api.openweathermap.org/data/2.5/forecast?q=CITY,COUNTRY&APPID=PERSONAL_KEY&mode=json&units=metric&cnt=3

dove CITY è la città di cui vuoi conoscere le condizioni meteo, COUNTRY è il paese in cui si trova la città, PERSONAL_KEY è la chiave che hai appena salvato dal portale di Openweathermap, mode è il formato di documento restituito (in questo caso un Json), units è il sistema di misurazione (in questo caso il sistema metrico), cnt è il numero di previsioni restituite (in questo caso 3).

Facciamo un esempio con la città di Roma in Italia. L’url sarà:

https://api.openweathermap.org/data/2.5/forecast?q=Roma,IT&APPID=KKKKKKKKKKKKKKKKKK&mode=json&units=metric&cnt=3

Ovviamente ho oscurato la mia chiave privata.

Ho ottenuto come risultato sul mio browser questo documento Json:

{
    "cod": "200",
    "message": 0,
    "cnt": 3,
    "list": [
        {
            "dt": 1697446800,
            "main": {
                "temp": 20.12,
                "feels_like": 19.88,
                "temp_min": 20.12,
                "temp_max": 22.7,
                "pressure": 1014,
                "sea_level": 1014,
                "grnd_level": 1010,
                "humidity": 65,
                "temp_kf": -2.58
            },
            "weather": [
                {
                    "id": 803,
                    "main": "Clouds",
                    "description": "broken clouds",
                    "icon": "04d"
                }
            ],
            "clouds": {
                "all": 75
            },
            "wind": {
                "speed": 2.93,
                "deg": 129,
                "gust": 4.84
            },
            "visibility": 10000,
            "pop": 0.1,
            "sys": {
                "pod": "d"
            },
            "dt_txt": "2023-10-16 09:00:00"
        },
        {
            "dt": 1697457600,
            "main": {
                "temp": 21.09,
                "feels_like": 20.87,
                "temp_min": 21.09,
                "temp_max": 23.03,
                "pressure": 1014,
                "sea_level": 1014,
                "grnd_level": 1010,
                "humidity": 62,
                "temp_kf": -1.94
            },
            "weather": [
                {
                    "id": 500,
                    "main": "Rain",
                    "description": "light rain",
                    "icon": "10d"
                }
            ],
            "clouds": {
                "all": 83
            },
            "wind": {
                "speed": 4.56,
                "deg": 162,
                "gust": 5.58
            },
            "visibility": 10000,
            "pop": 0.27,
            "rain": {
                "3h": 0.47
            },
            "sys": {
                "pod": "d"
            },
            "dt_txt": "2023-10-16 12:00:00"
        },
        {
            "dt": 1697468400,
            "main": {
                "temp": 21.83,
                "feels_like": 21.66,
                "temp_min": 21.83,
                "temp_max": 22.69,
                "pressure": 1013,
                "sea_level": 1013,
                "grnd_level": 1009,
                "humidity": 61,
                "temp_kf": -0.86
            },
            "weather": [
                {
                    "id": 500,
                    "main": "Rain",
                    "description": "light rain",
                    "icon": "10d"
                }
            ],
            "clouds": {
                "all": 92
            },
            "wind": {
                "speed": 4.94,
                "deg": 169,
                "gust": 6.4
            },
            "visibility": 10000,
            "pop": 0.6,
            "rain": {
                "3h": 0.37
            },
            "sys": {
                "pod": "d"
            },
            "dt_txt": "2023-10-16 15:00:00"
        }
    ],
    "city": {
        "id": 3169070,
        "name": "Rome",
        "coord": {
            "lat": 41.8947,
            "lon": 12.4839
        },
        "country": "IT",
        "population": 15000,
        "timezone": 7200,
        "sunrise": 1697433766,
        "sunset": 1697473700
    }
}

da cui possono essere estratte le informazioni che ci servono.

Di che componenti abbiamo bisogno per la nostra stazione meteo con ESP8266 e display TFT?

La lista dei componenti non è particolarmente lunga:

Vediamo nella foto seguente il tipo di display TFT utilizzato in questo progetto:

Il display TFT da 1.8"
Il display TFT da 1.8″

Realizzazione del progetto

Lo schema elettrico

Prima di realizzare il circuito vero e proprio diamo un’occhiata al pinout della board:

Pinout del NodeMCU ESP8266
Pinout del NodeMCU ESP8266

Vediamo anche il pinout del display:

Pinout del display TFT da 1.8"
Pinout del display TFT da 1.8″

Per il nostro progetto prenderemo in considerazione solo i pin sul lato sinistro (con connettore giallo su questa foto).

In genere questo display viene venduto già col connettore montato ma se il tuo non lo dovesse avere e avessi necessità di saldarlo, ti consiglio di dare prima un’occhiata all’articolo Un altro tutorial su come saldare per imparare a fare una perfetta saldatura.

Prima di passare allo schema elettrico dovrai effettuare una piccola operazione. Il display può funzionare sia a 5V che a 3.3V ma siccome i pin digitali dell’ESP8266 non tollerano tensioni più alte di 3.3V dovremo predisporre il display per funzionare con tale tensione.

Per fare ciò dovremo semplicemente cortocircuitare il jumper J1 cioè quello mostrato nella foto seguente:

Jumper J1 da cortocircuitare per far funzionare il display TFT a 3.3V
Jumper J1 da cortocircuitare per far funzionare il display TFT a 3.3V

Come vedi è un’operazione abbastanza semplice: è sufficiente una piccola goccia di stagno per mettere in cortocircuito le due piazzole indicate in rosso.

Vediamo ora lo schema elettrico del progetto, realizzato come al solito con Fritzing:

Lo schema Frintzing della stazione meteo con ESP8266 e display TFT
Lo schema Fritzing della stazione meteo con ESP8266 e display TFT

Per maggiore comodità riporterò di seguito la tabella dei collegamenti:

Display TFTESP8266
1D4
2D3
3D2
4D7
5D5
63V3
73V3
8GND
Collegamenti del display TFT

Lo sketch

Creiamo il progetto PlatformIO

Abbiamo già visto la procedura di creazione di un progetto PlatformIO nell’articolo Come creare un progetto per NodeMCU ESP8266 con PlatformIO.

Non installare le librerie indicate nell’articolo ma installa le seguenti librerie:

La libreria Adafruit GFX Library by Adafruit:

Installa la libreria Adafruit GFX Library
Installa la libreria Adafruit GFX Library

La libreria Adafruit ST7735 and ST7789 Library by Adafruit:

Installa la libreria Adafruit ST7735 and ST7789 Library
Installa la libreria Adafruit ST7735 and ST7789 Library

e la libreria ArduinoJson by Benoit Blanchon:

Installa la libreria ArduinoJson
Installa la libreria ArduinoJson

Ora modifica il file platformio.ini per aggiungere queste due righe:

monitor_speed = 115200
upload_speed = 921600

in modo che abbia un aspetto del genere:

[env:nodemcuv2]
platform = espressif8266
board = nodemcuv2
monitor_speed = 115200
upload_speed = 921600
framework = arduino
lib_deps = 
	adafruit/Adafruit GFX Library@^1.11.9
	adafruit/Adafruit ST7735 and ST7789 Library@^1.10.3
	bblanchon/ArduinoJson@^6.21.3

Ovviamente puoi scaricare il progetto dal link seguente:

Sostituisci il file main.cpp del progetto che hai creato con quello presente nel file zip.

Vediamo ora come funziona lo sketch.

Inizialmente, oltre alla solita Arduino.h, vengono incluse le librerie grafiche di Adafruit per il funzionamento del display, vengono definiti i GPIO su cui collegare il display TFT e viene instanziato l’oggetto tft che gestirà il display.

#include <Arduino.h>+

#include <Adafruit_GFX.h>      // include Adafruit graphics library
#include <Adafruit_ST7735.h>   // include Adafruit ST7735 TFT library

// ST7735 TFT module connections
#define TFT_RST   D4     // TFT RST pin is connected to NodeMCU pin D4 (GPIO2)
#define TFT_CS    D3     // TFT CS  pin is connected to NodeMCU pin D3 (GPIO0)
#define TFT_DC    D2     // TFT DC  pin is connected to NodeMCU pin D2 (GPIO4)

Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

In seguito vengono incluse le librerie per la gestione del WiFi, per il client http che opererà con l’API e quella per la gestione del Json ricevuto. Inoltre vengono definiti i parametri di accesso alla rete WiFi. Quindi, al posto di MY-SSID-WIFI dovrai mettere l’SSID reale della tua rete WiFI mentre al posto di MY-PASSWORD-WIFI dovrai mettere la password reale della tua rete WiFI:

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <ArduinoJson.h>

const char* ssid = "MY-SSID-WIFI";
const char* password = "MY-PASSWORD-WIFI";

Successivamente viene definito l’host di Openweathermap che sarà la base di partenza per l’API, viene definita la città di cui si vogliono conoscere le condizioni meteorologiche e viene inserita la chiave di Openweathermap. Quindi, al posto di MY-OPENWEATHERMAP-KEY dovrai mettere la tua chiave, quella che hai ottenuto dopo esserti iscritto al servizio di Openweathermap.

const char* host = "api.openweathermap.org";

String cityName = "Cagliari";
String appKey = "MY-OPENWEATHERMAP-KEY";

Ora vengono definite alcune variabili di controllo del display, le variabili che regolano le temporizzazioni di richiesta dati (ogni 60 secondi) e di visualizzazione dei dati sul display (ogni 10 secondi) e le variabili che raccolgono i dati dal Json e che verranno visualizzate.

int flagScreen = 0;
int flagFirstData = 1;

int state = 0;

unsigned long measureDelayInternalCycle = 10000;                //    10s
unsigned long lastTimeRanInternalCycle;

unsigned long measureDelayExternalCycle = 60000;                //    60s
unsigned long measureDelayExternalCycleVariable;
unsigned long lastTimeRanExternalCycle;

String line = "";

String tempNow0 = "";
String pressure0 = "";
String humNow0 = "";
String weatherNow0 = "";
String dateNow0 = "";

String tempNow1 = "";
String pressure1 = "";
String humNow1 = "";
String weatherNow1 = "";
String dateNow1 = "";

String tempNow2 = "";
String pressure2 = "";
String humNow2 = "";
String weatherNow2 = "";
String dateNow2 = "";

String tempNow3 = "";
String pressure3 = "";
String humNow3 = "";
String weatherNow3 = "";
String dateNow3 = "";

String tempNow4 = "";
String pressure4 = "";
String humNow4 = "";
String weatherNow4 = "";
String dateNow4 = "";

Segue poi una funzione grafica puramente decorativa che disegna dei rettangoli concentrici all’accensione del dispositivo. Serve solo a fare un po’ di colore!

void testfillrects(uint16_t color1, uint16_t color2) {
  tft.fillScreen(ST7735_BLACK);
  for (int16_t x=tft.width()-1; x > 6; x-=6) {
    tft.fillRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color1);
    tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color2);
  }
}

Le funzioni successive informano l’utente sullo stato della connessione dell’ESP8266 al WiFi:

void tftConnecting() {
  tft.setCursor(0, 0);
  tft.setRotation(3);
  tft.setTextColor(ST7735_RED);
  tft.setTextSize(2);
  tft.println("Connecting...");
  delay(1500);
}

void tftConnected() {
  tft.setCursor(0, 0);
  tft.setRotation(3);
  tft.setTextColor(ST7735_GREEN);
  tft.setTextSize(2);
  tft.println("Connected!");
  delay(2000);
  tft.fillScreen(ST7735_BLACK);
}

Incontriamo ora la funzione setup che inizializza la porta seriale, inizializza il display e mostra i quadrati concentrici, collega l’ESP8266 al WiFi e controlla lo stato di connessione (stampando sul display dei messaggi sullo stato di connessione):

void setup(void) {
  Serial.begin(115200);
  delay(2000);

  tft.initR(INITR_BLACKTAB);
  tft.fillScreen(ST7735_BLACK);

  testfillrects(ST7735_YELLOW, ST7735_MAGENTA);

  WiFi.begin(ssid, password);

  tft.fillScreen(ST7735_BLACK);

  while (WiFi.status() != WL_CONNECTED) 
  {
    delay(1000);
    Serial.println("Connecting...");
    tftConnecting();
  }

  if (WiFi.status() == WL_CONNECTED) 
  {
    Serial.println("CONNECTED");
    tft.fillScreen(ST7735_BLACK);
    tftConnected();
  }
}

Inizia ora la funzione loop.

Inizialmente definisce il client WIFI.

Inoltre, se è la prima volta che viene eseguita (cioè il flagFirstData è 1) mette la variabile measureDelayExternalCycleVariable a 2000 (cioè a 2 secondi) in modo che l’utente non debba aspettare molto per ricevere i primi dati. Infatti il suo valore di default è 60000 (cioè fa una richiesta all’API ogni 60 secondi). Le volte successive la variabile flagFirstData sarà posta a 0 quindi l’api verrà consultata ogni 60 secondi.

WiFiClient client;
if(flagFirstData == 1) {
measureDelayExternalCycleVariable = 2000;
tft.setCursor(0, 0);
tft.setRotation(3);
tft.setTextWrap(true);
tft.setTextColor(ST7735_RED);
tft.setTextSize(2);
tft.println("Wait a few seconds.");
tft.println();
tft.println("I'm receiving the first data.");
} else {
measureDelayExternalCycleVariable = measureDelayExternalCycle;
}

Segue poi il blocco if che, ogni measureDelayExternalCycleVariable ms, contatta l’host, crea l’URL dell’API, riceve i dati in risposta alla sua richiesta (cioè riceve il Json) ed estrae le informazioni dal Json mettendole nelle opportune variabili:

if (millis() > lastTimeRanExternalCycle + measureDelayExternalCycleVariable)  
{


    Serial.printf("\n[Connecting to %s ... ", host);
    if (client.connect(host, 80))
    {

        client.println("GET /data/2.5/forecast?q=" + cityName + "&APPID=" + appKey + "&mode=json&units=metric&cnt=7 HTTP/1.1");
        client.println("Host: api.openweathermap.org");
        client.println("User-Agent: ArduinoWiFi/1.1");
        client.println("Connection: close");
        client.println();
        
        while (client.connected() || client.available())
        {
        if (client.available())
        {
            line = client.readStringUntil('\n');
        }
        }
        client.stop();
    }  
        else
        {
        Serial.println("connection failed!]");
        client.stop();
        }      

        Serial.println("\n");
        Serial.println("-----------------------------------");
        Serial.println(line);
        Serial.println("-----------------------------------");


        int sizeResponse = line.length();

        DynamicJsonDocument doc(sizeResponse);

        deserializeJson(doc, line);

        JsonObject obj = doc.as<JsonObject>();

        String responseCode = obj["cod"];


        if(responseCode == "200") {

        tempNow0 = String(obj["list"][0]["main"]["temp"]);
        humNow0 = String(obj["list"][0]["main"]["humidity"]);
        pressure0 = String(obj["list"][0]["main"]["pressure"]);
        weatherNow0 = String(obj["list"][0]["weather"][0]["description"]);
        dateNow0 = String(obj["list"][0]["dt_txt"]);

        tempNow1 = String(obj["list"][1]["main"]["temp"]);
        humNow1 = String(obj["list"][1]["main"]["humidity"]);
        pressure1 = String(obj["list"][1]["main"]["pressure"]);
        weatherNow1 = String(obj["list"][1]["weather"][0]["description"]);
        dateNow1 = String(obj["list"][1]["dt_txt"]);

        tempNow2 = String(obj["list"][2]["main"]["temp"]);
        humNow2 = String(obj["list"][2]["main"]["humidity"]);
        pressure2 = String(obj["list"][2]["main"]["pressure"]);
        weatherNow2 = String(obj["list"][2]["weather"][0]["description"]);
        dateNow2 = String(obj["list"][2]["dt_txt"]);

        tempNow3 = String(obj["list"][3]["main"]["temp"]);
        humNow3 = String(obj["list"][3]["main"]["humidity"]);
        pressure3 = String(obj["list"][3]["main"]["pressure"]);
        weatherNow3 = String(obj["list"][3]["weather"][0]["description"]);
        dateNow3 = String(obj["list"][3]["dt_txt"]);

        tempNow4 = String(obj["list"][4]["main"]["temp"]);
        humNow4 = String(obj["list"][4]["main"]["humidity"]);
        pressure4 = String(obj["list"][4]["main"]["pressure"]);
        weatherNow4 = String(obj["list"][4]["weather"][0]["description"]);
        dateNow4 = String(obj["list"][4]["dt_txt"]);
        } else {
        tft.fillScreen(ST7735_BLACK);
        tft.setCursor(0, 0);
        tft.setRotation(3);
        tft.setTextWrap(true);
        tft.setTextColor(ST7735_RED);
        tft.setTextSize(2);
        tft.println("Something went wrong!");
        return;
    } 


        flagFirstData = 0;
        lastTimeRanExternalCycle = millis();
    
}

Lo sketch si conclude con un altro blocco if che viene eseguito ogni measureDelayInternalCycle ms (nel nostro caso 10 secondi) che mostra le varie schermate di dati raccolti. Ad ogni giro della funzione loop, la variabile state viene incrementata in modo da far andare lo switch al case successivo. Nel case 4 la variabile state viene azzerata in modo che al giro successivo lo switch si porti nuovamente al case 0:

    String dateMod = "";

    if (millis() > lastTimeRanInternalCycle + measureDelayInternalCycle)  {  

    switch (state) { 	
        case 0: 
        tft.fillScreen(ST7735_BLACK);
        tft.setCursor(0, 0);
        tft.setRotation(3);
        tft.setTextColor(ST7735_GREEN);
        tft.setTextSize(2);
        tft.println(cityName);
        tft.print("T: " + tempNow0);
        tft.println(" C");
        tft.print("H: " + humNow0);
        tft.print(" %");
        tft.println();
        tft.print("P: " + pressure0);
        tft.print(" hP");
        tft.println("\nWeather: ");
        tft.print(weatherNow0);
        tft.println();
        tft.println();
        for (int i = 5; i < dateNow0.length() - 3; i++) {
            dateMod += dateNow0[i];
        }
        dateMod.replace("-", "/");
        tft.println(dateMod);
        state = 1;
        break;
        case 1: 
        tft.fillScreen(ST7735_BLACK);
        tft.setCursor(0, 0);
        tft.setRotation(3);
        tft.setTextColor(ST7735_GREEN);
        tft.setTextSize(2);
        tft.println(cityName);
        tft.print("T: " + tempNow1);
        tft.println(" C");
        tft.print("H: " + humNow1);
        tft.print(" %");
        tft.println();
        tft.print("P: " + pressure1);
        tft.print(" hP");
        tft.println("\nWeather: ");
        tft.print(weatherNow1);
        tft.println();
        tft.println();
        for (int i = 5; i < dateNow1.length() - 3; i++) {
            dateMod += dateNow1[i];
        }
        dateMod.replace("-", "/");
        tft.println(dateMod);
        state = 2;
        break; 
        case 2: 
        tft.fillScreen(ST7735_BLACK);
        tft.setCursor(0, 0);
        tft.setRotation(3);
        tft.setTextColor(ST7735_GREEN);
        tft.setTextSize(2);
        tft.println(cityName);
        tft.print("T: " + tempNow2);
        tft.println(" C");
        tft.print("H: " + humNow2);
        tft.print(" %");
        tft.println();
        tft.print("P: " + pressure2);
        tft.print(" hP");
        tft.println("\nWeather: ");
        tft.print(weatherNow2);
        tft.println();
        tft.println();
        for (int i = 5; i < dateNow2.length() - 3; i++) {
            dateMod += dateNow2[i];
        }
        dateMod.replace("-", "/");
        tft.println(dateMod);
        state = 3;
        break; 
        case 3: 
        tft.fillScreen(ST7735_BLACK);
        tft.setCursor(0, 0);
        tft.setRotation(3);
        tft.setTextColor(ST7735_GREEN);
        tft.setTextSize(2);
        tft.println(cityName);
        tft.print("T: " + tempNow3);
        tft.println(" C");
        tft.print("H: " + humNow3);
        tft.print(" %");
        tft.println();
        tft.print("P: " + pressure3);
        tft.print(" hP");
        tft.println("\nWeather: ");
        tft.print(weatherNow3);
        tft.println();
        tft.println();
        for (int i = 5; i < dateNow3.length() - 3; i++) {
            dateMod += dateNow3[i];
        }
        dateMod.replace("-", "/");
        tft.println(dateMod);
        state = 4;
        break; 
        case 4: 
        tft.fillScreen(ST7735_BLACK);
        tft.setCursor(0, 0);
        tft.setRotation(3);
        tft.setTextColor(ST7735_GREEN);
        tft.setTextSize(2);
        tft.println(cityName);
        tft.print("T: " + tempNow4);
        tft.println(" C");
        tft.print("H: " + humNow4);
        tft.print(" %");
        tft.println();
        tft.print("P: " + pressure4);
        tft.print(" hP");
        tft.println("\nWeather: ");
        tft.print(weatherNow4);
        tft.println();
        tft.println();
        for (int i = 5; i < dateNow4.length() - 3; i++) {
            dateMod += dateNow4[i];
        }
        dateMod.replace("-", "/");
        tft.println(dateMod);
        state = 0;
        break; 
        default: 
        tft.setCursor(0, 0);
        tft.setRotation(3);
        tft.setTextWrap(true);
        tft.setTextColor(ST7735_RED);
        tft.setTextSize(2);
        tft.println("Undefined option");
        break; 
        } 

    lastTimeRanInternalCycle = millis();
}

Ed ecco un bel video dimostrativo della nostra stazione meteorologica in funzione

Come puoi vedere le previsioni sono su base 3 ore. Il display le mostrerà ciclicamente mentre ogni 60 secondi viene aggiornato il Json. L’ultima riga rappresenta mese/giorno ore:minuti (l’anno è stato omesso per problemi di spazio).

Newsletter

Se vuoi essere aggiornato sui nuovi articoli, iscriviti alla newsletter. Prima dell’iscrizione alla newsletter leggi la pagina Privacy Policy (UE)

Se ti vuoi disiscrivere dalla newsletter clicca sul link che troverai nella mail della newsletter.

Inserisci il tuo nome
Inserisci la tua email
0 0 votes
Valutazione articolo
guest
0 Commenti
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
Torna in alto