Arduino MKR Weather Monitor

Simple weather station with WiFi forecast and measuring of temperature, humidity, air pressure via MKR ENV shield.

Apr 2, 2019

17588 views

22 respects

Components and supplies

1

MKR ENV Shield

1

ArduiTouch MKR kit

1

Arduino MKR1000

Apps and platforms

1

Arduino IDE

Project description

Code

WeatherForecast_MKR\WeatherForecast_MKR.ino

arduino

/* * Application note: Weather monitor for ArduiTouch MKR * (Arduino MKR 1010 and MKR ENV Shield are needed) * Version 1.0 * Copyright (C) 2019 Hartmut Wendt www.zihatec.de * * based on sources of Art Deco Weather Forecast Display: http://www.educ8s.tv * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses></http:>. */ #include <SPI.h> #include <WiFi101.h> #include <ArduinoJson.h> #include "Adafruit_ILI9341.h" #include <Adafruit_GFX.h> #include <MKRENV.h> /*______Define colors _______*/ // Color definitions #define BLACK 0x0000 #define BLUE 0x001F #define RED 0xF800 #define GREEN 0x07E0 #define CYAN 0x07FF #define MAGENTA 0xF81F #define YELLOW 0xFFE0 #define WHITE 0xFFFF #define GREY 0xC618 /*_______End of color definitions______*/ /*______Define pins for ArduiTouch _______*/ #define TFT_CS A3 #define TFT_DC 0 #define TFT_MOSI 8 #define TFT_RST 22 #define TFT_CLK 9 #define TFT_MISO 10 #define TFT_LED A2 #define HAVE_TOUCHPAD #define TOUCH_CS A4 #define TOUCH_IRQ 1 /*_______End of pin definitions______*/ /*______Wifi definitions_______*/ char* ssid = "yourssid"; // SSID of local network char* password = "yourpassword"; // Password on network int status = WL_IDLE_STATUS; WiFiClient client; char servername[]="api.openweathermap.org"; // remote server we will connect to /*_______End of Wifi definitions______*/ /*______Weather definitions_______*/ String APIKEY = "your_api_key"; String CityID = "your_city_id"; //your city int TimeZone = 1; //GMT +2 String weatherDescription =""; String weatherLocation = ""; float Temperature; boolean night = false; /*_______End of Weather definitions______*/ String result; int counter = 10; extern unsigned char cloud[]; extern unsigned char thunder[]; extern unsigned char wind[]; Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST); void setup() { Serial.begin(115200); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } // initialize the TFT tft.begin(); tft.setRotation(3); // landscape mode tft.fillScreen(BLACK);// clear screen tft.setCursor(70,110); tft.setTextColor(WHITE); tft.setTextSize(2); tft.print("Connecting..."); pinMode(TFT_LED, OUTPUT); digitalWrite(TFT_LED, LOW); // low to turn TFT backlight on; // attempt to connect to WiFi network: while (status != WL_CONNECTED) { Serial.print("Attempting to connect to SSID: "); Serial.println(ssid); // Connect to WPA/WPA2 network. Change this line if using open or WEP network: status = WiFi.begin(ssid, password); // wait 10 seconds for connection: delay(10000); } Serial.println("Connected to wifi"); // init MKR ENV shield if (!ENV.begin()) { Serial.println("Failed to initialize MKR ENV shield!"); while (1); } } void loop() { if(counter == 10) //Get new data every 30 minutes { counter = 0; getWeatherData(); getMKRENVData(); }else { counter++; delay(5000); Serial.println(counter); } } /********************************************************************//** * @brief readout MRK ENV Shield and show the result on the screen * @param[in] None * @return None *********************************************************************/ void getMKRENVData() { String sensor_value; // temperature sensor_value = ENV.readTemperature(); Serial.print("Temperature = "); Serial.print(sensor_value); Serial.println(" °C"); tft.setCursor(160,10); tft.setTextSize(2); tft.print("Temperature:"); tft.setCursor(160,40); tft.setTextSize(3); tft.print(sensor_value + " C"); tft.setCursor(273,33); tft.setTextSize(2); tft.print("o"); // humidity sensor_value = ENV.readHumidity(); Serial.print("Humidity = "); Serial.print(sensor_value); Serial.println(" %"); tft.setCursor(160,90); tft.setTextSize(2); tft.print("Humidity:"); tft.setCursor(160,120); tft.setTextSize(3); tft.print(sensor_value + " %"); // air pressure sensor_value = ENV.readPressure(); Serial.print("Pressure = "); Serial.print(sensor_value); Serial.println(" kPa"); tft.setCursor(160,170); tft.setTextSize(2); tft.print("Pressure:"); tft.setCursor(160,200); tft.setTextSize(3); tft.print(sensor_value); tft.setCursor(280,205); tft.setTextSize(2); tft.print("kPa"); } /********************************************************************//** * @brief client function to send/receive GET request data * @param[in] None * @return None *********************************************************************/ void getWeatherData() { String result =""; WiFiClient client; const int httpPort = 80; if (!client.connect(servername, httpPort)) { return; } // We now create a URI for the request String url = "/data/2.5/forecast?id="+CityID+"&units=metric&cnt=1&APPID="+APIKEY; // This will send the request to the server client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + servername + "\r\n" + "Connection: close\r\n\r\n"); unsigned long timeout = millis(); while (client.available() == 0) { if (millis() - timeout > 5000) { client.stop(); return; } } // Read all the lines of the reply from server while(client.available()) { result = client.readStringUntil('\r'); } result.replace('[', ' '); result.replace(']', ' '); char jsonArray [result.length()+1]; result.toCharArray(jsonArray,sizeof(jsonArray)); jsonArray[result.length() + 1] = '\0'; StaticJsonBuffer<1024> json_buf; JsonObject &root = json_buf.parseObject(jsonArray); if (!root.success()) { Serial.println("parseObject() failed"); } String location = root["city"]["name"]; String temperature = root["list"]["main"]["temp"]; String weather = root["list"]["weather"]["main"]; String description = root["list"]["weather"]["description"]; String idString = root["list"]["weather"]["id"]; String timeS = root["list"]["dt_txt"]; timeS = convertGMTTimeToLocal(timeS); int length = temperature.length(); if(length==5) { temperature.remove(length-1); } Serial.println(location); Serial.println(weather); Serial.println(temperature); Serial.println(description); Serial.println(temperature); Serial.println(timeS); clearScreen(); int weatherID = idString.toInt(); printData(timeS,temperature, timeS, weatherID); } /********************************************************************//** * @brief display the weather forecast on left display side * @param[in] timeString // displayed time * temperature // displayed outside temperature * weatherID // id for future weather condition * @return None *********************************************************************/ void printData(String timeString, String temperature, String time, int weatherID) { tft.setCursor(35,60); tft.setTextColor(WHITE); tft.setTextSize(2); tft.print(timeString); printWeatherIcon(weatherID); tft.setCursor(27,172); tft.setTextColor(WHITE); tft.setTextSize(2); tft.print(temperature); tft.setCursor(83,170); tft.setTextColor(WHITE); tft.setTextSize(1); tft.print("o"); tft.setCursor(93,172); tft.setTextColor(WHITE); tft.setTextSize(2); tft.print("C"); } /********************************************************************//** * @brief creates the small weather picture on the left side * @param[in] id // id for future weather condition * @return None *********************************************************************/ void printWeatherIcon(int id) { switch(id) { case 800: drawClearWeather(); break; case 801: drawFewClouds(); break; case 802: drawFewClouds(); break; case 803: drawCloud(); break; case 804: drawCloud(); break; case 200: drawThunderstorm(); break; case 201: drawThunderstorm(); break; case 202: drawThunderstorm(); break; case 210: drawThunderstorm(); break; case 211: drawThunderstorm(); break; case 212: drawThunderstorm(); break; case 221: drawThunderstorm(); break; case 230: drawThunderstorm(); break; case 231: drawThunderstorm(); break; case 232: drawThunderstorm(); break; case 300: drawLightRain(); break; case 301: drawLightRain(); break; case 302: drawLightRain(); break; case 310: drawLightRain(); break; case 311: drawLightRain(); break; case 312: drawLightRain(); break; case 313: drawLightRain(); break; case 314: drawLightRain(); break; case 321: drawLightRain(); break; case 500: drawLightRainWithSunOrMoon(); break; case 501: drawLightRainWithSunOrMoon(); break; case 502: drawLightRainWithSunOrMoon(); break; case 503: drawLightRainWithSunOrMoon(); break; case 504: drawLightRainWithSunOrMoon(); break; case 511: drawLightRain(); break; case 520: drawModerateRain(); break; case 521: drawModerateRain(); break; case 522: drawHeavyRain(); break; case 531: drawHeavyRain(); break; case 600: drawLightSnowfall(); break; case 601: drawModerateSnowfall(); break; case 602: drawHeavySnowfall(); break; case 611: drawLightSnowfall(); break; case 612: drawLightSnowfall(); break; case 615: drawLightSnowfall(); break; case 616: drawLightSnowfall(); break; case 620: drawLightSnowfall(); break; case 621: drawModerateSnowfall(); break; case 622: drawHeavySnowfall(); break; case 701: drawFog(); break; case 711: drawFog(); break; case 721: drawFog(); break; case 731: drawFog(); break; case 741: drawFog(); break; case 751: drawFog(); break; case 761: drawFog(); break; case 762: drawFog(); break; case 771: drawFog(); break; case 781: drawFog(); break; default:break; } } /********************************************************************//** * @brief convert the GMT time to local time * @param[in] timeS // tiem string to convert * @return converted time string *********************************************************************/ String convertGMTTimeToLocal(String timeS) { int length = timeS.length(); timeS = timeS.substring(length-8,length-6); int time = timeS.toInt(); time = time+TimeZone; if(time > 21 || time<7) { night=true; }else { night = false; } timeS = String(time)+":00"; return timeS; } /********************************************************************//** * @brief clears the screen * @param[in] None * @return None *********************************************************************/ void clearScreen() { tft.fillScreen(BLACK); } /********************************************************************//** * @brief draw picture for weather without rain, snow and clouds * @param[in] None * @return None *********************************************************************/ void drawClearWeather() { if(night) { drawTheMoon(); }else { drawTheSun(); } } /********************************************************************//** * @brief draw cloud picture with sun or moon behind * @param[in] None * @return None *********************************************************************/ void drawFewClouds() { if(night) { drawCloudAndTheMoon(); }else { drawCloudWithSun(); } } /********************************************************************//** * @brief draw the sun without any clouds * @param[in] None * @return None *********************************************************************/ void drawTheSun() { tft.fillCircle(64,120,26,YELLOW); } /********************************************************************//** * @brief draw the moon without any clouds * @param[in] None * @return None *********************************************************************/ void drawTheFullMoon() { tft.fillCircle(64,120,26,GREY); } /********************************************************************//** * @brief draw the moon * @param[in] None * @return None *********************************************************************/ void drawTheMoon() { tft.fillCircle(64,120,26,GREY); tft.fillCircle(75,113,26,BLACK); } /********************************************************************//** * @brief draw a single cloud * @param[in] None * @return None *********************************************************************/ void drawCloud() { tft.drawBitmap(0,75,cloud,128,90,GREY); } /********************************************************************//** * @brief draw a cloud with sun behind * @param[in] None * @return None *********************************************************************/ void drawCloudWithSun() { tft.fillCircle(73,110,20,YELLOW); tft.drawBitmap(0,76,cloud,128,90,BLACK); tft.drawBitmap(0,80,cloud,128,90,GREY); } /********************************************************************//** * @brief draw rain with sun or moon behind * @param[in] None * @return None *********************************************************************/ void drawLightRainWithSunOrMoon() { if(night) { drawCloudTheMoonAndRain(); }else { drawCloudSunAndRain(); } } /********************************************************************//** * @brief draw light rain (under the cloud) * @param[in] None * @return None *********************************************************************/ void drawLightRain() { tft.drawBitmap(0,75,cloud,128,90,GREY); tft.fillRoundRect(50, 145, 3, 13, 1, BLUE); tft.fillRoundRect(65, 145, 3, 13, 1, BLUE); tft.fillRoundRect(80, 145, 3, 13, 1, BLUE); } /********************************************************************//** * @brief draw moderate rain (under the cloud) * @param[in] None * @return None *********************************************************************/ void drawModerateRain() { tft.drawBitmap(0,75,cloud,128,90,GREY); tft.fillRoundRect(50, 145, 3, 15, 1, BLUE); tft.fillRoundRect(57, 142, 3, 15, 1, BLUE); tft.fillRoundRect(65, 145, 3, 15, 1, BLUE); tft.fillRoundRect(72, 142, 3, 15, 1, BLUE); tft.fillRoundRect(80, 145, 3, 15, 1, BLUE); } /********************************************************************//** * @brief draw heavy rain (under the cloud) * @param[in] None * @return None *********************************************************************/ void drawHeavyRain() { tft.drawBitmap(0,75,cloud,128,90,GREY); tft.fillRoundRect(43, 142, 3, 15, 1, BLUE); tft.fillRoundRect(50, 145, 3, 15, 1, BLUE); tft.fillRoundRect(57, 142, 3, 15, 1, BLUE); tft.fillRoundRect(65, 145, 3, 15, 1, BLUE); tft.fillRoundRect(72, 142, 3, 15, 1, BLUE); tft.fillRoundRect(80, 145, 3, 15, 1, BLUE); tft.fillRoundRect(87, 142, 3, 15, 1, BLUE); } /********************************************************************//** * @brief draw thunderstrom with rain * @param[in] None * @return None *********************************************************************/ void drawThunderstorm() { tft.drawBitmap(0,80,thunder,128,90,YELLOW); tft.drawBitmap(0,75,cloud,128,90,GREY); tft.fillRoundRect(48, 142, 3, 15, 1, BLUE); tft.fillRoundRect(55, 142, 3, 15, 1, BLUE); tft.fillRoundRect(74, 142, 3, 15, 1, BLUE); tft.fillRoundRect(82, 142, 3, 15, 1, BLUE); } /********************************************************************//** * @brief draw light snow fall (under the cloud) * @param[in] None * @return None *********************************************************************/ void drawLightSnowfall() { tft.drawBitmap(0,70,cloud,128,90,GREY); tft.fillCircle(50, 140, 3, GREY); tft.fillCircle(65, 143, 3, GREY); tft.fillCircle(82, 140, 3, GREY); } /********************************************************************//** * @brief draw moderate snow fall (under the cloud) * @param[in] None * @return None *********************************************************************/ void drawModerateSnowfall() { tft.drawBitmap(0,75,cloud,128,90,GREY); tft.fillCircle(50, 145, 3, GREY); tft.fillCircle(50, 155, 3, GREY); tft.fillCircle(65, 148, 3, GREY); tft.fillCircle(65, 158, 3, GREY); tft.fillCircle(82, 145, 3, GREY); tft.fillCircle(82, 155, 3, GREY); } /********************************************************************//** * @brief draw heavy snow fall (under the cloud) * @param[in] None * @return None *********************************************************************/ void drawHeavySnowfall() { tft.drawBitmap(0,75,cloud,128,90,GREY); tft.fillCircle(40, 145, 3, GREY); tft.fillCircle(52, 145, 3, GREY); tft.fillCircle(52, 155, 3, GREY); tft.fillCircle(65, 148, 3, GREY); tft.fillCircle(65, 158, 3, GREY); tft.fillCircle(80, 145, 3, GREY); tft.fillCircle(80, 155, 3, GREY); tft.fillCircle(92, 145, 3, GREY); } /********************************************************************//** * @brief draw cloud with sun and rain * @param[in] None * @return None *********************************************************************/ void drawCloudSunAndRain() { tft.fillCircle(73,110,20,YELLOW); tft.drawBitmap(0,72,cloud,128,90,BLACK); tft.drawBitmap(0,75,cloud,128,90,GREY); tft.fillRoundRect(50, 145, 3, 13, 1, BLUE); tft.fillRoundRect(65, 145, 3, 13, 1, BLUE); tft.fillRoundRect(80, 145, 3, 13, 1, BLUE); } /********************************************************************//** * @brief draw cloud and moon * @param[in] None * @return None *********************************************************************/ void drawCloudAndTheMoon() { tft.fillCircle(94,100,18,GREY); tft.fillCircle(105,93,18,BLACK); tft.drawBitmap(0,72,cloud,128,90,BLACK); tft.drawBitmap(0,75,cloud,128,90,GREY); } /********************************************************************//** * @brief draw cloud and moon and rain * @param[in] None * @return None *********************************************************************/ void drawCloudTheMoonAndRain() { tft.fillCircle(94,100,18,GREY); tft.fillCircle(105,93,18,BLACK); tft.drawBitmap(0,72,cloud,128,90,BLACK); tft.drawBitmap(0,75,cloud,128,90,GREY); tft.fillRoundRect(50, 145, 3, 11, 1, BLUE); tft.fillRoundRect(65, 145, 3, 11, 1, BLUE); tft.fillRoundRect(80, 145, 3, 11, 1, BLUE); } /********************************************************************//** * @brief draw wind * @param[in] None * @return None *********************************************************************/ void drawWind() { tft.drawBitmap(0,75,wind,128,90,GREY); } /********************************************************************//** * @brief draw fog symbol * @param[in] None * @return None *********************************************************************/ void drawFog() { tft.fillRoundRect(45, 100, 40, 4, 1, GREY); tft.fillRoundRect(40, 110, 50, 4, 1, GREY); tft.fillRoundRect(35, 120, 60, 4, 1, GREY); tft.fillRoundRect(40, 130, 50, 4, 1, GREY); tft.fillRoundRect(45, 140, 40, 4, 1, GREY); } /********************************************************************//** * @brief clear the of the weather picture only * @param[in] None * @return None *********************************************************************/ void clearIcon() { tft.fillRect(0,80,128,100,BLACK); }

Comments

Only logged in users can leave comments

hwhardsoft

0 Followers

0 Projects

Table of contents

Intro

22

0