Making a NodeMCU Lua ESP8266 weather station

If a blinky LED is the IoT equivalent of “Hello, World!”, then hooking up a temperature and humidity sensor to the internet is the GOTO 10 that most of us like to do. Far be it for me to buck convention – after a few weeks of experimentation, it was time to set up a NodeMCU Lua ESP8266 weather station, pairing one of my ESP8266 dev boards with a DHT22/AM2302 digital temperature and humidity sensor on a breadboard, dropped into a Costco “Chocolates of the World” container for some weather protection and chucked out onto the deck with an old phone charger so that I can check the temperature outside without getting out of my bed.

While I’m at it, I may as well make it have a machine-readable interface too, so that (eventually) I can read the data from the ESP board from my Raspberry Pi and throw the data up into Azure and track things over time. But that’s for another day – today’s post covers the hardware setup and the code I run on the ESP8266 which provides either a human-readable web page or a JSON-like string for sending to the cloud.

What you need

Hardware setup

I love the ESP8266 boards, because you can just hook them up to a breadboard and some components in a matter of minutes. The DHT22 sensor is super-simple to connect too, here’s how it goes:

ESP8266, DHT22, and some beer

Very straightforward – all the pins on the ESP8266 dev board are labelled, and the pins on the DHT22 are as follows:

DHT22 Pinout
DHT22 Pinout

All you need to do is:

  • Plug your EP8266 development board into a breadboard
  • Similarly, plug your DHT22 temperature sensor into the breadboard
  • Connect pin 1 on the DHT22 to the 3.3v output of the ESP8266
  • Connect pin 2 on the DHT2 to D4 on the ESP8266
  • Connect pin 4 on the DHT22 to GND on the ESP8266

With the hardware all wired up, you’ll need some software on your ESP8266 to query the sensor and serve up the data. Here’s how I chose to do it.

Lua weather node script

There are two ways I want to be able to get the temperature data from my weather station node – directly from the ESP chip from a web browser on my phone, and programmatically from my Raspberry Pi so that I can upload the data to Azure for historical reporting and analysis.

Both of these methods are simple to achieve with a Lua script, as I can run a web server on the ESP board and respond to the query received as appropriate – when I hit the device from my phone, I’ll serve up a web page with temperature and humidity data, and by sending a custom query from my Pi (adding a “machine” parameter to the URL) I can get some semi-JSON formatted data to send to the cloud. FIrst of all you’ll need to visit Javier Yanez’s repo on GitHub and download his excellent DHT22 library, and upload that to your ESP8266 unit, and then create your own customer init.lua script to make use of it. Here’s my all-up code:

-- static IP setup from http://www.domoticz.com/wiki/ESP8266_WiFi_module

wifi.setmode(wifi.STATION)
wifi.sta.config("<your SSID>","your WIFI password")
wifi.sta.connect()
wifi.sta.setip({ip="192.168.1.105",netmask="255.255.255.0",gateway="192.168.1.1"})
print("ESP8266 mode is: " .. wifi.getmode())
print("The module MAC address is: " .. wifi.ap.getmac())
print("Config done, IP is "..wifi.sta.getip())

-- set up some DHT22 things from https://github.com/javieryanez/nodemcu-modules/tree/master/dht22
PIN = 4 --  data pin, GPIO2
dht22 = require("dht22_min")
chipserial = node.chipid()

-- run the server

srv=net.createServer(net.TCP, 4)
print("Server created on " .. wifi.sta.getip())
srv:listen(80,function(conn)
conn:on("receive",function(conn,request)
print(request)

dht22.read(PIN)
t = dht22.getTemperature()
h = dht22.getHumidity()

if string.match(request, "machine") then
conn:send("\"Temperature\": \""..((t-(t % 10)) / 10).."."..(t % 10).."\", \"Humidity\": \""..((h - (h % 10)) / 10).."."..(h % 10).."\"")
else
conn:send('<html>')
conn:send('<title>On Deck</title></head>')
conn:send('<body bgcolor=\"#ffffff\">')
conn:send('<center>')
conn:send('<table bgcolor=\"#0000ff\" width=\"90%\" border=\"0\">')
conn:send('<tr>')
conn:send('  <td><font size=\"2\" face=\"arial, helvetica\" color=\"#ffffff\"><center>Temperature</center></font></td>')
conn:send('</tr>')
conn:send('<tr>')
conn:send('  <td><font size=\"7\" face=\"arial, helvetica\" color=\"#ffffff\"><center>'..((t-(t % 10)) / 10).."."..(t % 10)..'&deg;C</center></font></td>')
conn:send('</tr>')

conn:send('<tr>')
conn:send('  <td><font size=\"2\" face=\"arial, helvetica\" color=\"#ffffff\"><center>Humidity</center></font></td>')
conn:send('</tr>')
conn:send('<tr>')
conn:send('  <td><font size=\"5\" face=\"arial, helvetica\" color=\"#ffffff\"><center>'..((h - (h % 10)) / 10).."."..(h % 10)..'%</center></font></td>')
conn:send('</tr>')

conn:send('</table>')
conn:send('</center>')
conn:send('</body></html>')
end

end)
end)

As you can see, I:

set up a static IP address

Check the incoming URL to see if it contains the string “machine”

  • if it does, deliver a kind-of JSON-formatted string that my Pi can parse and process (see a future blog post for details)
  • if it doesn’t, deliver the environmental data as a nicely formatted HTML page, thus:
Temperature and humidity
Show me the temperature

Now from my Pi, I can use curl to grab a string that looks like this:

Temperature Service
Temperature Service

and I’ll show you in a future post how to upload that to Azure so we can keep a log of what the weather’s been like.

Leave a Reply

Your email address will not be published. Required fields are marked *

Read previous post:
Stone Stochasticity Project Master Of Disguise
Stone Stochasticity Project Master Of Disguise Imperial Golden Stout

“There is no happenstance or coincidence. Dumb luck is a fallacy and randomness a commonly accepted mistruth. Much of what...

Close