Bemerkung

Hallo und willkommen in der SunFounder Raspberry Pi & Arduino & ESP32 Enthusiasten-Gemeinschaft auf Facebook! Tauchen Sie tiefer ein in die Welt von Raspberry Pi, Arduino und ESP32 mit anderen Enthusiasten.

Warum beitreten?

  • Expertenunterstützung: Lösen Sie Nachverkaufsprobleme und technische Herausforderungen mit Hilfe unserer Gemeinschaft und unseres Teams.

  • Lernen & Teilen: Tauschen Sie Tipps und Anleitungen aus, um Ihre Fähigkeiten zu verbessern.

  • Exklusive Vorschauen: Erhalten Sie frühzeitigen Zugang zu neuen Produktankündigungen und exklusiven Einblicken.

  • Spezialrabatte: Genießen Sie exklusive Rabatte auf unsere neuesten Produkte.

  • Festliche Aktionen und Gewinnspiele: Nehmen Sie an Gewinnspielen und Feiertagsaktionen teil.

👉 Sind Sie bereit, mit uns zu erkunden und zu erschaffen? Klicken Sie auf [ hier ] und treten Sie heute bei!

WeatherTime Bildschirm

Dieser Sketch verbindet sich mit einem WLAN-Netzwerk, holt jede Minute Wetterdaten von OpenWeatherMap ab, holt die aktuelle Zeit von einem NTP-Server und zeigt den Tag, die Zeit und die Wetterinformationen auf einem OLED-Bildschirm an.

Benötigte Komponenten

Für dieses Projekt benötigen wir die folgenden Komponenten.

Es ist definitiv praktisch, ein ganzes Kit zu kaufen, hier ist der Link:

Name

ARTIKEL IN DIESEM KIT

LINK

Elite Explorer Kit

300+

Elite Explorer Kit

Sie können sie auch separat über die untenstehenden Links kaufen.

KOMPONENTENBESCHREIBUNG

KAUF-LINK

Arduino Uno R4 WiFi

-

Jumperkabel

KAUFEN

OLED-Display-Modul

KAUFEN

Verdrahtung

../_images/06_weather_oled_bb.png

Schaltplan

../_images/06_weather_oled_schematic.png

OpenWeather

OpenWeather API-Schlüssel erhalten

OpenWeather ist ein Online-Dienst von OpenWeather Ltd, der weltweite Wetterdaten über eine API bereitstellt, einschließlich aktueller Wetterdaten, Prognosen, Nowcasts und historischer Wetterdaten für jeden geografischen Standort.

  1. Besuchen Sie OpenWeather, um sich anzumelden/ein Konto zu erstellen.

    ../_images/06_owm_1.png
  2. Klicken Sie in der Navigationsleiste auf die API-Seite.

    ../_images/06_owm_2.png
  3. Finden Sie Current Weather Data und klicken Sie auf Abonnieren.

    ../_images/06_owm_3.png
  4. Unter Current weather and forecasts collection abonnieren Sie den entsprechenden Dienst. In unserem Projekt reicht die kostenlose Version aus.

    ../_images/06_owm_4.png
  5. Kopieren Sie den Schlüssel von der Seite API keys.

    ../_images/06_owm_5.png
  6. Kopieren Sie ihn in die 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. Stellen Sie die Zeitzone Ihres Standorts ein.

    Nehmen Sie als Beispiel die Hauptstadt Schwedens, Stockholm. Suchen Sie auf Google nach „Stockholm Zeitzone“.

    ../_images/06_weather_oled_01.png

    In den Suchergebnissen sehen Sie „GMT+1“, also setzen Sie den Parameter der untenstehenden Funktion auf 3600 * 1 Sekunden.

    timeClient.setTimeOffset(3600 * 1);  // Adjust for your time zone (this is +1 hour)
    

Bibliothek installieren

Um die Bibliothek zu installieren, verwenden Sie den Arduino-Bibliotheksmanager und suchen Sie nach „ArduinoMqttClient“, „FastLED“, „Adafruit GFX“ und „Adafruit SSD1306“ und installieren Sie diese.

ArduinoJson.h: Wird verwendet, um JSON-Daten zu verarbeiten (Daten, die von openweathermap erhalten werden).

NTPClient.h: Wird verwendet, um die Echtzeit zu erhalten.

Adafruit_GFX.h, Adafruit_SSD1306.h: Wird für das OLED-Modul verwendet.

Code ausführen

Bemerkung

  • Sie können die Datei 06_weather_oled.ino direkt unter dem Pfad elite-explorer-kit-main\iot_project\06_weather_oled öffnen.

  • Oder kopieren Sie diesen Code in die Arduino IDE.

Bemerkung

Im Code werden SSID und Passwort in arduino_secrets.h gespeichert. Bevor Sie dieses Beispiel hochladen, müssen Sie sie mit Ihren eigenen WLAN-Anmeldeinformationen ändern. Außerdem sollten Sie aus Sicherheitsgründen diese Informationen vertraulich halten, wenn Sie den Code teilen oder speichern.

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}

Wie funktioniert des?

  1. Bibliotheken und Definitionen:

    1. WiFiS3.h: Dies ist wahrscheinlich eine spezifische Bibliothek für ein bestimmtes WLAN-Modul oder Board zur Verwaltung von WLAN-Verbindungen.

    2. ArduinoJson.h: Diese Bibliothek wird für das Dekodieren (und Kodieren) von JSON-Daten verwendet.

    3. arduino_secrets.h: Eine separate Datei, in der sensible Daten (wie WLAN-Zugangsdaten) gespeichert sind. Dies ist eine gute Praxis, um Zugangsdaten aus dem Hauptcode herauszuhalten.

    4. NTPClient & WiFiUdp: Diese werden verwendet, um die aktuelle Zeit von einem NTP-Server (Network Time Protocol) zu holen.

    5. Adafruit-Bibliotheken: Verwendet für die Verwaltung des OLED-Displays.

    6. Verschiedene globale Variablen: Dazu gehören WLAN-Zugangsdaten, Serverdetails und mehr, die im gesamten Skript verwendet werden.

  2. setup():

    1. Initialisiert die serielle Kommunikation.

    2. Überprüft und druckt die Firmware-Version des WLAN-Moduls aus.

    3. Versucht, eine Verbindung zum WLAN-Netzwerk mit der bereitgestellten SSID und dem Passwort herzustellen.

    4. Gibt den Status des verbundenen WLANs aus (SSID, IP, Signalstärke).

    5. Initialisiert das OLED-Display.

    6. Startet den NTP-Client, um die aktuelle Zeit zu holen und legt einen Zeitversatz fest (in diesem Fall 8 Stunden, was einer bestimmten Zeitzone entsprechen könnte).

  3. read_response():

    1. Liest die Antwort vom Server, insbesondere auf der Suche nach JSON-Daten (gekennzeichnet durch { und }).

    2. Wenn JSON-Daten gefunden werden, werden die Daten dekodiert, um Wetterdetails wie Temperatur, Feuchtigkeit, Druck, Windgeschwindigkeit und Windrichtung zu extrahieren.

    3. Ruft die Funktion displayWeatherData auf, um die Wetterinformationen auf dem OLED-Bildschirm anzuzeigen.

  4. httpRequest():

    1. Schließt alle bestehenden Verbindungen, um sicherzustellen, dass der Socket des WLAN-Moduls frei ist.

    2. Versucht, eine Verbindung zum OpenWeatherMap-Server herzustellen.

    3. Wenn verbunden, sendet es eine HTTP-GET-Anfrage, um die Wetterdaten für einen spezifischen Ort zu holen, der durch LOCATION definiert wird (wahrscheinlich definiert in arduino_secrets.h oder anderswo).

    4. Zeichnet die Zeit auf, zu der die Anfrage gestellt wurde.

  5. loop():

    1. Ruft die Funktion read_response auf, um alle eingehenden Daten vom Server zu verarbeiten.

    2. Aktualisiert die Zeit vom NTP-Server.

    3. Überprüft, ob es Zeit ist, eine weitere Anfrage an den Wetter-Server zu stellen (basierend auf dem postingInterval). Wenn ja, ruft es die Funktion httpRequest auf.

  6. printWifiStatus():

    1. Die SSID des verbundenen Netzwerks.

    2. Die lokale IP-Adresse des Boards.

    3. Die Signalstärke (RSSI).

  7. displayWeatherData():

    1. Löscht den OLED-Bildschirm.

    2. Zeigt den aktuellen Wochentag an.

    3. Zeigt die aktuelle Uhrzeit im HH:MM-Format an.

    4. Zeigt die bereitgestellten Wetterdaten an (Temperatur, Feuchtigkeit, Druck und Windgeschwindigkeit).