Arduino Lektion 69: OpenWeatherMap Daten auf OLED Display anzeigen

In diesem Tutorial möchte ich beschreiben, wie man Daten von der offenen Schnittstelle OpenWeatherMap.org auf einem OLED Display anzeigt.

Daten für den Standort "Braunschweig" auf dem NodeMCU mit OLED Display von Openweathermap.org
Daten für den Standort „Braunschweig“ auf dem NodeMCU mit OLED Display von Openweathermap.org

Ich nutze dazu den NodeMCU mit 0,96 Zoll OLED Display, dieser Microcontroller wurde mir vom OnlineShop Makershop.de kostenfrei zur Verfügung gestellt.
Den NodeMCU mit 0,96Zoll OLED Display kann man für knap 13,75€ unter https://www.makershop.de/plattformen/arduino/nodemcu-oled/ beziehen. 

Dieses Tutorial sollte jedoch auch mit anderen, baugleichen Microcontrollern (wie zbsp. der Wemos D1 mini mit OLED Display) funktionieren.

Anmelden bei OpenWeatherMap.org

Damit man den Service von OpenWeatherMap.org nutzen kann, muss man sich anmelden. Die Anmeldung ist kostenfrei und schnell erledigt.

OpenWeatherMap - erstellen eines Accounts
OpenWeatherMap – erstellen eines Accounts

Nachdem die Daten eingegeben wurden, ist man angemeldet. (Es gibt also kein DoubleOptIn, was sehr fraglich ist.)

Unter dem Menüpunkt „API keys“ findet man nun den Standard Api key. Welchen wir nun nutzen werden um die Daten von der Schnittstelle abzugreifen.

Preise

Die Nutzung der Schnittstelle ist im Basispaket kostenlos, jedoch ist die Nutzung dann etwas eingeschränkt.

Man kann dann zbsp. „nur“ 60 aufrufe pro Minute starten und auch die Verfügbarkeit des Services ist mit 95% gegeben. Weitere Einschränkungen können unter https://openweathermap.org/price eingesehen werden. In meinem Fall reicht das Basispaket völlig aus.

Zugriff auf die API

Für die API gibt es bereits zahlreiche Implementierungen für diverse Sprachen.
Leider ist für den Arduino nichts dabei, aber so schwierig ist das ja nicht. Man muss ja nur einen Request an die API senden und erhält ein JSON zurück.

Ich nutze neben der Arduino IDE noch zusätzlich das Tool Postman, dieses Tool gibt es als Erweiterung für Google Chrome und als Standalone Lösung.

Beispiel Aufruf mit Postman

Starten wir zuerst einen Aufruf der API mit dem API key sowie der Stadt Braunschweig.

http://api.openweathermap.org/data/2.5/weather?q=Braunschweig,DE&appid=3ee177bfa6d11e51f87055hierfehltnochetwas

Als Response erhalten wir im Standardfall einen JSON.

{
    "coord": {
        "lon": 10.53,
        "lat": 52.26
    },
    "weather": [
        {
            "id": 800,
            "main": "Clear",
            "description": "clear sky",
            "icon": "01d"
        }
    ],
    "base": "stations",
    "main": {
        "temp": 284.81,
        "pressure": 1019,
        "humidity": 58,
        "temp_min": 284.15,
        "temp_max": 285.15
    },
    "visibility": 10000,
    "wind": {
        "speed": 2.6,
        "deg": 210
    },
    "clouds": {
        "all": 0
    },
    "dt": 1538295600,
    "sys": {
        "type": 1,
        "id": 4925,
        "message": 0.0088,
        "country": "DE",
        "sunrise": 1538284651,
        "sunset": 1538326624
    },
    "id": 3221017,
    "name": "Brunswick",
    "cod": 200
}

Diesem JSON Objekt können wir nun zbsp. die Daten für den Sonnenaufgang die aktuelle Windgeschwindigkeit sowie Luftdruck, Luftfeuchtigkeit usw. entnehmen.

Arduino Sketch

erzeugen einer Internetverbindung

Wollen wir also loslegen, als erstes schreiben wir unser Sketch das wir in das lokale Netzwerk gelangen und das wir somit Internetzugang haben.

Wenn man das Paket „ESP8266 by ESP8266 Community“ installiert so sind einige Beispielsketche enthalten. 

Paket "esp8266 by ESP8266 Community"
Paket „esp8266 by ESP8266 Community“

Ich verwende aus diesen Beispielen das Beispiel „BasicHttpClient“ als basis für den nachfolgenden Sketch.

#include <Arduino.h>

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>

#include <ESP8266HTTPClient.h>

ESP8266WiFiMulti WiFiMulti;

const char* SSID = "";
const char* PW = "";

const String url ="http://api.openweathermap.org/data/2.5/weather?q=Braunschweig,DE&appid=3ee177bfa6d11e51hierfehltnochetwas";

void setup() {
    Serial.begin(115200);
    Serial.println();
    delay(500);
    WiFiMulti.addAP(SSID, PASSWORD);
}

void loop() {
    if((WiFiMulti.run() == WL_CONNECTED)) {
        HTTPClient http;
        Serial.println("[HTTP] begin...");
        http.begin(url);
        Serial.println("[HTTP] GET...");
        int httpCode = http.GET();
        if(httpCode > 0) {
            Serial.printf("[HTTP] GET... code: %d\n", httpCode);
            if(httpCode == HTTP_CODE_OK) {
                String response = http.getString();
                Serial.println(response);
            }
        } else {
            Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
        }
        http.end();
    }
    delay(10000);
}

In dem Beispiel habe ich die SSID, das Passwort entfern und den API key entfremdet. Wenn du das Beispiel auf deinem Microcontroller nachstellen möchtest so musst du diese Daten vorher anpassen.

Die Ausgabe auf dem seriellen Monitor der Arduino IDE sieht nun wiefolgt aus:

Ausgabe des HTTP Response auf dem seriellen Monitor der Arduino IDE
Ausgabe des HTTP Response auf dem seriellen Monitor der Arduino IDE

Nachdem wir also das JSON erhalten haben, müssen wir uns „nurnoch“ die für uns nützlichen Daten herausziehen. 

parsen des HTTP Response (JSON Objekt)

Für den Zugriff auf die Schlüssel / Wertepaare im JSON Objekt verwende ich nun die Bibliothek von https://arduinojson.org. Des Weiteren erzeuge ich den Quellcode über DEV-C++ IDE welche kostenfrei unter https://sourceforge.net/projects/orwelldevcpp/ heruntergeladen werden kann. 

installieren der Bibliothek ArduinoJSON

Die Bibliothek „ArduinoJson“ kann man ganz bequem über den Bibliotheksverwalter der Arduino IDE installiert werden. Dazu navigiert man über das Hauptmenü „Sketch“ > „Bibliothek einbinden“ > „Bibliotheken verwalten…“ es öffnet sich nun ein neues Fenster. Nachdem die Daten fertig geladen wurden (je nach Internet & Rechnergeschwindigkeit kann dieses variieren) wird in der Suchleiste (1) nach „ArduinoJSON“ gesucht. Der Eintrag lautet „ArduinoJson by Benoit Blanchon“. Gemäß der Entwicklerseite soll man die Version 5 auswählen, daher wähle ich hier die Version 5.13.2 (stand 30.09.2018) (2) und betätige danach die Schaltfläche „Installieren“ (3).

Installieren der Bibliothek "ArduinoJSON" in der Arduino IDE
Installieren der Bibliothek „ArduinoJSON“ in der Arduino IDE

Wenn die Bibliothek erfolgreich installiert wurde so steht hinter dem Titel nun die Versionsnummer gefolgt vom Text „INSTALLED“.

ArduinoJson erfolgreich installiert
ArduinoJson erfolgreich installiert

Klasse OpenWeatherMap

Die Klasse „OpenWeatherMap“ enthält die geparsten Daten aus dem JSON der Schnittstelle. Um den Parser zu verwenden muss dieser dem Projekt hinzugefügt werden. Dazu werden die Dateien „openWeatherMapParser.h“ sowie „OpenWeatherMap.h“ parallel zum Arduino Sketch abgelegt. 

Ablage der Resourcen

Das gesamte Projekt kann vom GitHub Repository https://github.com/StefanDraeger/Arduino-OpenWeatherMap heruntergeladen werden. Dort findest du alle Resourcen zu diesem Projekt.

Drehspulinstrument für Icons

Für die Darstellung der Icons nutze ich ein Drehspulinstrument. Sicherlich könnte man die Icons auch als XBM convertieren und dann auf dem Display anzeigen jedoch finde ich diese Lösung etwas cooler.

Drehspulinstrument Vorder / Rückseite
Drehspulinstrument Vorder / Rückseite

Was wird benötigt?

Ich verwende dazu ein Drehspulinstrument mit einer Anzeige für maximal 100µA.

Das Drehspulinstrument habe ich bei Wish.com für je 2,70€ erstanden.

Angebot von Drehspulinstrumente auf wish.com
Angebot von Drehspulinstrumente auf wish.com

Auf der Plattform Wish.com gibt es sicherlich einiges an Schrott und der durchgestrichene Preis ist unter Garantie ein Mondpreis aber mit solchen Artikeln habe ich bisher immer glück gehabt. Der Preis von 3€ ist echt unschlagbar auf ebay.de oder anderen Portalen zahlt mal deutlich mehr (Okay die Lieferzeit wird für den ein oder anderen ein K.O. Kriterium sein.).

Des Weiteren wird ein Widerstand von 46kOhm und 30kOhm benötigt und zusätzlich einige Kabel.

Der 46kOhm Widerstand wird für den Test der Schaltung am Arduino UNO und der 30kOhm wird für den Live Betrieb mit dem NoceMCU benötigt.

Wollen wir zuerst ein kleines Projekt starten um zu testen wie sich das Drehspulinstrument am Arduino UNO verhält.

Arduino Sketch

Im nachfolgenden Sketch habe ich eine einfache Schleife welche die Zahlen von 0 bis 255 hochzählt und am digitalen PWM Pin 9 ausgibt.
Dieses bewirkt das die Nadel des Drehspulinstrumentes sich bewegt. 

void setup() {
  Serial.begin(9600);
}

void loop() {
  for(int i = 0;i<255;i++){
     analogWrite(9,i);
     Serial.println(i);
     delay(250);
  }
}

Video

Drehspulinstrument am Arduino UNO

Als erstes haben wir mit diesem Sketch erreicht das die Nadel von links nach rechts „wandert“. Nun benötigen wir aber noch die exakten Daten damit wir die Icons korrekt positionieren müssen. Dazu prüfen wir nun wieviel Pixel ein uA auf der Skala des Drehspulinstruments sind. Je nach Größe und Model kann die nachfolgende Anleitung etwas abweichen.

Erstellen einer eigenen Skala mit den Icons

Erstellen wir uns also nun eine eigene Skala mit den Icons von OpenWeatherMap.org .
Auf der Seite https://openweathermap.org/weather-conditions findet man die verschiedenen Icons welche im JSON (und natürlich auch im XML) Response zu finden sind. Es sind insgesamt 12 verschiedene Icons verfügbar. Jedes Icon hat eine Größe von 50×50 Pixel. Das ergibt eine kurze Rechnung von 50 x 12 = 600 Pixel breite.
Die Skala ist jedoch „nur“ 5cm breit somit werden wir die Icons zusätzlich etwas schrumpfen müssen.

 

Skala mit Wettericons für das Drehspulinstrument
Skala mit Wettericons für das Drehspulinstrument

Im nun folgenden Schritt werden wir die Positionen für die Icons auf dem Drehspulinstrument ermittelt.
Hier gibt es zwei Möglichkeiten diese Positionen zu ermitteln, einmal die etwas aufwändige das man immer wieder (neuen) einen Wert setzt und dann kompiliert und den Sketch hochlädt. Oder man erstellt sich eine kleine Schaltung mit einem Drehpotentiometer über den Analogen Pin A0 und kann dann per Hand die Nadel bewegen und über dem seriellen Monitor die Arduino IDE den Wert ablesen. Und genau diese Schaltung erzeugen wir nun.

Schaltung zum ermitteln der Positionen der Icons auf dem Drehspulinstrument

Wir benötigen für die Schaltung:

  • 1x Arduino UNO (oder vergleichbarer Microcontroller)
  • 7x Steckbrettkabel, männlich – männlich
  • 1x Drehpotentiometer mit 50kOhm
  • 1x Drehspulinstrument
  • 1x Steckbrett mit min. 170 Pin
Schaltung - Drehpotentiometer und Drehspulinstrument
Schaltung – Drehpotentiometer und Drehspulinstrument
Schaltung - Drehpotentiometer und Drehspulinstrument am Arduino UNO
Schaltung – Drehpotentiometer und Drehspulinstrument am Arduino UNO

In der Schaltung habe ich einen Arduino UNO verwendet jedoch beim späteren Test mit dem NodeMCU habe ich festgestellt das der Widerstand von 46kOhm deutlich zuviel ist, somit musste ich auf ein 22kOhm ausweichen.
(Dieser währe jedoch zuwenig für den Arduino UNO!)

Video
Steuern eines Drehspulinstrumentes mit hilfe eines Drehpotentiometers am Arduino UNO
Arduino Sketch

Im nachfolgenden Sketch lese ich den analogen Wert des Drehpotentiometers am Pin A0 ein und mappe diesen mit der Funktion map auf den PWM Wert für das Drehspulinstrument.

void setup() {
  Serial.begin(9600);
}

void loop() {
  int analogValue = analogRead(A0);
  Serial.print("analog->");
  Serial.println(analogValue);

  int pwmValue = map(analogValue, 0,1023, 0,255);
  Serial.print("pwm->");
  Serial.println(pwmValue);

  analogWrite(D5,pwmValue);
 
  delay(500);
}

Die Werte für die einzelnen Icons sind wiefolgt:

#define SONNE 0
#define WOLKE_SONNE 85
#define WOLKE 192
#define WOLKE_DUNKEL 329
#define REGEN 429
#define SONNE_REGEN 522
#define GEWITTER 608
#define SCHNEE 658
#define REGEN_MOND 713
#define WOLKE_MOND 780
#define MOND 838

Im nachfolgenden werden wir nun das Beispiel 1 aus dem GitHub Repository von mir laden und für unsere Bedürfnisse anpassen. 

Am Anfang des Tutorials haben wir bereits eine Verbindung zum lokalen Netzwerk hergestellt und ein JSON als String empfangen und auf dem seriellen Monitor der Arduino IDE ausgegeben.

Wollen wir also nun das JSON Parsen und die Werte Seitenweise auf dem OLED Display des NodeMCU ausgeben.

#include <ArduinoJson.h>

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>

#include <ESP8266HTTPClient.h>

#include <Wire.h> //Bibliothek für die Arduino IDE <= 1.6.5
#include "SSD1306Wire.h" //Display Bibliothek
#include "OLEDDisplayUi.h" //Display Bibliothek

#include <SPI.h>
#include <Wire.h>

ESP8266WiFiMulti WiFiMulti;

SSD1306Wire  display(0x3c, D1, D2);
OLEDDisplayUi ui ( &display );

const char* SSID = "SSID des Routers";
const char* PW = "WLAN Schluessel";

#define SONNE 0
#define WOLKE_SONNE 85
#define WOLKE 192
#define WOLKE_DUNKEL 329
#define REGEN 429
#define SONNE_REGEN 522
#define GEWITTER 608
#define SCHNEE 658
#define REGEN_MOND 713
#define WOLKE_MOND 780
#define MOND 838

const String url ="http://api.openweathermap.org/data/2.5/weather?q=Braunschweig,DE&appid=3ee177bfa6d11e51f87055hierfehltetwas";

class Coord {
  double longitude;
  double latitude;
      
  public:
    double getLongitude(){ return longitude; }
    double getLatidute(){ return latitude; }
      
    void setLongitude(double inLongitude){ longitude = inLongitude; }
    void setLatitude(double inLatitude){ latitude = inLatitude; }
};

class Weather {
  int id;
  String main;
  String description;
  String icon; 
  
  public:
    int getId(){ return id; }
    String getMain(){ return main; }
    String getDescription(){ return description; }
    String getIcon(){ return icon; }
        
    void setId(int inId){ id = inId;  }
    void setMain(String inMain){ main = inMain; } 
    void setDescription(String inDescription){ description = inDescription; }
    void setIcon(String inIcon){ icon = inIcon; }   
};

class Main {
  double temp;
  double tempMin;
  double tempMax;
  int pressure;
  int humidity;
  
  public:
    double getTemp(){ return temp; }
    double getTempMin(){ return tempMin; }
    double getTempMax(){ return tempMax; }
    int getPressure(){ return pressure; }
    int getHumidity(){ return humidity; }
    
    void setTemp(double inTemp){ temp = inTemp; }
    void setTempMin(double inTempMin){ tempMin = inTempMin; }
    void setTempMax(double inTempMax){ tempMax = inTempMax; }
    void setPressure( int inPressure){ pressure = inPressure; }
    void setHumidity( int inHumidity){ humidity = inHumidity; }
};

class Wind {
  double speed;
  int degree;
  
  public:
    double getSpeed(){ return speed; }
    int getDegree(){ return degree; }
    
    void setSpeed(double inSpeed) { speed = inSpeed; }
    void setDegree( int inDegree){ degree = inDegree; }
};

class Clouds {
  int all;
  
  public:
    int getAll(){ return all; }
    void setAll( int inAll){ all = inAll; }
};

class Sys{
  int type;
  int id;
  double message;
  String country;
  long sunrise;
  long sunset;
  
  public:
    int getType(){ return type; }
    int getId(){ return id; }
    double getMessage(){ return message; }
    String getCountry(){ return country; }
    long getSunrise(){ return sunrise; }
    long getSunset(){ return sunset; }
    
    void setType(int inType){ type = inType; }
    void setId(int inId){ id = inId; }
    void setMessage(double inMessage){ message = inMessage; }
    void setCountry(String inCountry){ country = inCountry; }
    void setSunrise(long inSunrise){ sunrise = inSunrise; }
    void setSunset(long inSunset){ sunset = inSunset; }
};

class OpenWeatherMap {    
  int id;
  String name;
  int code;
  String httpResponse; 
  String base;
  int visibility;
  long dateTime;
  
  Coord coord;
  Weather weather;
  Main main;  
  Wind wind;
  Clouds clouds;
  Sys sys;
  
  public: 
    String getHttpResponse(){ return httpResponse; }    
    void setHttpResponse(String inHttpResponse){ httpResponse = inHttpResponse; } 
  
    int getId(){ return id; }
    void setId(int inId){ id = inId; }
    
    String getName(){ return name; }
    void setName(String inName){ name = inName; }
    
    int getCode(){ return code; }
    void setCode(int inCode){ code = inCode; }
    
    String getBase(){ return base; }
    void setBase(String inBase){ base = inBase; }
    
    int getVisibility(){ return visibility; }
    void setVisibility( int inVisibiity){ visibility = inVisibiity; }
    
    long getDateTime(){ return dateTime; }
    void setDateTime(long inDateTime){ dateTime = inDateTime; }
    
    Coord getCoord(){ return coord; }
    void setCoord(Coord inCoord){ coord = inCoord; }
    
    Weather getWeather(){ return weather; }
    void setWeather(Weather inWeather){ weather = inWeather; }
    
    Main getMain(){ return main; }
    void setMain(Main inMain){ main = inMain; }
    
    Wind getWind(){ return wind; }
    void setWind(Wind inWind){ wind = inWind; }
    
    Clouds getClouds(){ return clouds; }
    void setClouds(Clouds inClouds){ clouds = inClouds; }
    
    Sys getSys(){ return sys; }
    void setSys(Sys inSys){ sys = inSys; }
};

OpenWeatherMap parseCurrentJson(String httpResponse){ 
  OpenWeatherMap openWeatherMap; 
  openWeatherMap.setHttpResponse(httpResponse); 
  
  StaticJsonBuffer<2000> jsonBuffer;
  JsonObject& root = jsonBuffer.parseObject(httpResponse);
  if (!root.success()) {
      return openWeatherMap; 
  }
  
  String base = root["base"];
  openWeatherMap.setBase(base);
  
  int visibility = root["visibility"];
  openWeatherMap.setVisibility(visibility);
  
  long dateTime = root["dt"];
  openWeatherMap.setDateTime(dateTime);
  
  int id = root["id"];
  openWeatherMap.setId(id);
  
  String name = root["name"];
  openWeatherMap.setName(name);
  
  int code = root["cod"];
  openWeatherMap.setCode(code);
  
  double longitude = root["coord"]["lon"];
  double latidude = root["coord"]["lat"];
  Coord coord;
  coord.setLongitude(longitude);
  coord.setLatitude(latidude);
    openWeatherMap.setCoord(coord);
      
  int weatherId = root["weather"][0]["id"];
  String weatherMain = root["weather"][0]["main"];
  String weatherDescription = root["weather"][0]["description"];
  String weatherIcon = root["weather"][0]["icon"];
  
  Weather weather;
  weather.setId(weatherId);
  weather.setMain(weatherMain);
  weather.setDescription(weatherDescription); 
  weather.setIcon(weatherIcon);
    openWeatherMap.setWeather(weather);
        
    double temp = root["main"]["temp"];
    double tempMin = root["main"]["temp_min"];
    double tempMax = root["main"]["temp_max"];
    int tempPressure = root["main"]["pressure"];
    int tempHumidity = root["main"]["humidity"];
    
  Main main;
  main.setTemp(temp);
  main.setTempMin(tempMin);
  main.setTempMax(tempMax);
  main.setPressure(tempPressure);
  main.setHumidity(tempHumidity);
  openWeatherMap.setMain(main);
  
  double windSpeed = root["wind"]["speed"];
  double windDegree = root["wind"]["deg"];
  
  Wind wind;
  wind.setSpeed(windSpeed);
  wind.setDegree(windDegree);
  openWeatherMap.setWind(wind);
  
  int cloudsAll = root["clouds"]["all"];
  
  Clouds clouds;
  clouds.setAll(cloudsAll);
  openWeatherMap.setClouds(clouds);
  
  int sysType = root["sys"]["type"];
  int sysId = root["sys"]["id"];
  double sysMessage = root["sys"]["message"];
  String sysCountry = root["sys"]["country"];
  long sysSunrise = root["sys"]["sunrise"];
  long sysSunset =  root["sys"]["sunset"];
  
  Sys sys;
  sys.setType(sysType);
  sys.setId(sysId);
  sys.setMessage(sysMessage);
  sys.setCountry(sysCountry);
  sys.setSunrise(sysSunrise);
  sys.setSunset(sysSunset);
  openWeatherMap.setSys(sys);
  
  return openWeatherMap; 
}

OpenWeatherMap openWeatherMap;

void mainData(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
  display->setTextAlignment(TEXT_ALIGN_LEFT);
  display->setFont(ArialMT_Plain_16);
  display->drawString(0, 0, openWeatherMap.getName());
  Serial.println("1");
}

void windData(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
Serial.println("2a");
  Wind wind = openWeatherMap.getWind();
  Serial.println("2b");
  display->setTextAlignment(TEXT_ALIGN_LEFT);
  display->setFont(ArialMT_Plain_16);
  display->drawString(0, 0, "Wind");
  display->setFont(ArialMT_Plain_10);  
  display->drawString(0, 16, "Speed:");
  String windSpeed = String(wind.getSpeed());
  windSpeed += " m/sec";
  display->drawString(55, 16, windSpeed);
  
  display->drawString(0, 30, "Degree:");
  String windDegree = String(wind.getDegree());
  windDegree += "°"; 
  display->drawString(55, 30, windDegree);  
  Serial.println("2");
}

void weather1Data(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
  Main main = openWeatherMap.getMain();
  display->setTextAlignment(TEXT_ALIGN_LEFT);
  display->setFont(ArialMT_Plain_16);
  display->drawString(0, 0, "Weather");
  display->setFont(ArialMT_Plain_10);  
  display->drawString(0, 16, "Temp.:");
  String weatherTemp = String(main.getTemp()-273.15,2);
  weatherTemp += "°C";
  display->drawString(63, 16, weatherTemp);
  String weatherTempMin = String(main.getTempMin()-273.15,2);
  weatherTempMin += "°C";
  display->drawString(0, 30, "min. Temp.:");
  display->drawString(63, 30, weatherTempMin);  
  String weatherTempMax = String(main.getTempMax()-273.15,2);
  weatherTempMax += "°C";
  display->drawString(0, 43, "max. Temp.:");
  display->drawString(63, 43, weatherTempMax);  
  Serial.println("3");
}

void weather2Data(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
  Main main = openWeatherMap.getMain();
  display->setTextAlignment(TEXT_ALIGN_LEFT);
  display->setFont(ArialMT_Plain_16);
  display->drawString(0, 0, "Weather");
  display->setFont(ArialMT_Plain_10);  
  
  display->drawString(0, 16, "Pressure:");
  String weatherPressure = String(main.getPressure());
  weatherPressure += " hPa";
  display->drawString(55, 16, weatherPressure);
   
  display->drawString(0, 30, "Humidity:");
  String weatherHumidity = String(main.getHumidity());
  weatherHumidity += " %";
  display->drawString(55, 30, weatherHumidity);  
  Serial.println("4");
}

FrameCallback frames[] = {mainData, windData, weather1Data, weather2Data};

void setup() {
  Serial.begin(115200);
  
  Serial.println();
  WiFiMulti.addAP(SSID, PW);

  const int frameCount = 4;
  ui.setTargetFPS(60);
  ui.setFrames(frames, frameCount);
  ui.init();
}

void showData(){
  Weather weather = openWeatherMap.getWeather();
  String icon = weather.getIcon();
  setWeatherIcon(icon);   
}

void setWeatherIcon(String icon){
  int pwmValue = WOLKE;
  if(icon == "01d"){ pwmValue = SONNE; } 
  else if(icon == "02d"){ pwmValue = WOLKE_SONNE; } 
  else if(icon == "03d"){ pwmValue = WOLKE; } 
  else if(icon == "04d"){ pwmValue = WOLKE_DUNKEL; } 
  else if(icon == "09d"){ pwmValue = REGEN; } 
  else if(icon == "10d"){ pwmValue = SONNE_REGEN; } 
  else if(icon == "11d"){ pwmValue = GEWITTER; } 
  else if(icon == "13d"){ pwmValue = SCHNEE; } 
  else if(icon == "50d"){ pwmValue = WOLKE; } 
  else if(icon == "01n"){ pwmValue = MOND; } 
  else if(icon == "02n"){ pwmValue = WOLKE_MOND; } 
  else if(icon == "03n"){ pwmValue = WOLKE; } 
  else if(icon == "04n"){ pwmValue = WOLKE_DUNKEL; } 
  else if(icon == "09n"){ pwmValue = REGEN; } 
  else if(icon == "10n"){ pwmValue = REGEN_MOND; } 
  else if(icon == "11n"){ pwmValue = GEWITTER; } 
  else if(icon == "13n"){ pwmValue = SCHNEE; } 
  analogWrite(D5,pwmValue);
}   

long lastUpdate = -1L;
long updateIntervall = 15000;

void loop() {
    if((WiFiMulti.run() == WL_CONNECTED) && ((lastUpdate+updateIntervall) < millis())) {
        lastUpdate = millis();
        HTTPClient http;
        Serial.println("[HTTP] begin...");
        http.begin(url);
        Serial.println("[HTTP] GET...");
        int httpCode = http.GET();
        if(httpCode > 0) {
            Serial.printf("[HTTP] GET... code: %d\n", httpCode);
            if(httpCode == HTTP_CODE_OK) {
                String response = http.getString();
                Serial.println(response);
                openWeatherMap = parseCurrentJson(response);
                showData();
            }
        } else {
            Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
        }
        http.end();
    }
    int remainingTimeBudget = ui.update();
}

Video

Anzeigen der Daten von OpenWeatherMap auf dem NodeMCU mit OLED Display

Fazit und Ausblick

Wir haben nun die aktuellen Wetterdaten auf dem OLED Display angezeigt, als nächstes können wir nun die letzten 5 Wetterdaten von der Schnittstelle empfangen und anzeigen usw. 

Das Parsen der Daten mit der Bibliothek ArduinoJSON kann einfacher nicht sein daher konnte dieses Projekt mit relativ wenig Aufwand bewerkstelligt werden einzig war etwas arbeit nötig um das JSON als Objekt darzustellen.

Als nächstes werde ich nun ein Gehäuse bauen und ein schönes Plätzchen auf meinem Schreibtisch suchen…..

 

 

Ein Gedanke zu „Arduino Lektion 69: OpenWeatherMap Daten auf OLED Display anzeigen

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.