Arduino Weather Station

by HairySloth in Circuits > Arduino

350 Views, 5 Favorites, 0 Comments

Arduino Weather Station

20220614_103823.jpg

Ik heb een LED weerstation gemaakt met een ESP8266 arduino. Met de API van OpenWeatherMap wordt de weerdata opgehaald. Vervolgens wordt het huidige weer en temperatuur weergegeven door WS2812B LED'jes, die achter een vel doorzichtig papier zitten.

Met dit simpele weerstation kun je het de huidige weersituatie en temperatuur zien. Door een segmented display kunnen weerscenario's op 6 verschillende manieren worden weergegeven. De temperatuur wordt weergegeven door een aantal LED's op te lichten, in de vorm van een traditionele thermostaat.

Supplies

Onderdelen:

  • ESP2866 Arduino met WiFi verbinding
  • WS2812B LED's (50)
  • Bedrading
  • Micro-USB kabel
  • Wifi of mobiele hotspot

Behuizing:

  • Dun, buigbaar, bouwkarton
  • Vel A4 papier

Gereedschap:

  • Schaar
  • Soldeerbout met tin
  • Lijm

Design

Screenshot 2022-08-15 025315.png

Voor stap 1 was ik vooral gewoon aan het experimenteren met verschillende ideeen die ik had. Zoals bijvoorbeeld geluiden toevoegen, of alleen maar een kleur lamp hebben, zonder display. Verder had ik ook nog ideeen om bijvoorbeeld een klok er in te verwerken. Maar toen ik langs een oud weerstation kwam die ik ergens zag liggen, was ik geinteresseerd door het segmenten-display. Het leek mij leuk om dat na te maken. De foto hierboven toont een van mijn vroege designs; een lamp aan de binnenkant van een cilinder. Mijn idee was toen om de lamp voor elke weersituatie een andere kleur te geven, en daarnaast toepassende geluiden af te spelen. Het bleek snel dat het lastig was om zo duidelijk te maken wat voor weer wat was. Het uiteindelijke design was veel duidelijker.

Constructie

IMG_20220613_221608.jpg
IMG_20220614_080836.jpg

De behuizing van het weerstation is gemaakt van dun knutselkarton. De segmenten aan de binnenkant en de zijkanten zijn gemaakt van dikker karton. De segmenten zijn zo neergezet, dat er zeer weinig verschillende LED strips gebruikt hoeven te worden. Er zijn in totaal 50 lichtjes. Er zijn 12 segmenten. 3 verschillende voor de zon/wolken, en 9 voor de verschillende soorten neerslag/mist. Verder is er een groot verticaal stuk voor de thermostaat. Aan de achterkant is genoeg plek om de ESP2866 kwijt te krijgen.

Code

De code is redelijk ingewikkeld, en by far waar de meeste moeite voor dit project in gegaan is. De code werkt in verschillende stappen. Bovenaan worden verschillende variabelen gedefinieerd.

Daarna wordt data ingevuld voor de verbinding met WIFI. In dit geval is dit mijn persoonlijke hotspot op mijn telefoon. Daarna wordt de juiste data bij elkaar gehaald zodat de weerinformatie van OpenWeatherMap gehaald kan worden. (Dit deel van de code is grotendeels van https://randomnerdtutorials.com/esp32-http-get-open-weather-map-thingspeak-arduino/)

In de setup worden veel verschillende dingen gedaan. De LED's worden verbonden, de serial monitor wordt aangezet, en er wordt verbonden met de WiFi.

Daarna wordt de Json request om de minuut opgevraagd. Wanneer de Json binnen eerst, wordt eerst de temperatuur omgezet van Kelvin naar Celsius, en dan wordt de temperatuur getoond op de thermostaat-LED's.

Daaronder staan allemaal verschillende switch-cases, die elk voor verschilllende weersituaties gebruikt worden. Dankzij de manier waarop het geformuleerd is, (4 rijen van 3 maakt 12 segmenten) is het makkelijk om nieuwe scenario's toe te voegen. Daarna worden de LED's aangestuurd.

Hieronder zien we hoe dat zo mooi geformuleerd is, hier staat een enorme waslijst LED adressen die duidelijkere namen gegeven worden, en sommige worden permanent uitgezet omdat ze in de behuizing op een plek zitten waar ze niet te zien zijn.

Daaronder staat meer van de code van de website die hierboven ook gelinked staat. Ik heb geprobeerd om zelf deze code vanaf niks te schrijven, maar het werd mij aangeraden om toch code te gebruiken van iemand met meer ervaring.

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
#include <Arduino_JSON.h>
#include <FastLED.h>


#define LED_PIN       5
#define button_pin    13


#define ledSunStart   1
#define ledSunEnd     5
#define ledSun2Start  6
#define ledSun2End    9
#define ledCloudStart 10
#define ledCloudEnd   22
#define ledInd1 23
#define ledInd2 28
#define ledInd3 33
#define ledTempStart 34
#define ledTempEnd  50
#define NUM_LEDS 50


#define tempGrad 30


#define colorSun    0xf2bb13
#define colorCloud  0xffffff
#define colorRain   0x0592f7
#define colorZap    0xf7ef05
#define colorOff    0x000000


CRGB leds[NUM_LEDS];


int mode = 1;
int id;


const char* ssid = "thegamer";
const char* password = "bananana";


// Your Domain name with URL path or IP address with path
String openWeatherMapApiKey = "f3d03e8938ac1114d664bbb8a663ce2f";
// Example:
//String openWeatherMapApiKey = "bd939aa3d23ff33d3c8f5dd1dd4";


// Replace with your country code and city
String city = "Amersfoort";
String countryCode = "NL";


unsigned long lastTime = 0;
unsigned long timerDelay = 60000;
int tempTime = timerDelay;
String jsonBuffer;


void setup() {
  Serial.begin(115200);
  FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
  pinMode(13, INPUT_PULLUP);
  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());


  Serial.println("Timer set to 60 seconds (timerDelay variable), it will take 60 seconds before publishing the first reading.");
}


void loop() {
  // Send an HTTP GET request
  if ((millis() - lastTime + tempTime) > timerDelay) {
    tempTime = 0;
    // Check WiFi connection status
    if (WiFi.status() == WL_CONNECTED) {
      String serverPath = "http://api.openweathermap.org/data/2.5/weather?q=" + city + "," + countryCode + "&APPID=" + openWeatherMapApiKey;


      jsonBuffer = httpGETRequest(serverPath.c_str());
      Serial.println(jsonBuffer);
      JSONVar myObject = JSON.parse(jsonBuffer);


      id = int(myObject["weather"][0]["id"]);
      float temp = double(myObject["main"]["temp"]);
      temp = temp - 273.15;
      int tempint = round(temp);
      
      fill_solid(&(leds[ledTempStart]), (temp+ledTempStart)/2, 0xc91b0e);
      mode = mode + 1;
      fill_solid(&(leds[0]), 50, 0xc91b0e);
    } else {
      Serial.println("WiFi Disconnected");
    }
    
    
    
    switch (id) {
      case 701 ... 800:
        ledColor(colorSun, colorSun, colorOff, 
                 colorOff, colorOff, colorOff,
                 colorOff, colorOff, colorOff,
                 colorOff, colorOff, colorOff);
        break;
        
      case 801:
        ledColor(colorSun, colorCloud, colorCloud,
                 colorOff, colorOff, colorOff,
                 colorOff, colorOff, colorOff,
                 colorOff, colorOff, colorOff);
        break;
      case 500 ... 622:
        ledColor(colorOff, colorCloud, colorCloud, 
                 colorRain, colorOff, colorRain,
                 colorOff, colorOff, colorOff,
                 colorRain, colorOff, colorRain);
        break;
      case 200 ... 232:
        ledColor(colorOff, colorCloud, colorCloud, 
                 colorRain, colorZap, colorRain,
                 colorOff, colorZap, colorOff,
                 colorRain, colorZap, colorRain);
        break;
      case 300 ... 321:
        ledColor(colorOff, colorCloud, colorCloud, 
                 colorOff, colorRain, colorOff,
                 colorOff, colorOff, colorOff,
                 colorOff, colorOff, colorOff);
        break;
      case 802 ... 805:
        ledColor(colorOff, colorCloud, colorCloud, 
                 colorOff, colorOff, colorOff,
                 colorOff, colorOff, colorOff,
                 colorOff, colorOff, colorOff); 
        
    }
    
    lastTime = millis();


  }
  FastLED.show();
}




//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


void ledColor(uint32_t sun, uint32_t sun2, uint32_t cloud, uint32_t ind1a, uint32_t ind2a, uint32_t ind3a, uint32_t ind1b, uint32_t ind2b, uint32_t ind3b, uint32_t ind1c, uint32_t ind2c, uint32_t ind3c) { 
  fill_solid(&(leds[ledSunStart]), ledSunEnd, sun);
  fill_solid(&(leds[ledSun2Start]), ledSun2End, sun2);
  fill_solid(&(leds[ledCloudStart]), ledCloudEnd, cloud);
  
  leds[ledInd1] = ind1a;
  leds[ledInd1+1] = ind2a;
  leds[ledInd1+2] = ind3a;
  leds[ledInd1+3] = colorOff;
  leds[ledInd1+4] = colorOff;
  leds[ledInd2] = ind1b;
  leds[ledInd2+1] = ind2b;
  leds[ledInd2+2] = ind3b;
  leds[ledInd2+3] = colorOff;
  leds[ledInd2+4] = colorOff;
  leds[ledInd3] = ind1c;
  leds[ledInd3+1] = ind2c;
  leds[ledInd3+2] = ind3c;
}


String httpGETRequest(const char* serverName) {
  WiFiClient client;
  HTTPClient http;


  // Your IP address with path or Domain name with URL path
  http.begin(client, serverName);


  // Send HTTP POST request
  int httpResponseCode = http.GET();


  String payload = "{}";


  if (httpResponseCode > 0) {
    Serial.print("HTTP Response code: ");
    Serial.println(httpResponseCode);
    payload = http.getString();
  } else {
    Serial.print("Error code: ");
    Serial.println(httpResponseCode);
  }
  // Free resources
  http.end();


  return payload;
}

Conclusie

Ik heb veel geleerd met dit project. Ik heb geleerd hoe ik met API's en Json bestanden werk, maar ook hoe ik moet solderen. Dat vond ik het leukst en meest interessant aan dit project, hoeveel verschillende vaardigheden je nodig hebt, en dus de kans krijgt om deze allemaal aan te scherpen. Ik zou liegen als ik zou zeggen dat het van een leien dakje ging, maar als ik erop terug kijk ben ik toch erg blij met de ervaring en het resultaat.