Nota

Ciao, benvenuto nella community di appassionati SunFounder Raspberry Pi & Arduino & ESP32 su Facebook! Approfondisci Raspberry Pi, Arduino ed ESP32 insieme ad altri appassionati.

Perché unirti?

  • Supporto Esperto: Risolvi problemi post-vendita e sfide tecniche con l’aiuto della nostra community e del team.

  • Impara e Condividi: Scambia suggerimenti e tutorial per migliorare le tue competenze.

  • Anteprime Esclusive: Ottieni accesso anticipato a nuovi annunci di prodotti e anteprime.

  • Sconti Speciali: Approfitta di sconti esclusivi sui nostri prodotti più recenti.

  • Promozioni Festive e Giveaway: Partecipa a giveaway e promozioni festive.

👉 Pronto per esplorare e creare con noi? Clicca [Qui] e unisciti oggi!

WeatherTime Screen

Questo sketch si connette a una rete WiFi, recupera i dati meteo da OpenWeatherMap ogni minuto, ottiene l’ora corrente da un server NTP e visualizza il giorno, l’ora e le informazioni meteorologiche su uno schermo OLED.

Componenti Necessari

In questo progetto, abbiamo bisogno dei seguenti componenti.

È sicuramente conveniente acquistare un kit completo, ecco il link:

Nome

ARTICOLI IN QUESTO KIT

LINK

Elite Explorer Kit

300+

Elite Explorer Kit

È anche possibile acquistarli separatamente dai link sottostanti.

INTRODUZIONE AI COMPONENTI

LINK PER L’ACQUISTO

Arduino Uno R4 WiFi

-

Cavi Jumper

ACQUISTA

Modulo Display OLED

ACQUISTA

Cablaggio

../_images/06_weather_oled_bb.png

Schema

../_images/06_weather_oled_schematic.png

OpenWeather

Ottieni le chiavi API di OpenWeather

OpenWeather è un servizio online, di proprietà di OpenWeather Ltd, che fornisce dati meteorologici globali tramite API, inclusi dati meteorologici attuali, previsioni, nowcast e dati storici per qualsiasi posizione geografica.

  1. Visita OpenWeather per accedere o creare un account.

    ../_images/06_owm_1.png
  2. Clicca sulla pagina delle API dalla barra di navigazione.

    ../_images/06_owm_2.png
  3. Trova Current Weather Data e clicca su Iscriviti.

    ../_images/06_owm_3.png
  4. Sotto Current weather and forecasts collection, iscriviti al servizio appropriato. Nel nostro progetto, la versione gratuita è sufficiente.

    ../_images/06_owm_4.png
  5. Copia la chiave dalla pagina API keys.

    ../_images/06_owm_5.png
  6. Copiala nel file arduino_secrets.h.

    #define SECRET_SSID "<SSID>"        // your network SSID (name)
    #define SECRET_PASS "<PASSWORD>"        // your network password
    #define API_KEY "<OpenWeather_API_KEY>"
    #define LOCATION "<YOUR CITY>"
    
  7. Imposta il fuso orario della tua posizione.

    Prendi la capitale della Svezia, Stoccolma, come esempio. Cerca «fuso orario Stoccolma» su Google.

    ../_images/06_weather_oled_01.png

    Nei risultati della ricerca, vedrai «GMT+1», quindi imposta il parametro della funzione sottostante su 3600 * 1 secondi.

    timeClient.setTimeOffset(3600 * 1);  // Regola per il tuo fuso orario (questo è +1 ora)
    

Installa la Libreria

Per installare la libreria, utilizza il Gestore delle Librerie Arduino e cerca «ArduinoMqttClient», «FastLED», «Adafruit GFX» e «Adafruit SSD1306» e installale.

ArduinoJson.h: Utilizzato per gestire i dati JSON (dati ottenuti da OpenWeatherMap).

NTPClient.h: Utilizzato per ottenere l’ora in tempo reale.

Adafruit_GFX.h, Adafruit_SSD1306.h: Utilizzati per il modulo OLED.

Esegui il Codice

Nota

  • Puoi aprire il file 06_weather_oled.ino nel percorso elite-explorer-kit-main\iot_project\06_weather_oled direttamente.

  • Oppure copia questo codice nell’IDE di Arduino.

Nota

Nel codice, SSID e password sono memorizzati in arduino_secrets.h. Prima di caricare questo esempio, è necessario modificarli con le proprie credenziali WiFi. Inoltre, per motivi di sicurezza, assicurati che queste informazioni siano mantenute riservate durante la condivisione o la memorizzazione del codice.

arduino_secrets.h
#define SECRET_SSID "your_ssid"        // your network SSID (name)
#define SECRET_PASS "your_password"        // your network password (use for WPA, or use as key for WEP)
#define API_KEY "your_key"
#define LOCATION "your_location"
06_weather_oled.ino
  1/*
  2  The code fetches and shows weather information such as temperature, humidity, pressure, 
  3  and wind details. This information is obtained from the OpenWeatherMap API through a WiFi 
  4  connection. The program initially connects to the WiFi network and retrieves the current 
  5  time from an NTP server. It then regularly sends HTTP requests to retrieve weather data 
  6  from the OpenWeatherMap API. Upon receiving a JSON response, it parses the data and displays 
  7  both the weather information and current time on the OLED screen.
  8
  9  Board: Arduino Uno R4 WiFi
 10  Component: OLED
 11  Library: https://github.com/bblanchon/ArduinoJson (ArduinoJson by Benoit Blanchon)
 12           https://github.com/adafruit/Adafruit_SSD1306 (Adafruit SSD1306 by Adafruit)  
 13           https://github.com/adafruit/Adafruit-GFX-Library (Adafruit GFX Library by Adafruit) 
 14           https://github.com/arduino-libraries/NTPClient (NTPClient by Fabrice Weinberg) 
 15           
 16*/
 17
 18#include "WiFiS3.h"
 19#include <ArduinoJson.h>  // JSON decoding library
 20#include "arduino_secrets.h"
 21
 22// NTP client setup to get real-time data
 23#include <NTPClient.h>
 24#include <WiFiUdp.h>
 25WiFiUDP ntpUDP;
 26NTPClient timeClient(ntpUDP, "pool.ntp.org");  // NTP server
 27
 28// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
 29#include <SPI.h>
 30#include <Wire.h>
 31#include <Adafruit_GFX.h>
 32#include <Adafruit_SSD1306.h>
 33#define SCREEN_WIDTH 128  // OLED display width, in pixels
 34#define SCREEN_HEIGHT 64  // OLED display height, in pixels
 35#define OLED_RESET 4      // Reset pin # (or -1 if sharing Arduino reset pin)
 36Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
 37
 38// WiFi credentials and server information
 39char ssid[] = SECRET_SSID;  // your network SSID (name)
 40char pass[] = SECRET_PASS;  // your network password
 41int status = WL_IDLE_STATUS;
 42char server[] = "api.openweathermap.org";  // name address for OWM (using DNS)
 43
 44// Timing variables to manage update intervals
 45unsigned long lastConnectionTime = 0;               // last time you connected to the server, in milliseconds
 46const unsigned long postingInterval = 60L * 1000L;  // delay between updates, in milliseconds
 47
 48// WiFi client for connecting to the API server
 49WiFiClient client;
 50
 51void setup() {
 52  //Initialize serial and wait for port to open:
 53  Serial.begin(9600);
 54  while (!Serial) {
 55    ;  // wait for serial port to connect. Needed for native USB port only
 56  }
 57
 58  // check for the WiFi module:
 59  if (WiFi.status() == WL_NO_MODULE) {
 60    Serial.println("Communication with WiFi module failed!");
 61    // don't continue
 62    while (true)
 63      ;
 64  }
 65
 66  String fv = WiFi.firmwareVersion();
 67  if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
 68    Serial.println("Please upgrade the firmware");
 69  }
 70
 71  // attempt to connect to WiFi network:
 72  while (status != WL_CONNECTED) {
 73    Serial.print("Attempting to connect to SSID: ");
 74    Serial.println(ssid);
 75    status = WiFi.begin(ssid, pass);
 76    delay(5000);  // Wait 5 seconds before retrying
 77  }
 78
 79  printWifiStatus();
 80
 81  // Initialize and clear OLED display
 82  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
 83  display.display();
 84  display.clearDisplay();
 85
 86  // Initialize and clear OLED display
 87  timeClient.begin();
 88  timeClient.setTimeOffset(3600 * 8);  // Adjust for your time zone (this is +8 hour)
 89}
 90
 91void loop() {
 92
 93  read_response();
 94  timeClient.update();
 95
 96  // Check if it's time to send a new request
 97  if (!lastConnectionTime || millis() - lastConnectionTime > postingInterval) {
 98    httpRequest();
 99  }
100}
101
102
103void read_response() {
104  uint32_t received_data_num = 0;
105  String payload = "";
106  bool jsonDetected = false;
107
108  // Read data from the client connection
109  while (client.available()) {
110    /* actual data reception */
111    char c = client.read();
112    
113    // for debug
114    Serial.print(c);
115    
116    if ('{' == c) {
117      jsonDetected = true;
118    }
119    if (jsonDetected) {
120      payload += c;
121    }
122    received_data_num++;
123  }
124  if (jsonDetected) {
125    /* print data to serial port */
126    // Serial.print("data num : ");
127    // Serial.println(received_data_num);
128    // Serial.print("data : ");
129    // Serial.println(payload);
130    DynamicJsonDocument root(1024);
131    DeserializationError error = deserializeJson(root, payload);
132    if (error) {
133      Serial.print("Deserialization failed with code: ");
134      Serial.println(error.c_str());
135      return;
136    }
137
138    String weather = (root["weather"][0]["main"]);
139    float temp = (float)(root["main"]["temp"]) - 273.15;        // get temperature in °C
140    int humidity = root["main"]["humidity"];                    // get humidity in %
141    float pressure = (float)(root["main"]["pressure"]) / 1000;  // get pressure in bar
142    float wind_speed = root["wind"]["speed"];                   // get wind speed in m/s
143    int wind_degree = root["wind"]["deg"];                      // get wind degree in °
144
145    // // print data
146    // Serial.println("Temperature= " + String(temp) + " °C");
147    // Serial.println("Humidity = " + String(humidity) + " %");
148    // Serial.println("Pressure = " + String(pressure) + " bar");
149    // Serial.println("Wind speed = " + String(wind_speed) + " m/s");
150    // Serial.println("Wind degree = " + String(wind_degree) + " °");
151    displayWeatherData(weather, temp, humidity, pressure, wind_speed);
152  }
153}
154
155
156void httpRequest() {
157  // close any connection before send a new request.
158  client.stop();
159
160  // Construct HTTP GET request for OpenWeatherMap API
161  String httpRequest = "";
162  httpRequest += "GET /data/2.5/weather?q=" LOCATION "&APPID=" API_KEY " HTTP/1.1";
163
164  // if you get a connection, report back via serial:
165  if (client.connect(server, 80)) {
166    Serial.println("connected");
167    // Make a HTTP request:
168    client.println(httpRequest);
169    client.println("Host: api.openweathermap.org");
170    client.println("Connection: close");
171    client.println();
172    // note the time that the connection was made:
173    lastConnectionTime = millis();
174  } else {
175    // if you couldn't make a connection:
176    Serial.println("connection failed");
177  }
178}
179
180void printWifiStatus() {
181  // print the SSID of the network you're attached to:
182  Serial.print("SSID: ");
183  Serial.println(WiFi.SSID());
184
185  // print your board's IP address:
186  IPAddress ip = WiFi.localIP();
187  Serial.print("IP Address: ");
188  Serial.println(ip);
189
190  // print the received signal strength:
191  long rssi = WiFi.RSSI();
192  Serial.print("signal strength (RSSI):");
193  Serial.print(rssi);
194  Serial.println(" dBm");
195}
196
197void displayWeatherData(String weather, float temp, int humidity, float pressure, float wind_speed) {
198  display.clearDisplay();
199  display.setTextSize(1);               // Normal 1:1 pixel scale
200  display.setTextColor(SSD1306_WHITE);  // Draw white text
201  display.setCursor(0, 0);              // Start at top-left corner
202
203  // Display Day of the Week
204  String daysOfTheWeek[7] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
205  display.print(daysOfTheWeek[timeClient.getDay()]);
206
207  display.print(" ");
208  if (timeClient.getHours() < 10) display.print("0");  // Add leading zero for hours < 10
209  display.print(timeClient.getHours());
210  display.print(":");
211  if (timeClient.getMinutes() < 10) display.print("0");  // Add leading zero for minutes < 10
212  display.println(timeClient.getMinutes());
213
214  display.println();
215  display.print(LOCATION);
216  display.println(" " + weather);
217
218  // Display Weather
219  display.print("Temperature: ");
220  display.print(temp);
221  display.println(" C");
222
223  display.print("Humidity: ");
224  display.print(humidity);
225  display.println(" %");
226
227  display.print("Pressure: ");
228  display.print(pressure);
229  display.println(" bar");
230
231  display.print("Wind: ");
232  display.print(wind_speed);
233  display.println(" m/s");
234
235  display.display();
236}

Come Funziona?

  1. Librerie e Definizioni:

    1. WiFiS3.h: Probabilmente una libreria specifica per un modulo WiFi o una scheda per gestire le connessioni WiFi.

    2. ArduinoJson.h: Questa libreria è utilizzata per decodificare (e codificare) dati JSON.

    3. arduino_secrets.h: Un file separato in cui sono memorizzati i dati sensibili (come le credenziali WiFi). Questa è una buona pratica per mantenere le credenziali fuori dal codice principale.

    4. NTPClient & WiFiUdp: Sono utilizzati per recuperare l’ora corrente da un server NTP (Network Time Protocol).

    5. Librerie Adafruit: Utilizzate per gestire il display OLED.

    6. Varie variabili globali: Includono le credenziali WiFi, i dettagli del server e altro, che saranno utilizzati durante tutto il programma.

  2. setup():

    1. Inizializza la comunicazione seriale.

    2. Controlla e stampa la versione del firmware del modulo WiFi.

    3. Tenta di connettersi alla rete WiFi utilizzando l’SSID e la password forniti.

    4. Stampa lo stato della connessione WiFi (SSID, IP, Intensità del segnale).

    5. Inizializza il display OLED.

    6. Avvia il client NTP per recuperare l’ora corrente e imposta un offset temporale (in questo caso, 1 ora, che potrebbe corrispondere a un fuso orario specifico).

  3. read_response():

    1. Legge la risposta dal server, cercando specificamente dati JSON (denotati da { e }).

    2. Se vengono trovati dati JSON, li decodifica per estrarre dettagli meteo come temperatura, umidità, pressione, velocità del vento e direzione del vento.

    3. Chiama la funzione displayWeatherData per visualizzare le informazioni meteorologiche sullo schermo OLED.

  4. httpRequest():

    1. Chiude eventuali connessioni esistenti per garantire che il socket del modulo WiFi sia libero.

    2. Tenta di connettersi al server OpenWeatherMap.

    3. Se connesso, invia una richiesta GET HTTP per recuperare i dati meteorologici per una specifica posizione definita da LOCATION (probabilmente definita in arduino_secrets.h o altrove).

    4. Registra l’ora in cui è stata effettuata la richiesta.

  5. loop():

    1. Chiama la funzione read_response per elaborare eventuali dati in arrivo dal server.

    2. Aggiorna l’ora dal server NTP.

    3. Verifica se è il momento di effettuare un’altra richiesta al server meteorologico (basato sull’intervallo di pubblicazione, postingInterval). Se sì, chiama la funzione httpRequest.

  6. printWifiStatus():

    1. Stampa l’SSID della rete connessa.

    2. Stampa l’indirizzo IP locale della scheda.

    3. Stampa l’intensità del segnale (RSSI).

  7. displayWeatherData():

    1. Cancella lo schermo OLED.

    2. Visualizza il giorno della settimana corrente.

    3. Visualizza l’ora corrente nel formato HH:MM.

    4. Visualizza i dati meteorologici forniti (temperatura, umidità, pressione e velocità del vento).