Introduction: ESP32/ESP8266 Weather Forecaster/Predictor
Using an ESP32 or ESP8266 we can forecast weather by reading air pressure from a sensor such as the BOSCH BMP085/180 or BME280.
Then by monitoring the changes in air pressure and categorising the changes thus:
- Rising quickly
- Rising
- Rising slowly
- Steady
- Falling slowly
- Falling
- Falling quickly
And applying the changes to a set of rules this enables the weather to be forecast based on air pressure at your location (adjusted from sea level with a offset) and then by monitoring changes over time, in this case 3 and 1 hours leading to a prediction with a good level of certainty.
Step 1: Hardware Either an ESP32 or ESP8266
The project uses an ESP32 or ESP8266 processor and the I2C bus to communicate with an OLED display of 1.3” or 0.96” size together with a BOSCH BMP180 or BME280 air pressure sensor.
The choices are the processor an ESP32 or ESP8266, then a suitable sensor either a BOSCH BMP180 or BME280 and then a display either a 1.3" OLED with SH22016 controller or alternatively a 0.96" OLED with a SSD1306 controller.
Step 2: BMP180 Sensor Type
This provided pressure and temperature, although in this project temperature is not used.
Step 3: BME280 Sensor Type
This sensor provides pressure, temperature and humidity, which if mounted at an outside location enables even more advanced forecasting to be achieved rather than using pressure alone,. For example, air temperature nearly always falls just before it rains, so this parameter can help improve forecast prediction, albeit in the short-term.
Step 4: Wiring It Together Using the I2C Bus
Use the following diagram to wire up the controller, sensor and OLED display. Most sensors use a +5v supply, so beware if using the 3.3v types as they will require an additional 3.3v regulator or a take off from the 3.3v available on most ESP32/ESP8266 development boards. IF your using a 3.3v system then make sure your OLED display will operate at that voltage and wire the sensors to by-pass the usual 3.3v regulator fitted on-board. You can obtain the Bosch sensors designed for 3.3v.
Connect the ESP32 or ESP8266 to the OLED and BMP/BME Sensors using the I2C bus connections. For example if you decide to use GPIO-5 for the I2C SDA function and GPIO-4 for the I2C SCL function then the source code statement that initiates the I2C bus support would be:
Wire.begin(5,4); // wire.begin(sda,scl)
Generally you can use any two pins to provide the I2C bus function, but be aware that other pins are often used for other functions, so be careful not to create a pin usage conflict.
Step 5: Software Set-Up
The source code needs to be adjusted depending on the hardware configuration. The BOSCH sensors require:
Device Driver Library Required
BMP085 or BMP180 Adafruit_BMP085
BME280 Adafruit_BME280
Both Adafruit libraries do-not provide support for the Bosch devices but are easily modified to enable support and compilation. See later.
The displays require the correct driver support, the most common screen driver device is the SSD1306 for the 0.96” OLED display or SH1106 for the 1.3” OLED variant.
The code works equally well on an ESP8266 but the time source requires some modification, see the ESP8266 source code version for the differences.
Step 6: 5 ADAFRUIT LIBRARY CHANGES REQUIRED
The
Adafruit sensor BME280 has an I2C address that has been set at 0x77 and if you are using an Adafruit device then no modification of the device library address is required.
However, if you have one of the many third-party devices these nearly always use the address 0x76 and require the following changes to the library file:
BME280 Modify the address in the library file: Adafruit_BME280.h to read thus:
#define BME280_ADDRESS (0x76)
Generally the BMP085 third-party devices use the address 0x77 as does the Adafruit variety.
In addition to device address changes the files Adafruit_BMP085.cpp and Adafruit_BME280.cpp need to be modified to remove a default Wire.begin() statement so that the ESP32 can have the required pins defined.
For the Adafruit_BMP085 library, edit the file Adafruit_BMP085.CPP and comment out the wire.begin statement:
boolean Adafruit_BMP085::begin(uint8_t mode) {
if (mode > BMP085_ULTRAHIGHRES) mode = BMP085_ULTRAHIGHRES;
oversampling = mode;
//Wire.begin(); //***************** Comment out
For the Adafruit_BME280 library, edit the file Adafruit_BME280.CPP and comment out the wire.begin statement:
bool Adafruit_BME280::begin(uint8_t addr) {
_i2caddr = addr; // init I2C or SPI sensor interface
if (_cs == -1) { // I2C
//Wire.begin(); //***************** Comment out
Step 7: 6 DAYLIGHT SAVING AND TIME ZONE ADJUSTMENTS
The source code time statement currently provided is for UK time and Daylight Saving Time is enabled, this requires a time configuration statement thus:
configTime(1*3600, 3600, "pool.ntp.org"); // +1hour (1*60*60=3600=+1hour) ahead for DST in the UK
The format of the ‘configtime’ statement is thus:
configTime(timezone, daylightoffset, primary_timeserver_address, secondary_timeserver_address);
therefore examples are:
configTime(1*3600, 3600, "pool.ntp.org"); // UK and DST is active
configTime(0, 0, "pool.ntp.org"); // UK and DST is not active
Step 8: 3-Hr Forecast Screen
The top line displays a real time clock that is updated every second together with the current Day of week and date.
An icon is displayed that corresponds to the forecast, in this example ‘Mostly Sunny’.
The second line displays the current air pressure in hPA. If you wish to convert to “ (inches) change the display of air pressure using a simple units conversion constant and change text from hPA to inches or “
The third line displays the change in air pressure over the time period being displayed for this screen 3 hours.
Step 9: 3-Hr Forecast Text Screen
This display provides the forecast text that corresponds to the weather icon in the previous screen.
When the forecast screen is the 3-hour or 1hr Segment and the forecast is either ‘No Change’ or ‘Clear Spells’ and depending on the average 1 or 3-hours of previous weather conditions preceding this forecast, the forecast test can have a suffix added thus:
- expect sun
- mainly cloudy
- expect rain
‘No change’ is assumed to be a continuation of the previous weather patterns, which the program averages for the given period; either 1 or 3-hours.
Step 10: Pressure Trend Screen
This display provides a
graph of pressure change over the last 24-Hrs. The reference is time-0 or the first column which will always be display as zero regardless of any historical value. It provides a useful visual indication of how pressure is changing over time.
Pressure is displayed at the following time periods in historical hours -24, -18, -12, -6, -3, -2, -1, 0:
- 0 now or since the last update
- -1 pressure 1-hour ago
- -2 pressure 2-hours ago
- -3 pressure 3-hours ago
- -6 pressure 6-hours ago
- -12 pressure 12-hours ago
- -18 pressure 18-hours ago
- -24 pressure 24-hours ago
The display on the far-left indicates the currency of the data in hours, so a display of 3 would mean the data is current up to the 3-hour column. The Y-axis is in hPA + or -
Step 11: Source Code and Youtube Video
These are the source files for the ESP32/ESP8266 variant together with a YouTube video and User Guide.
The files can also be downloaded from GitHub here: Weather Forecaster Source Code and other files
20 Comments
3 years ago
hi i tried your code it give a error, "invalid conversion from 'const char*' to 'const uint8_t* {aka const unsigned char*}' [-fpermissive] "
i don't know why because i am not in programming. i made necessory changes to work with bmp180 sensor.is it something else i am missing ?
Reply 3 years ago
The display driver has been updated so change 'const char*' to 'const uint8_t*’ in my code
Reply 3 years ago
hi i got it working, thank you very much.just have to change "const uint8_t" to make it working.
Reply 2 years ago
Same error here. Please, can you describe how to fix it.
Reply 3 years ago
What is the error line and code version your using there are 3? ESP32 or esp8266
Reply 3 years ago
default time format is 24 hour anyway to change it to 12 hour?
Tip 2 years ago
Lovely piece of code, Thank you!
For what it's worth I have managed to make some changes and refinements.
My hardware now is, ESP32, BMP280 and a 2.4" OLED (SSD1309)
Changes:
#1 Didn't like the tiny original 0.9" OLED so I changed to a 2.4" plus changed from I2C to SPI for display interface. Important to note that the 2.4" SSD1309 OLED can use the same library as the 0.9" SSD1306 OLED as you see in the attached picture. All details are in the Github repository for the library https://github.com/helmut64/OLED_SSD1306
#2 Modified the NTP configuration so it now knows both the timezone and if its Daylight savings time. I followed the NTP Clock code example by Frenoy Osburn https://www.bitsnblobs.com/network-time-using-esp8266
#3 Changed the screen scroll delay to a more suitable pace. I did this in the OLEDDisplayUi.cpp library itself. (setTimePerFrame(10000); //original 5000)
#4 Added a timer library (couldn't get millis to work reliably) to do a screen timeout and obviously added a wake button. This was the trickiest bit as I'm not a programmer per say and it took a while to figure out how to use the library's screen timeout function. https://github.com/contrem/arduino-timer
#5 Added an extra screen to display temperature
My sketch changes may not be the most efficient but they work. Sketch has been running for a couple of months now and has done the daylight savings change during that time.
You can view or download this modified version of the sketch from here https://pastebin.com/3XecVrDF
3 years ago
Hi, great project.
From the location where this gadget may be installed what is the expected diameter of its localized weather prediction. A good informed estimation will do for my purpose.
Thanks.
Paulo
Reply 3 years ago
About 20-30 miles, it depends on local pressure variations, but these are rarely localised, hence the estimate.
4 years ago on Step 8
I try to display temperature and I substitute line 261 with this one;
<display->drawStringMaxWidth(x+47,y+32,90,String(bme.readTemperature()));>
but nothing changes.
Further the program after some hours stops.
Thanks
Renzo Giurini
Reply 4 years ago
When you say nothing changes do you mean you don’t see the temperature at all?
You need to check the x, y coordinates are not off screen once you add the text width
Reply 4 years ago
I checked,coordinates are correct, there was another error in variable.
in any case after few hours the program stucks. I read something about this problem, but I don't remember where,
Thanks
Reply 4 years ago
Have you tried slowing down the refresh rate as the ESP8266 runs out of time if your reading a sensor and refreshing the screen at maximum rate.
6 years ago
Good to hear it's working OK now.
6 years ago
Okay, thanks. I'll study the code some more.
6 years ago
I just built this in the last couple of days and I can't figure out how "weather_extra_text" is displayed. I see where is it set, but where is it used? I'm using the ESP8266 version.
Thanks for the Instructable.
Reply 6 years ago
see my other explanation, but the extra text is added at e.g. Line 319 with the expression 'test?true:false' which calls either the 1hr or 3hr average checker as required. Frame 2 display is the 3hr forecast and frame 5 the 1hr variant so called with range=true for one and false for the other.
Reply 6 years ago
It only gets displayed (Extra-Text) if the conditions move to No Change and the preceding average value is say 'Sunny' then the prediction is more of the same so 'No Change, Expect Sun' or if the preceding weather was rain and No Change is forecasted, then the same thing happens (No Change, Expect Rain) it checks the average weather before the forecast change then adds whatever it was , most likely Rain so the extra-text is added for 'Expect Rain'. or if no significant weather precedes the 'No Change' forecast then most likely 'Cloudy Conditions' will follow. The forecast is saved for every hour to make the average based on a simple + / - number scale, so Sunny is say +3, Cloudy +2 and Rain -2 and so-on. The average if predominantly negative, is then mostly likely for rain or storms. Hope this helps.
6 years ago
That's a neat setup :)
Reply 6 years ago
My aim was not use any of the many weather data sources like Weather Underground as many people don't like to get an account, so using pressure trends is the next best solution and it's quite accurate. I've been running my setup for over 6-weeks now and the correlation with real weather is high, I would say >80%, but I have not been recording to be sure. Glad you like it.