{"id":1555,"date":"2019-08-31T03:11:35","date_gmt":"2019-08-31T03:11:35","guid":{"rendered":"https:\/\/bitcows.com\/?p=1555"},"modified":"2024-05-10T18:03:06","modified_gmt":"2024-05-10T18:03:06","slug":"esp32-weather-station","status":"publish","type":"post","link":"https:\/\/bitcows.com\/?p=1555","title":{"rendered":"ESP32 Weather Station"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/bitcows.com\/wp-content\/uploads\/2019\/08\/weatherWidget-225x300.jpg\" alt=\"\" width=\"225\" height=\"300\" class=\"alignnone size-medium wp-image-1556\" \/><\/p>\n<h3>\nComponenents Needed<br \/>\n<\/h3>\n<p>&#8211; ESP 32 Breakout Board<br \/>\n&#8211; 128&#215;63 OLED<br \/>\n&#8211; Momentary button<br \/>\n&#8211; 10k Resistor<br \/>\n&#8211; <a href=\"https:\/\/darksky.net\/dev\" rel=\"noopener noreferrer\" target=\"_blank\">Darksky API Key<\/a><\/p>\n<h3>\nNot interested in learning just want the code?<br \/>\n<\/h3>\n<p><a href=\"https:\/\/github.com\/djmason9\/WeatherStation\" rel=\"noopener noreferrer\" target=\"_blank\">Full Code<\/a><\/p>\n<h3>\nExpected Knowledge<br \/>\n<\/h3>\n<p>&#8211; Basic understanding of ESP32 and how to connect it<br \/>\n&#8211; How to push code to ESP32 using the Arduino IDE<br \/>\n&#8211; Basic understanding of C and coding in Arduino<\/p>\n<h3>\nThe Overview<br \/>\n<\/h3>\n<p>This app uses Darksky Free API to gather all its data.<\/p>\n<p><a href=\"https:\/\/darksky.net\/\" rel=\"noopener noreferrer\" target=\"_blank\">https:\/\/darksky.net\/<\/a><br \/>\nExample:<br \/>\n<code>https:\/\/api.darksky.net\/forecast\/[API_KEY]\/33.307575,-111.844940?exclude=minutely,hourly,alerts,flags<\/code><\/p>\n<p>I used ArduinoJson lib (5.13.5) to parse the response from the API, the WiFI lib to connect to the WiFi Access Point.<\/p>\n<p>Open the Arduino Library Manager<br \/>\nSearch for \u201cArduinoJson\u201d<\/p>\n<p>The <a href=\"https:\/\/github.com\/ThingPulse\/esp8266-oled-ssd1306\" rel=\"noopener noreferrer\" target=\"_blank\">https:\/\/github.com\/ThingPulse\/esp8266-oled-ssd1306<\/a> is a great LCD lib to allow the ESP32 to chip to easily communitcate with the display<br \/>\nI wrote my own font lib and graphics lib for the graphics using:<br \/>\n<a href=\"http:\/\/oleddisplay.squix.ch\/#\/home\" rel=\"noopener noreferrer\" target=\"_blank\">http:\/\/oleddisplay.squix.ch\/#\/home<\/a> for fonts and <a href=\"http:\/\/chilipeppr.com\/esp32\" rel=\"noopener noreferrer\" target=\"_blank\">http:\/\/chilipeppr.com\/esp32<\/a> to convert the images<br \/>\nImages are in <code>WeatherGraphics.h<\/code> and <code>MoonPhase.h<\/code><br \/>\n<code>time.h<\/code> and <code>math.h<\/code> are used to format the Unix time stamps to a readable date and round temperatures<\/p>\n<pre class=\"prettyprint\">#include \"WeatherGraphics.h\"\n#include \"CustomDisplayFonts.h\"\n#include \"MoonPhase.h\"\n#include <ArduinoJson.h>\n#include <WiFi.h>\n#include <HTTPClient.h>\n#include \"SSD1306.h\"\n#include \"ArduinoSort.h\"\n#include \"time.h\"\n#include \"math.h\"<\/pre>\n<p>The screen is a 128&#215;64 i2c LCD. You can get these on ebay or adafruit pretty cheap.<br \/>\n<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/bitcows.com\/wp-content\/uploads\/2019\/08\/128x64-Blue-I2C-OLED-Display.png\" alt=\"\" width=\"209\" height=\"209\" class=\"alignnone size-full wp-image-1583\" \/><br \/>\nPinout is pretty straight forward. 3.3v and ground. The pin 21 and 22. I also wired in a button, for this you will need a momentary button and a 10k resistor. That is connected to pin 23<br \/>\n<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/bitcows.com\/wp-content\/uploads\/2019\/08\/weatherstationpin-1024x450.png\" alt=\"\" width=\"1024\" height=\"450\" class=\"alignnone size-large wp-image-1586\" \/><\/p>\n<p>This is a pinout of the ESP32 I have for this.<br \/>\n<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/bitcows.com\/wp-content\/uploads\/2019\/08\/ESP32-S-Pinout.png\" alt=\"\" width=\"800\" height=\"600\" class=\"alignnone size-full wp-image-1587\" \/><\/p>\n<h3>\nDeeper Code Dive<br \/>\n<\/h3>\n<p>Ok lets talk about whats going on in the code. If you don&#8217;t care about this just skip this section and you&#8217;re done. <\/p>\n<p>The main loop is where all the button action takes place. Wiring up the button pin produces a high button state which means when pressed this code will run. The loop runs constantly so if you hold the button down it will cycle through these conditions every 600th of a second. As you can see the default is the DAILYWEATHER and as you click the button it increments by one. Then once its at the last one (3) it sets it back to the start so we can keep looping. Lastly there is a call that happens every 9 minutes (9000)<\/p>\n<pre class=\"prettyprint\">\nint updateWeather = 0;\nint countDownSeconds = 9000;\nenum Screens\n{\n    DAILYWEATHER = 1,\n    MOONPHASE = 2,\n    THREEDAY = 3\n};\nint screenId = DAILYWEATHER;\nvoid loop()\n{\n    int buttonState = digitalRead(btnPin);\n    \/\/ Serial.println(screenId);\n    if (buttonState == HIGH) \/\/(buttonState != previousButtonState))\n    {\n        screenId++;\n\n        displayWeather = false;\n        if (screenId == MOONPHASE)\n        {\n            display.clear();\n            drawMoonPhase();\n        }\n        else if (screenId == THREEDAY)\n        {\n            threeDayforcast();\n        }\n        else if (screenId = DAILYWEATHER)\n        {\n            display.clear();\n            drawCurrentWeatherData();\n            screenId = DAILYWEATHER;\n        }\n\n        delay(500);\n    }\n\n    delay(100);\n\n    updateWeather++;\n\t\/\/called every 9 mins\n    if (updateWeather % countDownSeconds == 0)\n    {\n        callWeatherApi(true);\n    }\n}<\/pre>\n<p>The API returns back a string of an icon, but I can&#8217;t use icons since i&#8217;m using <code>ints<\/code> to represent icons. So I created a map of icons that map to the enums of icons.<\/p>\n<pre class=\"prettyprint\">String jsonMap = \"{\\\"partly-cloudy-night-sm\\\":18,\\\"clear-day-sm\\\":10,\\\"rain-sm\\\":11,\\\"snow-sm\\\":12,\n\\\"partly-cloudy-day-sm\\\":13,\\\"sleet-sm\\\":14,\\\"wind-sm\\\":15,\\\"cloudy-sm\\\":16,\n\\\"thunderstorm-sm\\\":17,\\\"partly-cloudy-day\\\":0,\\\"clear-day\\\":1,\\\"clear-night\\\":7,\\\"rain\\\":2,\\\"snow\\\":3,\n\\\"partly-cloudy-night\\\":4,\\\"sleet\\\":5,\\\"wind\\\":6,\\\"cloudy\\\":8,\\\"thunderstorm\\\":9,\\\"clear-night-sm\\\":19}\";<\/pre>\n<p>I feel like most everything else is pretty self explanitory code wise.<\/p>\n<p><strong>NOTE<\/strong>: if you have a screen with a yellow and blue color scheme there is a boolean at the top that will shift the icons for you.<br \/>\n<code>\/\/NOTE FOR A SCREEN WITH A YELLOW TOP AND BLUE BOTTOM CHECK true<br \/>\nbool isYellow = true;<\/code><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Componenents Needed &#8211; ESP 32 Breakout Board &#8211; 128&#215;63 OLED &#8211; Momentary button &#8211; 10k Resistor &#8211; Darksky API Key Not interested in learning just want the code? Full Code Expected Knowledge &#8211; Basic understanding of ESP32 and how to connect it &#8211; How to push code to ESP32 using the Arduino IDE &#8211; Basic&hellip;<\/p>\n<p class=\"more-link\"><a href=\"https:\/\/bitcows.com\/?p=1555\" class=\"themebutton\">Read More<\/a><\/p>\n","protected":false},"author":1,"featured_media":2292,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9,12,14],"tags":[],"class_list":["post-1555","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-coding","category-electronics","category-hacking"],"_links":{"self":[{"href":"https:\/\/bitcows.com\/index.php?rest_route=\/wp\/v2\/posts\/1555","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bitcows.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bitcows.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bitcows.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bitcows.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1555"}],"version-history":[{"count":1,"href":"https:\/\/bitcows.com\/index.php?rest_route=\/wp\/v2\/posts\/1555\/revisions"}],"predecessor-version":[{"id":2293,"href":"https:\/\/bitcows.com\/index.php?rest_route=\/wp\/v2\/posts\/1555\/revisions\/2293"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/bitcows.com\/index.php?rest_route=\/wp\/v2\/media\/2292"}],"wp:attachment":[{"href":"https:\/\/bitcows.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1555"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bitcows.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1555"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bitcows.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1555"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}