Weerstation bouwen
Geplaatst opAPI key
Voor het verkrijgen van weerinformatie is een API key nodig. Hiervoor moet je een account registreren bij OpenWeatherMap, wat hier kan: https://home.openweathermap.org/users/sign_up. Ga nadat je geregistreerd bent naar het kopje "API keys". Kopieër de API key die je daar vindt (Zie foto's).
Voor het verkrijgen van weerinformatie is een API key nodig. Hiervoor moet je een account registreren bij OpenWeatherMap, wat hier kan: https://home.openweathermap.org/users/sign_up. Ga nadat je geregistreerd bent naar het kopje "API keys". Kopieër de API key die je daar vindt (Zie foto's).
Ga naar "API keys"
Kopieër de API key
Installeer de ArduinoJson library
Als je de laatste versie van de ArduinoJson library al hebt, kun je deze stap overslaan.
Open de Arduino IDE, ga naar Sketch > Include library > Manage libraries (zie foto). Zoek naar "arduinojson" en installeer de laatste versie van de ArduinoJson library van Benoit Blanchon (zie foto).
Als je de laatste versie van de ArduinoJson library al hebt, kun je deze stap overslaan.
Open de Arduino IDE, ga naar Sketch > Include library > Manage libraries (zie foto). Zoek naar "arduinojson" en installeer de laatste versie van de ArduinoJson library van Benoit Blanchon (zie foto).
Open de library manager
Download de ArduinoJson library
Installeer de LiquidCrystal I2C library
Download eerst het ZIP bestand van de library door naar deze link te gaan: https://github.com/johnrickman/LiquidCrystal_I2C/archive/master.zip.
Ga in de Arduino IDE vervolgens naar Sketch -> Include Library -> Add .ZIP library en selecteer het ZIP bestand van de library.
Download eerst het ZIP bestand van de library door naar deze link te gaan: https://github.com/johnrickman/LiquidCrystal_I2C/archive/master.zip.
Ga in de Arduino IDE vervolgens naar Sketch -> Include Library -> Add .ZIP library en selecteer het ZIP bestand van de library.
Voeg het ZIP bestand toe
Installeer de ESP8266 boards
Als u de ESP8266 boards al heeft toegevoegd aan de Arduino IDE, kun je deze stap overslaan.
Open de instellingen van de Arduino IDE door te gaan naar File > Preferences. Voer in het tekstvak "Additional Boards Manager URLs" de URL "http://arduino.esp8266.com/stable/package_esp8266com_index.json" in (zie foto). Open vervolgens de Board Manager met Tools > Board > Boards Manager (zie foto). Installeer vervolgens de ESP8266 boards (zie foto).
Als u de ESP8266 boards al heeft toegevoegd aan de Arduino IDE, kun je deze stap overslaan.
Open de instellingen van de Arduino IDE door te gaan naar File > Preferences. Voer in het tekstvak "Additional Boards Manager URLs" de URL "http://arduino.esp8266.com/stable/package_esp8266com_index.json" in (zie foto). Open vervolgens de Board Manager met Tools > Board > Boards Manager (zie foto). Installeer vervolgens de ESP8266 boards (zie foto).
Verander de "Additional Boards Manager URLs"
Open de Boards Manager
Installeer de ESP8266 boards
I2C adres achterhalen
Voordat je de weerstation code upload, moet je het adres van de I2C LCD module vinden. Gebruik daarvoor de onderstaande code.
Voordat je de weerstation code upload, moet je het adres van de I2C LCD module vinden. Gebruik daarvoor de onderstaande code.
I2C scanner code
#include <Wire.h>
void setup()
{
Wire.begin();
Serial.begin(9600);
Serial.println("\nI2C Scanner");
}
void loop()
{
byte error, address;
int nDevices;
Serial.println("Scanning...");
nDevices = 0;
for(address = 1; address < 127; address++ )
{
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0)
{
Serial.print("I2C device found at address 0x");
if (address<16)
Serial.print("0");
Serial.print(address,HEX);
Serial.println(" !");
nDevices++;
}
else if (error==4)
{
Serial.print("Unknown error at address 0x");
if (address<16)
Serial.print("0");
Serial.println(address,HEX);
}
}
if (nDevices == 0)
Serial.println("No I2C devices found\n");
else
Serial.println("done\n");
delay(5000);
}
In dit geval is het adres 0x3F
Code uploaden
Zorg ervoor dat je het juiste board hebt geselecteerd onder Tools -> Board en dat je de juiste poort hebt geselecteerd onder Tools -> Port.
Voer je informatie in en upload de volgende code naar de Wemos via de Arduino IDE:
Zorg ervoor dat je het juiste board hebt geselecteerd onder Tools -> Board en dat je de juiste poort hebt geselecteerd onder Tools -> Port.
Voer je informatie in en upload de volgende code naar de Wemos via de Arduino IDE:
Weerstation code
x
#include <ESP8266WiFi.h>
#include <ArduinoJson.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <WiFiUdp.h>
char ssid[] = "--VOER HIER DE NAAM VAN JE WIFI NETWERK IN--";
char pass[] = "--VOER HIER HET WACHTWOORD VAN JE WIFI NETWERK IN--";
String apiKey = "--VOER HIER JE API KEY IN--";
String city = "--VOER HIER DE NAAM VAN JE STAD OF DORP IN--";
int timeOffset = 7200; // 7200 voor zomertijd, 3600 voor wintertijd
int address = 0x3F; // Voer hier het I2C adres in van de vorige stap
// Ik raad aan niks onder deze regel te wijzigigen.
WiFiClient client;
LiquidCrystal_I2C lcd(address, 16, 2);
char servername[] = "api.openweathermap.org";
String result;
unsigned long weatherLast = millis();
unsigned long weatherInterval = 60000;
char ntpServer[] = "0.nl.pool.ntp.org";
WiFiUDP UDP;
IPAddress timeServerIP;
const int NTP_PACKET_SIZE = 48;
byte ntpBuffer[NTP_PACKET_SIZE];
uint32_t unixTime = 0;
unsigned long lastActualTime = 0;
void setup() {
lcd.begin();
lcd.backlight();
lcd.noCursor();
lcd.clear();
lcd.print("Laden (WiFi)...");
Serial.begin(9600);
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
lcd.clear();
lcd.print("Laden (NTP)...");
UDP.begin(123);
if(!WiFi.hostByName(ntpServer, timeServerIP)) {
lcd.clear();
lcd.print("NTP DNS fail");
Serial.println("DNS lookup fail. Rebooting.");
delay(1000); // Wacht even met rebooten
ESP.reset();
}
sendNTPpacket(timeServerIP);
/* Deze loop wacht op een NTP response */
while(true) {
uint32_t time = getTime();
if(time) {
unixTime = time;
ntpLast = millis();
break;
}
}
lcd.clear();
lcd.print("Laden (Data)...");
getWeather();
}
void loop() {
unsigned long currentMillis = millis();
uint32_t actualTime = unixTime + (currentMillis - ntpLast) / 1000;
if(lastActualTime - actualTime > 1000) {
lastActualTime = actualTime;
int hours = getHours(actualTime);
int minutes = getMinutes(actualTime);
int seconds = getSeconds(actualTime);
lcd.setCursor(0, 0);
if(hours < 10) {
lcd.print("0");
}
lcd.print(hours);
lcd.print(":");
if(minutes < 10) {
lcd.print("0");
}
lcd.print(minutes);
lcd.print(":");
if(seconds < 10) {
lcd.print("0");
}
lcd.print(seconds);
}
if(currentMillis - weatherLast > weatherInterval) {
getWeather();
}
}
void getWeather() {
if(!client.connect(servername, 80)) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Verbinding");
lcd.setCursor(0, 1);
lcd.print("mislukt");
Serial.println("Connection failed");
weatherLast = millis();
return;
}
client.println("GET /data/2.5/weather?q=" + city + "&APPID=" + apiKey + "&units=metric");
client.println("Host: api.openweathermap.org");
client.println("Connection: close");
if(client.println() == 0) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Kon request");
lcd.setCursor(0, 1);
lcd.print("niet sturen");
Serial.println("Failed to send request");
weatherLast = millis();
return;
}
const size_t capacity = JSON_ARRAY_SIZE(3) + 2*JSON_OBJECT_SIZE(1) + JSON_OBJECT_SIZE(2) + 3*JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(5) + JSON_OBJECT_SIZE(6) + JSON_OBJECT_SIZE(12) + 340;
DynamicJsonDocument doc(capacity);
DeserializationError error = deserializeJson(doc, client);
if (error) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Kon JSON");
lcd.setCursor(0, 1);
lcd.print("niet verwerken");
Serial.print("deserializeJson() failed: ");
Serial.println(error.c_str());
weatherLast = millis();
return;
}
long temp = doc["main"]["temp"].as<double>();
long humidity = doc["main"]["humidity"].as<long>();
lcd.clear();
lcd.setCursor(0, 1);
lcd.print(temp);
lcd.print("C | ");
lcd.print(humidity);
lcd.print("%");
Serial.print("Temperature: ");
Serial.print(temp);
Serial.println(" C");
Serial.print("Humidity: ");
Serial.print(humidity);
Serial.println("%");
client.stop();
weatherLast = millis();
}
uint32_t getTime() {
if (UDP.parsePacket() == 0) {
return 0;
}
UDP.read(ntpBuffer, NTP_PACKET_SIZE);
uint32_t ntpTime = (ntpBuffer[40] << 24) | (ntpBuffer[41] << 16) | (ntpBuffer[42] << 8) | ntpBuffer[43];
const uint32_t seventyYears = 2208988800UL;
uint32_t unixTime = ntpTime - seventyYears;
return unixTime + timeOffset;
}
void sendNTPpacket(IPAddress& address) {
memset(ntpBuffer, 0, NTP_PACKET_SIZE);
ntpBuffer[0] = 0b11100011;
UDP.beginPacket(address, 123);
UDP.write(ntpBuffer, NTP_PACKET_SIZE);
UDP.endPacket();
}
inline int getSeconds(uint32_t unixTime) {
return unixTime % 60;
}
inline int getMinutes(uint32_t unixTime) {
return unixTime / 60 % 60;
}
inline int getHours(uint32_t unixTime) {
return unixTime / 3600 % 24;
}