ESP32 Project: Weather forecast display

ESP32 project: display for weather forecast

 

How will the weather be tomorrow and the day after tomorrow? The classic weather station projects that you see in the scene can not say anything about it, because they only display and log the current temperature values. We choose a different approach here: With the ESP32 (https://az-delivery.de/products/esp32-developmentboard) we download the weather forecast for the next five days from https://openweathermap.org  and show them on a small OLED display (https://az-delivery.de/products/0-96zolldisplay) on.

 

The project is implemented in three sections: (1) preparation of the hardware, (2) generation of an API key for OpenWeatherMap to access data, and (3) software for downloading and displaying the weather forecast.

 

hardware

 

 

The display is connected to the ESP32 with 3.3 V and GND. For the I²C connection, SCL are also connected to G22 and SDA to G21. The following figure shows the fully wired hardware.

Graphics can even be shown on the mini display. With the sample sketches from the library, these are just a few clicks away.

 

Graphics can even be shown on the mini display. With the sample sketches from the library, these are just a few clicks away.

 

Openweathermap API

OpenWeatherMap is an IT company that provides weather data. On a small scale even free of charge. To get weather data you have to send HTTP requests to the OpenWeatherMap API (https://openweathermap.org/forecast5) send. This requires authentication using an API key. You can get your API key on the price page (https://openweathermap.org/price). For example, it looks like this:


a254362gegeg715dce096a37b32c17aa

 

 

If you now have the URL in the browser http://api.openweathermap.org/data/2.5/forecast?q=Karlsruhe,de&appid=a254362gegeg715dce096a37b32c17aa  , you will get the weather forecast for Karlsruhe for the next five days. In the URL, replace Karlsruhe with the name of your city and the API key behind appid =  through your.

 

The data returned is in JSON format. The attribute temp gives the predicted temperature in Kelvin for the time German  on. The latter is a Unix timestamp, which is once again in readable form as dt_txt  is sent along. Example for starting a response:

 

{
cod: "200",
message: 0.0447,
cnt: 40,
list: [
   {
     German: 1503241200,
main: {
       temp: 293.69,
temp_min: 293.69,
temp_max: 293.738,
pressure: 1017.16,
sea_level: 1037.44,
grnd_level: 1017.16,
humidity: 53,
temp_kf: -0.05
     },
weather: [
       {
id: 800,
main: "Clear",
description: "clear sky",
icon: "01d"
       }
     ],
clouds: {
all: 0
     }, [...]

 

 

software

This section outlines how the program works. For a deeper understanding, take a look at the code (https://github.com/Simsso/Microcontroller-Examples/tree/master/ESP32/WeatherDisplay) essential. The project files do the following:

  • WeatherDisplay.ino: Arduino-Sketch, Main program: Connects all components.
  • OpenWeatherMapAPI.h: OpenWeatherMap API header file: Defines how the OpenWeatherMap can be accessed.
  • OpenWeatherMapAPI.cpp: OpenWeatherMap API code file: implements the methods of the previous header file.
  • OLEDScreen.h: OLED screen header file: Controls the OLED display and outputs the weather data graphically.
  • WeatherForecastSample.cpp: Weather forecast sample: Class that represents a single weather forecast.

 

API access with the ESP32

In order to display the weather information, the ESP32 must receive the data listed above in part from the OpenWeatherMap API. Because of its length, the code for downloading and reading is in separate C ++ files that are included in the main ketch #include  be involved. In order to be able to run the sample program, you must have the entire folder content of https://github.com/Simsso/Microcontroller-Examples/tree/master/ESP32/WeatherDisplay download and then open the .ino file with the Arduino IDE. The program downloads weather data at regular intervals (2 hours by default). These are shared with the ArduinoJson Library (https://github.com/bblanchon/ArduinoJson/) parsed, that is, read so that they can be used in the program.

 

To be able to put the code into operation you have to install the libraries

  • Enter your WLAN SSID and password (file WeatherDisplay.ino),
  • update the city for which a forecast is to be made (file WeatherDisplay.ino, variable query) and
  • enter a valid OpenWeatherMap API key (file WeatherDisplay.ino, variable apiKey).

 

Display the weather forecast

The display that shows the downloaded weather data can be controlled, for example, with the Ai_Ardulib_SSD1306 library (https://github.com/acrobotic/Ai_Ardulib_SSD1306). At the time of publication of this post, this contained a bug that was fixed in this pull request: https://github.com/barbeque/Ai_Ardulib_SSD1306/tree/patch-1. To be on the safe side, download the code from the latter link.

 

In the current version, the WeatherDisplay program shows the weather forecast in plain form, i.e. without further formatting. You are cordially invited to prettify the display with cloud / sun graphics, for example. http://www.instructables.com/id/Display-Images-on-OLED-Screen-With-Arduino-ATtiny8/.

 

With this weather forecast - 13 ° C - playing around with the ESP32 is simply the best thing to do.

DisplaysEsp-32Projects for beginners

27 comments

Yuu

Yuu

Vielen Dank für den Artikel, hat bei mir wunderbar geklappt :)

Warum es bei manchen nicht geklappt hat weiß ich nicht, ich stellte mich als totaler Anfänger nur etwas an mit den Installieren der richtigen Liberies. Auf geheiß mancher Kommentare hab ich ArduinoJson 5.10 installieren lassen statt 6, keine Ahnung ob es mit 6 auch genauso gut klappt.

Hab rechts am Display nur diverse Pixel… Pixelfehler? Sieht etwas schmutzig aus aber sonst erkennt man alles gut. Vielleicht probiere ich mal das ganze an größere Displays.

JP

JP

Dieses Projekt ist das erste mit WIFI und ESP32 für mich. Ich fand die Idee spannend und habe mich nun etliche Stunden damit beschäftigt. Ich habe die Treiber installiert, das Board richtig im IDE angemeldet und den Sketch samt Libraries nun auch übertragen kommen.
Dennoch läuft es noch nicht. Ich bekomme zwar den Versuch angezeigt, dass die Kommunikation nach außen passieren soll, im IDE wird “connecting…connecting…” angezeigt, aber denn laufe ich immer auf einen Timeout. Dies Wifi Zugangsdaten sind es definitiv nicht und so komme ich also nicht weiter.
Kann jemand helfen?

Johannes Sock

Johannes Sock

Hi Horst,
danke für deinen Kommentar v. 12.03.. Die ArduinoJson Lib Version 5 hat mir bisher auch noch nicht weiter geholfen, wobei ich den Verdacht habe, dass sich hier noch ein Problem mit der Ai_Ardulib_SSD1306 Library auftut, zumal der Link auf https://github.com/barbeque/Ai_Ardulib_SSD1306/tree/patch-1 lt. Projektbeschreibung (soll einen Bugfix beinhalten) nicht funktioniert. Alles in allem muss ich feststellen, dass dieses Projekt für Anfänger wie mich eine Nummer zu hoch zu sein scheint. Schade drum, aber ich werfe hier zur Zeit das Handtuch.
Eine überarbeitete ausgereifte Installationsanweisung mit aktuellen und korrekten Downloadlinks wäre schon toll.
LG Johannes

Horst Koch

Horst Koch

Hallo Johannes,
ich bin auch Anfänger und habe mich mit der Software ziemlich “abgequält”. Funktioniert hat einfach die Installation der ArduinoJson Lib Version 5, also die alte Version vor dem Compilieren.

Viele Grüße
Horst

edu

edu

Gibt es bereits ein ausgeführtes Projekt mit einem seriellen Feinstaubsensor am ESP32 der per WLAN die Daten an eine z.b. Handy oder PC-App oder direkt per WLAN an eine entfernte Datenbank sendet?

danke f. eine Info – edu

Thomas

Thomas

Läuft das nicht irgendwie in ein Wetterabo? Die FreeCalls sind doch begrenzt.
Zitat
We accumulate the total number of calls from all the API keys that belong to your account.
When your account exceeds the limit, we do not block your account immediately but send you an automatic notification by email asking you to switch to one of our paid subscriptions within the reasonable term. If we do not get any feedback from you, we suspend your account. To renew your account, contact us
Zitat Ende

Johannes Sock

Johannes Sock

Kann mich Uli Engel nur anschließen. Das Projekt scheitert bei mir ann der Compilerei mit der Fehlermeldung
Arduino: 1.8.12 (Windows 10), Board: “ESP32 Dev Module, Disabled, Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS), 240MHz (WiFi/BT), QIO, 80MHz, 4MB (32Mb), 921600, None”

OpenWeatherMapAPI.cpp:13:11: error: DynamicJsonBuffer is a class from ArduinoJson 5. Please see arduinojson.org/upgrade to learn how to upgrade your program to ArduinoJson version 6

DynamicJsonBuffer jsonBuffer(20000); // response body size is usually around 15 kByte ^

OpenWeatherMapAPI.cpp:13:29: error: expected constructor, destructor, or type conversion before ‘(’ token

DynamicJsonBuffer jsonBuffer(20000); // response body size is usually around 15 kByte ^

sketch\OpenWeatherMapAPI.cpp: In static member function ‘static ArduinoJson::JsonObject* OpenWeatherMapAPI::getData(String, String)’:

OpenWeatherMapAPI.cpp:102:22: error: ‘jsonBuffer’ was not declared in this scope

JsonObject& root = jsonBuffer.parseObject(resBody); ^

OpenWeatherMapAPI.cpp:103:13: error: ‘ArduinoJson::JsonObject {aka class ArduinoJson6141_0000010::ObjectRef}’ has no member named ‘success’

if (!root.success()) { ^

Mehrere Bibliotheken wurden für “WiFi.h” gefunden
Benutzt: C:\Users\Socke\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\libraries\WiFi
Nicht benutzt: C:\Program Files (x86)\Arduino\libraries\WiFi
exit status 1
DynamicJsonBuffer is a class from ArduinoJson 5. Please see arduinojson.org/upgrade to learn how to upgrade your program to ArduinoJson version 6

Ungültige Bibliothek C:\Users\Socke\Documents\Arduino\libraries\Microcontroller-Examples-master in keine Header-Dateien (.h) in C:\Users\Socke\Documents\Arduino\libraries\Microcontroller-Examples-master gefunden gefunden
Ungültige Bibliothek C:\Users\Socke\Documents\Arduino\libraries\Microcontroller-Examples-master in keine Header-Dateien (.h) in C:\Users\Socke\Documents\Arduino\libraries\Microcontroller-Examples-master gefunden gefunden

Dieser Bericht wäre detaillierter, wenn die Option
“Ausführliche Ausgabe während der Kompilierung”
in Datei → Voreinstellungen aktiviert wäre.

Scheint ein Problem mit der ArduinoJson.h-Datei in der Version 5 zu sein.
Wer hat hier schon eine Lösung gefunden, die einem Neuling in diesem Metier weiter helfen kann?
Ich wäre hierfür sehr dankbar, da ich dadurch vielleicht etwas mehr über die Codierung lernen könnte.
Gruß Johannes

Michael

Michael

Kann ich das Projekt auch mit einem ESP8266 umsetzen?
Was muss ich ändern?

Ulli Engel

Ulli Engel

Hallo,
kann man auch einen ESP8266 verwenden?
Was muss ich dann ggf. anpassen?

Danke

Ulli Engel

Ulli Engel

Hi,
ich lese den Blog regelmäßig und habe heute diese Wetterstations-Anleitung darin gefunden. Vielleicht ist dieser Blog nur für Profis gedacht. Mich interessiert aber dieses Thema und ich würde es gerne nachbauen. Doch für einen Anfänger wie ich es bin ist die Darstellung sehr kurz (zu kurz). Und wenn ich die Kommentare der Profis lese, frage ich mich, wie Anfänger hier zu einem gewünschte “Erlebnis” kommen sollen. Ich würde mich über mehr Ausführlichkeit mit mehr Informationen freuen.
Gruß Ulli

Gerhart Ullmann

Gerhart Ullmann

Hallo,
könntet Ihr bitte die Gelbe Schriftfarbe in Blau oder Rotändern? Das wäre deutlich besser zu sehen.
Gruß
Gerhart

Thomas

Thomas

Und diese Datei noch: OpenWeatherMapAPI.h

—snip

#include
#include “SSD1306.h”

#include “WeatherForecastSample.cpp”

class OpenWeatherMapAPI
{
public:
static void init(const char* ssid, const char* password);
static bool getForecast(
String query,
String appId,
WeatherForecastSample** forecast,
int* count);

private:
//static JsonObject* getData(String query, String appId);
static JsonObject getData(String query, String appId);

static String getResponse(String query, String appId);

};

#endif

—snap

Thomas

Thomas

Hallo,

evtl, das mal testen, wenn ArduinoJson Lib 6.10.1

Datei: OpenWeatherMapAPI.cpp

—snip

#include
#include
#include

#include “OpenWeatherMapAPI.h”
#include “WeatherForecastSample.cpp”

const char *owmApiHost = “api.openweathermap.org”;
const uint64_t timeout = 5000; // [ms]

DynamicJsonDocument jDoc(30000);

void OpenWeatherMapAPI::init(const char* ssid, const char* password)
{
Serial.println("Connecting to " + String(ssid));
WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) { } Serial.println("Connected with IP address " + WiFi.localIP().toString());

};

bool OpenWeatherMapAPI::getForecast(String query, String appId, WeatherForecastSample** forecast, int* count)
{
//const JsonObject* root = OpenWeatherMapAPI::getData(query, appId);
//const
JsonObject root = OpenWeatherMapAPI::getData(query, appId);
if (root.isNull()) return false;

*count = 20; forecast = new WeatherForecastSample[count]; for (int i = 0; i < *count; i++) { (*forecast)[i].dt = (root)[“list”][i][“dt”].as(); (*forecast)[i].temp = (root)[“list”][i][“main”][“temp”].as(); (*forecast)[i].description = (root)[“list”][i][“weather”]0[“description”].as(); (*forecast)[i].dtTxt = (root)[“list”][i][“dt_txt”].as(); if ((*forecast)[i].dtTxt.length() == 0) { *count = i; break; } } Serial.println("Forecast data parsed "); return true;

};

String OpenWeatherMapAPI::getResponse(String query, String appId)
{
WiFiClient client;
const int httpPort = 80;
if (!client.connect(owmApiHost, httpPort)) {
Serial.println(“Connection failed”);
return "";
}

String path = “/data/2.5/forecast?q=” + query + “&appid=” + appId; client.print( “GET " + path + " HTTP/1.1\r\n" + “Host: " + owmApiHost + “\r\n” + “Connection: close\r\n” + “Pragma: no-cache\r\n” + “Cache-Control: no-cache\r\n” + “User-Agent: ESP32\r\n” + “Accept: text/html,application/json\r\n\r\n”); uint64_t startMillis = millis(); while (client.available() == 0) { if (millis() – startMillis > timeout) { Serial.println(“Client timeout”); client.stop(); return ""; } } String resHeader = "", resBody = ""; bool receivingHeader = true; while(client.available()) { String line = client.readStringUntil(‘\r’); if (line.length() == 1 && resBody.length() == 0) { receivingHeader = false; continue; } if (receivingHeader) { resHeader += line; } else { resBody += line; } } client.stop(); Serial.print("Data received successfully (request body size: " + String(resBody.length()) + " bytes)"); Serial.println(resBody); return resBody;

};

JsonObject OpenWeatherMapAPI::getData(String query, String appId)
{
String resBody = OpenWeatherMapAPI::getResponse(query, appId);
const int contentLength = resBody.length();
JsonObject root;

if (contentLength > 0) { // parse JSON DeserializationError error = deserializeJson(jDoc, resBody); if (error) { Serial.println(error.c_str()); Serial.println(“return nullptr”); return root; //nullptr; } else { Serial.println(error.c_str()); root = jDoc.as(); Serial.println(“return &root”); //return &root; return root; } } return root; //nullptr;

};

—snap

Peter Pi.

Peter Pi.

Nachtrag: Mit der Version 5 der ArduinoJson Lib läuft es. Es gibt auch eine Anleitung zum Update von V5 auf V6.

Peter Pi.

Peter Pi.

Scheint mit den o.a. Quellen nicht zu kompilieren, weil die lib von version 5 auf 6 ein upgrade bekommen hat.

“DynamicJsonBuffer is a class from ArduinoJson 5. Please see arduinojson.org/upgrade to learn how to upgrade your program to ArduinoJson version 6”

Ich wollte das nur schnell zusammenbauen und probieren, da die Hardware bereits vorliegt, also wenn jemand Rat weiß, Danke!

Peter F.

Peter F.

Interessanter Ansatz, jedoch ist openwether hier ein Overkill
Mit wttr.in wäre es einfacher und man bekommt eine kleine Grafik dazu.
Wer würde es versuchen, bin leider selbst kein Programmierer?

Joerg

Joerg

Und wenn man openweathermap auf deutsch umstellt, kommen die Umlaute nicht richtig raus. Hat jemand einen Vorschlag?

Wolfgang

Wolfgang

Schade, dass alles ausverkauft ist! Hätte es gerne nachgebaut.

Wolfgang Noel

Wolfgang Noel

Hallo Thomas, mit der Änderung funktioniert es jetzt einwandfrei. Danke

Thomas

Thomas

Hallo,

bei mit wurde die Wetterdaten auch immer nur beim ersten Mal geladen.
Abhilfe brachte bei mit eine Anpasung der OpenWeatherMapAPI.cpp
Oben der der globalen Variablendeklaration DynamicJsonBuffer jsonBuffer(20000); auskommentieren und …

—snip
const char *owmApiHost = “api.openweathermap.org”;
const uint64_t timeout = 5000; // [ms]

//DynamicJsonBuffer jsonBuffer(20000); // response body size is usually around 15 kByte → auskommentieren

void OpenWeatherMapAPI::init(const char* ssid, const char* password)
—snap

…eine Kopie davon in der Funktion JsonObject* OpenWeatherMapAPI::getData(String query, String appId)

—snip
JsonObject* OpenWeatherMapAPI::getData(String query, String appId)
{
String resBody = OpenWeatherMapAPI::getResponse(query, appId);
const int contentLength = resBody.length();
if (contentLength > 0) {
// parse JSON
DynamicJsonBuffer jsonBuffer(20000); // response body size is usually around 15 kByte → hierhin kopieren

JsonObject& root = jsonBuffer.parseObject(resBody);

—snap

Beim Aufruf der Funktion wird jedes Mal der Buffer neu erstellt.

Bitte mal testen.

Gruß Thomas

Eveline Purps

Eveline Purps

Das ist doch mal eine konkrete Anleitung – bin gespannt ob es funktioniert. Sowas könnte man doch gut weiter machen….

Wolfgang Noel

Wolfgang Noel

Hallo, leider werden bei mir die Daten nicht aktualisiert. Soll eigentlich doch alle 2 Stunden erfolgen. Scripte so wie in der Vorlage übernommen. Nach Neustart wird auch aktualisiert.

Wolfgang

Wolfgang

Hallo, ich habe alle Programmteile so übernommen. Programm funktioniert auch soweit. Leider werden die Daten nicht automatisch aktualisiert. Nach einem Neustart sind die aktuellen Daten dann da. Woran kann das liegen?

Stephan

Stephan

Hallo zusammen,

habe das Programm heute morgen mal umgesetzt, gefällt mir.

@Michael … du brauchst meines Erachtens den Patch nicht mehr; die Library funktioniert auch so.

Ich habe eine einzige Sache geändert: Und zwar in der OLEDScreen.h habe ich in Zeile 15 aus (font5x7) (font8x8) gemacht, sonst wurde bei mir der Text nicht korrekt auf dem Display ausgegeben …

Gruß, Stephan

 Michael

Michael

Hallo leider ist der link https://github.com/barbeque/Ai_Ardulib_SSD1306/tree/patch-1 nicht mehr online, das bauen bricht leider mit einem fehler ab. wo kann ich den patch noch downloaden? bitte um eure hilfe.

MFG
Michael

Marcus

Marcus

Herrliche Spielerei – jetzt macht mein Raspberry / OpenHab die Wettervorhersage nicht mehr selbst, sondern bekommt sie direkt gemeinsam mit den gemessenen Wetterdaten von einem ESP32. Und dieser zeigt die Werte auch noch in der Garage auf dem OLED an.

Stephan

Stephan

Tolle Idee! Jetzt noch eine Variante mit Solarbetrieb wäre cool!

Leave a comment

All comments are moderated before being published

Recommended blog posts

  1. Install ESP32 now from the board manager
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. OTA - Over the Air - ESP programming via WLAN