PNG mini weather station logo

NEW!  Weather Station Version 3.3


PNG
                    dareweather webserver interface

JPG Dare Weather
                    Station

Technical Background References

The V2 and V3 NodeMCU development boards contain an ESP12E wireless chip, which in turn contains the ESP8266 microcontroller.  The NodeMCU board can run Artduino IDE or MicroPython, but the LUA language is implemented using the NodeMCU firmware, which I use:

I have used both the 2-pin I2C-based BME280 breakout boards and the 4-pin SPI-based version, but only use the I2C configuration:

Tools (in Linux) that are used:

DareWeather Recent History

2024/12/24: Surprise of surprises!  Even though I had proved to myself that the 'uart' module was not needed, later on with a different device install I was unable to upload any LUA modules to the NodeMCU -- the mystery stands, but I have accepted it.  As well, even though I had come to similar conclusions for the 'bme280_math' module, I now found that calls to the BME280 setup were no longer working.  So now I am back to this module build requirement:

This was built against the release branch and includes the following modules: bme280, bme280_math, file, gpio, http, i2c, net, node, rtctime, sjson, sntp, tmr, uart, wifi.

To my delight, I also found that the Sunrise-Sunset API site had improved their API so that passed timezone info via the 'tzid' parameter would convert the sunrise/set values to my local time *without* all the convoluted code I was forced to use to do this myself!

2024/12/22: Since I needed to reinitialize some of my older weather stations, I decided to test my earlier theory that I didn't need the 'bit' and 'uart' modules in my custom-made firmware, so I only chose what I now believe is the minimum set:

You successfully commissioned a NodeMCU custom build from the release branch. You selected the following 12 modules: bme280 file gpio http i2c net node rtctime sjson sntp tmr wifi.  We'll keep you posted by email about the progress of your build.  In the meantime I suggest you take a look at the build stats to find out how your firmware configuration compares to others in the community.

When I wrote this new firmware to my NodeMCU boards, I used this new minimal firmware, and it worked fine!

esptool.py --port /dev/ttyUSB0 write_flash -fm dio 0x0000 nodemcu-release-12-modules-2024-12-22-14-11-50-float.bin
esptool.py v4.7.0
Serial port /dev/ttyUSB0
Connecting....
Detecting chip type... Unsupported detection protocol, switching and trying again...
Connecting....
Detecting chip type... ESP8266
Chip is ESP8266EX
Features: WiFi
Crystal is 26MHz
MAC: 5c:cf:7f:95:10:23
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Flash will be erased from 0x00000000 to 0x00076fff...
Compressed 487424 bytes to 319597...
Wrote 487424 bytes (319597 compressed) at 0x00000000 in 28.2 seconds (effective 138.2 kbit/s)...
Hash of data verified.

I also noticed two more bugs, which I dealt with:
  • Even though I extracted the current TZ (timezone) from the World Time API site, I was no longer (?) using it in my HTML web page code, so I added it back in
  • The 'FLASH' button response had dropped off severely, and I noticed that when I had increased my timer for checking the BME280 weather values to 60 seconds, it had also done the same for detecting the button press, so I created a separate 1-second timer to check for this specific case instead.

So my basic initialization procedure looks like this on the Linux command line:

esptool.py --port /dev/ttyUSB0 erase_flash

esptool.py --port /dev/ttyUSB0 write_flash -fm dio 0x0000 nodemcu-release-12-modules-2024-12-22-14-11-50-float.bin


nodemcu-tool -p /dev/ttyUSB0 upload astro.lua baro.lua chrono.lua geo.lua init_ap.lua main_ap.lua main_html.lua main_ws.lua --compile

nodemcu-tool -p /dev/ttyUSB0 upload init.lua main_ap.html

I then restart the device, connect my WiFi to the 'DareWeather' SSID, navigate to '192.168.5.1', fill in the custom parameters, and reboot.  Results are then viewable on the HTML interface (if requested) and the ThingSpeak channel graphs (if requested and setup on that site).

2024/12/15: In attempting to install/test another ESP8266/NodeMCU for a weather station, I ran into some unexplained problems, forcing me to re-visit my code.  One change that was immediately required was the reduction of the time interval on the World Time API site, since the terms-of-use had changed over time and attempts to use it faster than once-per-minute were no longer accepted -- so I changed it to 10 minutes.  Another change was to reduce the ThingSpeak upload interval from once every 20 seconds to only once every minute -- allowing me room to have multiple devices uploading data at the same time.  I also notice that BME280 calls were returning (intentionally) inflated values, so I adjusted the code to divide by 100/1000/10000 appropriately.  I also removed the 'bme280.lua' module since I continue to use the older/deprecated internal BME280 code.

The most recent firmware build I did on the NodeMCU Build site was done with the most current 'release' and with the following modules:
bit,bme280,bme280_math,file,gpio,http,i2c,net,node,rtctime,sjson,sntp,tmr,uart,wifi
I now believe that the 'bme280_math' module was/is unnecessary for my deprecated method of calling the (internal) BME280 firmware code.

After using this firmware, the utilities that I used provide the following information:
NodeMCU 3.0.0.0 built on nodemcu-build.com provided by frightanic.com
        branch: release
        commit: 36cbf9f017d356319a6369e299765eedff191154
        release:
        release DTS: 202402250804
        SSL: false
        build type: float
        LFS: 0x0 bytes total capacity
        modules: bit,bme280,bme280_math,file,gpio,http,i2c,net,node,rtctime,sjson,sntp,tmr,uart,wifi
 build 2024-12-14 21:58 powered by Lua 5.1.4 on SDK 3.0.1-dev(fce080e)
2024/03/14: After a change to DST in my timezone, I was able to confirm that my code was not taking it properly into effect for the current time and for the time of sunrise/sunset, so fixes to code were required.  Time will tell (pun intended) if these fixes are working for myself, and for others that might live in different time zones.  In the process of making these changes, I was able to also verify a effective method of making changes like this with the least difficulty:
nodemcu-tool -p /dev/ttyUSB0 remove init.lua
(press reset button)
nodemcu-tool -p /dev/ttyUSB0 upload fixedmodule.lua --compile
screen /dev/ttyUSB0 115200                
(press reset button, watch debug messages, and verify new corrected operation)
(exit 'screen' tool via ctrl-a + ctrl-d)
(press reset button)

nodemcu-tool -p /dev/ttyUSB0 upload init.lua              
(press reset button)
(confirm correct operation)
2024/01/27: The easy universal 'Access Point' configuration mode at address 192.168.4.1 stopped working with my new internet provider Eero-based routers, and so I needed to tweak my code to something else, and so I picked 192.168.5.1 instead.

2021/12/12: An exhaustive one-month effort pays off!  My two primary goals were to:
  • Refresh my NodeMCU ESP8266 weather station builds using current firmware (rather than the 'frozen' nodemcu-1.5.4.1-final that I had used previously)
  • Add more functionality (if possible) beyond merely presenting the BME280 sensor data (with the extra-difficult severe memory limitations involved)

Meeting the first goal meant that I had to learn what syntax/style changes had been introduced into the Lua code base.  Meeting the second goal forced me to learn better methods of conserving memory usage, as well as seeking out other information-providing web-based APIs.

In addition to the orignal BME280 sensor data, DareWeather now provides current date/time, location, elevation, and astronomical information using freely-usable APIs!

Clicking on the left-column entries provides links to the relevant APIs, and clicking on the right-column entries returns the actual JSON data from the API calls made by the code itself -- in order to provide the full list of values (which DareWeather does not have sufficient memory to display):

DareWeather Modules

The LUA/HTML files used in this new version are here:

MODULE
PURPOSE
astro.lua Astronomy API from https://sunrise-sunset.org/api
baro.lua Elevation API from https://www.nrcan.gc.ca (Canada Only)
chrono.lua Chronological API from http://worldtimeapi.org/
geo.lua Geographical API from https://ip-api.com/
init.lua Initialization code for DareWeather
init_ap.lua Initialization for configuration Access Point
main_ap.html Main Access Point HTML
main_ap.lua Main Access Point code
main_html.lua Main Webserver HTML
main_ws.lua Main Webserver code

In order to minimize memory problems, all of the Lua code was compiled with the exception of 'init.lua'.

DareWeather Flowchart




The 'Reset Password' input allows the user to reset the DareWeather device in one of two ways:
  • By entering the original reconfiguration password, which causes the device to restart in 'Access Point' configuration mode at address 192.168.4.1 (which you need to sign onto with your wireless settings in order to setup the original configuration)
  • By entering the original reconfiguration password with the suffix of 'rb', which caurebootses the device to  with current settings (in case of temporary malfunction)

By appending the word 'json' at the end of the DareWeather webserver URL, a valid JSON output of the BME280 sensor values is produced -- so that other services have the opportunity to query/use them for another purpose.

DareWeather Wiring


The wiring scheme for the ESP8266/NodeMCU and BME280 sensor is extremely simple and was modified from the previous version:

BME280
NodeMCU
VIN
+3
GND
GND
SCL
D1 (GPIO5)
SDA
D2 (GPIO4)

PNF nodemcu
                        wired to bme280

DareWeather Building

After proper wiring of the BME280 sensor, the environment/system was constructed in this way, on a host PC (normally Linux-based), and copied over to the NodeMCU using a USB data cable:
  • The firmware itself was built using the NodeMCU Custom Build facility on the 'release' branch' with the options 'bit', 'bme280_math', 'file', gpio', 'http', 'i2c', 'net', 'node', 'rtctime', 'sjson', 'sntp', 'tmr', 'uart', and 'wifi.
  • The fresh NodeMCU/ESP8266 chip was erased:
$ esptool.py --port /dev/ttyUSB0 erase_flash
esptool.py v3.2
Serial port /dev/ttyUSB0
Connecting....
Detecting chip type... Unsupported detection protocol, switching and trying again...
Connecting....
Detecting chip type... ESP8266
Chip is ESP8266EX
Features: WiFi
Crystal is 26MHz
MAC: 2c:3a:e8:35:da:17
Uploading stub...
Running stub...
Stub running...
Erasing flash (this may take a while)...
Chip erase completed successfully in 6.7s
Hard resetting via RTS pin..
  • The custom-configured firmware was installed:
$ esptool.py --port /dev/ttyUSB0 write_flash -fm dio 0x0000 
nodemcu-release-14-modules-2021-11-23-17-26-37-float.bit-bme280_math-file-gpio-http-i2c-net-node-rtctime-sjson-sntp-tmr-uart-wifi.bin
esptool.py v3.2
Serial port /dev/ttyUSB0
Connecting....
Detecting chip type... Unsupported detection protocol, switching and trying again...
Connecting....
Detecting chip type... ESP8266
Chip is ESP8266EX
Features: WiFi
Crystal is 26MHz
MAC: 2c:3a:e8:35:da:17
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Flash will be erased from 0x00000000 to 0x00076fff...
Compressed 487424 bytes to 320411...
Wrote 487424 bytes (320411 compressed) at 0x00000000 in 28.3 seconds (effective 137.6 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...
  • The compilable lua files were uploaded:
$ nodemcu-tool -p /dev/ttyUSB0 upload xxxl.lua --compile
(node:14887) Warning: Accessing non-existent property 'padLevels' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)
[NodeMCU-Tool]~ Connected
[device]      ~ Arch: esp8266 | Version: 3.0.0 | ChipID: 0x35da17 | FlashID: 0x1640ef
[NodeMCU-Tool]~ Uploading "xxx.lua" >> "xxx.lua"...
[connector]   ~ Transfer-Mode: hex
[device]      ~  |- compiling lua file..
[device]      ~  |- success
[device]      ~  |- original Lua file removed
[NodeMCU-Tool]~ File Transfer complete!
[NodeMCU-Tool]~ disconnecting
...
...(other lua scripts uploaded with --compile option)
...
  • The HTML files were uploaded:
$ nodemcu-tool -p /dev/ttyUSB0 upload xxx.html 
(node:14950) Warning: Accessing non-existent property 'padLevels' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)
[NodeMCU-Tool]~ Connected
[device]      ~ Arch: esp8266 | Version: 3.0.0 | ChipID: 0x35da17 | FlashID: 0x1640ef
[NodeMCU-Tool]~ Uploading "xxx.html" >> "xxx.html"...
[connector]   ~ Transfer-Mode: hex
[NodeMCU-Tool]~ File Transfer complete!
[NodeMCU-Tool]~ disconnecting ...
...(other lua scripts uploaded without --compile option)
...
  • The non-compilable 'init.lua' file was uploaded:
$ nodemcu-tool -p /dev/ttyUSB0 upload init.lua 
(node:14950) Warning: Accessing non-existent property 'padLevels' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)
[NodeMCU-Tool]~ Connected
[device]      ~ Arch: esp8266 | Version: 3.0.0 | ChipID: 0x35da17 | FlashID: 0x1640ef
[NodeMCU-Tool]~ Uploading "init.lua" >> "init.lua"...
[connector]   ~ Transfer-Mode: hex
[NodeMCU-Tool]~ File Transfer complete!
[NodeMCU-Tool]~ disconnecting
  • The final list of uploaded files is checked:
$ nodemcu-tool -p /dev/ttyUSB0 fsinfo
(node:19032) Warning: Accessing non-existent property 'padLevels' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)
[NodeMCU-Tool]~ Connected
[device]      ~ Arch: esp8266 | Version: 3.0.0 | ChipID: 0x35da17 | FlashID: 0x1640ef
[device]      ~ Free Disk Space: 455 KB | Total: 486 KB | 12 Files
[device]      ~ Files stored into Flash (SPIFFS)
[device]      ~  - init.lua (2029 Bytes)
[device]      ~  - main_ws.lc (6196 Bytes)
[device]      ~  - main_ap.lc (3268 Bytes)
[device]      ~  - config.lc (444 Bytes)
[device]      ~  - main_html.lc (3888 Bytes)
[device]      ~  - geo.lc (500 Bytes)
[device]      ~  - baro.lc (488 Bytes)
[device]      ~  - chrono.lc (832 Bytes)
[device]      ~  - init_ap.lc (948 Bytes)
[device]      ~  - bme280.lc (2596 Bytes)
[device]      ~  - main_ap.html (3755 Bytes)
[device]      ~  - astro.lc (2580 Bytes)
[NodeMCU-Tool]~ disconnecting
  • NodeMCU/ESP8266 chip was restarted (unplug/plug power)

DareWeather Starting

When first activated, after the firmware/software has been loaded, the device initializes into a temporary 'Access Point' mode -- where a direct wifi connection is established between DareWeather and the computer used to configure the relevant parameters.  Upon connection to 192.168.4.1, the web browser screen looks like this:

PNG dareweather AP


The user uses whatever names, settings, values, etc. preferred.  If a ThingSpeak account is available (great idea!) the relevant channel and write key is entered here.  For full accuracy for location and elevation (which affects barometric pressure readings on the BME280 sensor), exact lat/lon and elevation (meter) values can be entered.  Alternatively, native geolocation and API services available on the web can be used to 'guess' the station location (anywhere) and elevation (Canada only).  Once everything is set as desired, the 'Save Configuration & Reboot' option is clicked, and the new IP location is used.

When the DareWeather device is (re)started, the following information is sent to the serial interface (invisible to the user unless connected to a terminal display at 115200 baud using a USB data cable):
NodeMCU 3.0.0.0 built on nodemcu-build.com provided by frightanic.com
 branch: release
commit: d4ae3c364bd8ae3ded8b77d35745b7f07879f5f9
 release:
release DTS: 202105102018
 SSL: false
 build type: float
 LFS: 0x0 bytes total capacity
 modules: bit,bme280_math,file,gpio,http,i2c,net,node,rtctime,sjson,sntp,tmr,uart,wifi
 build 2021-11-23 17:25 powered by Lua 5.1.4 on SDK 3.0.1-dev(fce080e)

DareWeather Placement

The ideal location for a DareWeather station is indoors, in a protected area or container where the devices and wires will not be disturbed, with good air circulation, and away from drafts and direct sunlight. 

But the most fun is when the device is placed outdoors, where a true weather station should live! :)  The electronics themselves are extremely robust as far as temperatures are concerned -- the main issues are these:

  • No rain/water/snow should be allowed on the device!  What I have been using are medium-sized empty inverted yogurt containers -- open at the top (now bottom) and the electronics stuffed at the bottom (now top) of the container.  This provides good air circulation (a closed container will heat up from the heat created), while at the same time keeping water out (as long as the container is fastened in such a way that it remains inverted.
  • The device should be placed out of direct sunlight, and off the ground.  Of course, the power supply will limit what the options are, but under a house eave/roof edge is a good compromise, where the wifi signal is still powerful enough to be utilized.

NEW!  Weather Station Version 2







Having proven the technology required to create a simple weather station with an ESP8266/NodeMCU microcontroller and a BME280 weather sensor (see Weather Station #1 below), it was time to try it again -- this time sending the data stream to ThingSpeak and Ubidots (in addition to the original Weather Underground feed).

My public channel page is here.  Apart from the challenge/frustration of working with misbehaving NodeMCU chips, another final one was enclosing/positioning this new weather station where minimal heat buildup would occur.  Despite my efforts, this station still registers hotter than Weather Station #1.

The wiring scheme for the ESP8266/NodeMCU and BME280 sensor is extremely simple:

BME180
NodeMCU
VIN
3V
GND
GND
SCL
D3 (GPIO0)
SDA
D2 (GPIO4)

Here is the LUA computer code that I use:

NEW!  IMPROVED!  Avoids hardcoding of configuration parameters.  Instead, relevant parameters are solicited during initial configuration phase, and then re-used once the ESP8266 is rebooted into its regular data-serving mode.  Also, web page display is now a standard feature.

init.lua
Embedded Text Document

init_ap.lua
Embedded Text Document

main_ap.lua
Embedded Text Document

main_bme280.lua
Embedded Text Document
main_ap.html
Embedded Text Document



Weather Station Version 1


JPG weather station display


It was something much different than I was used to, but I completed my first 2nd prototype IoT mini weather station (for a look at my 1st prototype version, see here).  In this 2nd version, the weather station is composed of two components:
  • Outdoors transmitter in weatherproof box [transmits weather sensor data to indoor receiver and to IMORDEN5 station of Weather Underground]
  • Indoors receiver in weatherproof box with display screen (as shown above) [receives remote weather sensor data and internal climate data and displays it]
After ordering the various pieces from eBay, I finally took the time to figure out how to program (in LUA computer language) the NodeMCU ESP8266 wifi SoC (system-on-a-chip) devkit running XTOS.  These devices are even simpler than the popular SBC (Single Board Computers) like the Raspberry Pi and C.H.I.P., which run a full Linux operating system i.e. the NodeMCU/ESP8266 is a SB/MC (Single-Board-MicroController) with only has 20k of memory and 4mb of storage!  Like the Raspberry Pi/C.H.I.P. systems, the NodeMCU/ESP8266 is powered by a regular 5v cell phone charger.  The term 'NodeMCU' refers to both the board configuration and the special firmware used to run the LUA programming language (see here for more information).

The particular make/model of NodeMCU ESP8266 I purchased is of the ESP-12E form factor and made by LoLin, but there are many other manufacturers and form factors available with different features.  I picked the one I did due to its cost, and the fact that it was a 'development' board with a USB power/data connection and lots of pins available.  The pinout (but not exactly the board layout) of my board is this:

JPG nodecmu pinout

In order to actually create a mini-weather-station, I also picked out some environmental sensors -- DHT22 temperature/humidty, BMP180 temperature/pressure, and BME280 temperature/humidity/pressure.  The BME280 is superior in all aspects, and I used it in the outside box, but since I had them anyways, I used the DHT22/BMP180 in the indoor box.  I also ended up getting a SSD1306 128x64 pixel OLED for a display on the indoor weather box.

Here is what I used for pin connections:

Indoor Box

DHT22
NodeMCU
VCC (PIN 1)
3V
DATA (PIN 2)
D7 (GPIO13)
GND (PIN 4)
GND
BMP180
NodeMCU
VIN
3V
GND
GND
SCL
D2 (GPIO4)
SDA
D1 (GPIO5)
SSD1306
NodeMCU
VIN
3V
GND
GND
SCL
D6 (GPIO12)
SDA
D5 (GPIO14)

Outdoor Box

BME180
NodeMCU
VIN
3V
GND
GND
SCL
D3 (GPIO0)
SDA
D2 (GPIO4)

The NodeMCU ESP8266 requires customized firmware to be generated, and NodeMCU Build is the site to do this.  For my purposes, in addition to the defaults selected (file/GPIO/net/node/timer/UART/WiFi), I also chose BMP085 (for the BMP180, which is fully compatible with BMP85), DHT (for the DHT22), BME280 (for the BME280), U8G & I2C (for the SSD1306 OLED), but also the options MQTT for future purposes (even though it is very easy to generate new firmware):
You successfully commissioned a NodeMCU custom build from the master branch. You selected the following 14 modules: 
bit bme280 bmp085 dht file gpio i2c mqtt net node tmr u8g uart wifi

Once the firmware was generated and downloaded to my Linux machine, I used ESPTool to upload it to the NodeCMU ESP8266 using the following command (where 'ttyUSBx' is whatever USB address the NodeMCU ESP8266 has at the time):

sudo python esptool.py --port /dev/ttyUSB45 write_flash -fm dio -fs 4MB 0x00000 \
../nodemcu-master-14-modules-2016-10-24-18-09-04-float.bin 0x3fc000 ../esp_init_data_default.bin
esptool.py v1.2-dev
Connecting...
Running Cesanta flasher stub...
Flash params set to 0x0240
Writing 442368 @ 0x0... 442368 (100 %)
Wrote 442368 bytes at 0x0 in 38.4 seconds (92.3 kbit/s)...
Writing 4096 @ 0x3fc000... 4096 (100 %)
Wrote 4096 bytes at 0x3fc000 in 0.4 seconds (89.7 kbit/s)...
Leaving...


Here is the LUA computer code that I use for the transmitter box:

init.lua
Embedded Text Document

bme280.lua
Embedded Text Document

Here is the LUA computer code that I use for the receiver box:


init.lua
Embedded Text Document

bmp180_dht22_oled.lua
Embedded Text Document

LUATool was then used to upload these code sections to both NodeCMU ESP8266 devices using the following command (where 'ttyUSBx' is whatever USB address the NodeMCU ESP8266 has at the time):

python luatool.py --port /dev/ttyUSBx --src xxx.lua --dest xxx.lua --verbose --baud 115200 --delay 2

Here is the parts list for this project:

1st NodeMCU ESP8266 V3 LUA CH340 WIFI Internet Development Board
$5.70
2nd NodeMCU ESP8266 V3 LUA CH340 WIFI Internet Development Board $4.28
BMP180 Digital Barometric Pressure Sensor $1.88
DHT22/AM2302 Digital Temperature And Humidity Sensor $4.27
BME280 Pressure Temperature Sensor Module for Arduino with IIC I2C $13.96
SSD1306 3-5V 0.96" 12C Serial 128X64 OLED LCD LED Display Module
$5.01
2pcs Waterproof Weatherproof Plastic Junction Box Enclosure Case DIY IP44 HS602
$4.75
Dupont Wire Male to Male Jumper Cables
$0.28
AC Converter Adapter DC 5V
N/A
TOTAL
$40.13

JPG bme280
                        outdoor box JPG base
                        station
Outdoor transmitter weather station box containing:
  • LoLin ESP8266 NodeMCU development board
  • Bosch BME280 environmental sensor
Indoor receiver weather station box containing:
  • LoLin ESP8266 NodeMCU development board
  • Aosong (Guangzhou) Electronics DHT22 environmental sensor
  • Bosch BMP180 environmental sensor
  • Solomon Systech SSD1306 OLED