PNG mini weather station logo

NEW!  Weather Station Version 3.1


PNG
                    dareweather webserver interface


DareWeather Background Story

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)
bme280.lua Meteorological data from BME280 temperature/humidity/pressure sensor
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 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

If working, the most recent weather reading will be presented below directly from the mini weather station!  Note that I have not yet been able to get the BMP180 sensor data to work with the SSD1306 OLED display -- for reasons that totally escape me.