Capturing Sensor Data: DHT22

Ok, having blinking LED's connected to an ESP8266 SOC is nice but is not very useful in terms of information exchange and/or interaction. This blog builds a simple IoT application which measures temperature and humidity and returns the measured values. This build is relatively straightforward build as we can leverage DHT22 temperature-humidity sensor and the corresponding native NodeMCU dht module.

Breadboard sketch

We need to wire up the DHT22 sensor to the NodeMCU which will provide ground and power - black and red wires respectively. Second the sensor data must be captured using the GPIO4 pin - purple wire. As this is an IoT use case I would like to enable deep sleep capabilities to conserve power in between sensor readings - yellow wire. The breadboard sketch is depicted below.

With the wiring in place we move on to the coding portion of this prototype. This blog assumes you have successfully flashed the NodeMCU with the modules necessary for this. For more details, check out my blog post Flash NodeMCU for more information.

Code

The NodeMCU firmware has a module available to interact with DHT sensors. The code snippets below fully utilize the functions provided by this module. In addition, the wifi module is used to connect the ESP8266 SoC onto the internet.

config.lua

The variables required for this sketch are stored in a separate file for easy maintenance. In this case we need variables for the NodeMCU wifi and dht modules. A constant is declared for the duration of the deep sleep cycle in milliseconds.

--[[
config.lua | Tiest van Gool

Global variables definitions for usage across various lua scripts  
--]]

--wifi module
wifi_ssid = "YOUR NETWORK"  
wifi_password = "YOUR PASSWORD"

--dht module
dht_pin = 2  -- Pin for DHT22 sensor (GPIO4)  
dht_temp_calc = 0  -- Calculated temperature  
dht_humi_calc = 0  -- Calculated humidity

--sensor reading interval
dsleep_time = 60000 --sleep time in microseconds (us) 

-- Status Message
print("Global variables loaded")  

dht22.lua

With the necessary variables defined we move forward with the code that does the heavy lifting. If we examine the code below closer we can identify 3 different functions:

  • First a connection is made to the wifi network using NodeMCU's wifi module. Without connectivity to the network no further actions are taken.
  • Function func_read_dht leverages NodeMCU's dht module to read the temperature and humidity information as collected by the dht22 sensor. Once the information is retrieved its outputted in the serial window.
  • The routine func_exec_loop executes the logic as described previously and once successfully completed initiates deep sleep mode using the node.dsleep command. Upon waking up the ESP8266 unit starts up and initiates the init.lua script.
--[[
dht22.lua | Tiest van Gool  
Script connects to internet through NodeMCU wifi module.  
Once connection is established dht module and temperature and humidity is retrieved.  
--]]

-- Load global user-defined variables
dofile("config.lua")

-- Connect to the wifi network using wifi module
wifi.setmode(wifi.STATION)  
wifi.sta.config(wifi_ssid, wifi_password)  
wifi.sta.connect()

-- Read out DHT22 sensor using dht module
function func_read_dht()  
  status, temp, humi, temp_dec, humi_dec = dht.read(2)
  if( status == dht.OK ) then
-- Integer firmware use this code
    print("DHT Temperature: "..math.floor(temp).."."..temp_dec.." C")
    print("DHT Humidity: "..math.floor(humi).."."..humi_dec.." %")
-- Float firmware uuse this code
--    print("DHT Temperature: "..temp.." C")
--    print("DHT Humidity: "..humi.." %")
  elseif( dht_status == dht.ERROR_CHECKSUM ) then          
    print( "DHT Checksum error" )
  elseif( dht_status == dht.ERROR_TIMEOUT ) then
    print( "DHT Time out" )
  end
end

-- Execute sensor reading and enter deep sleep
function func_exec_loop()  
  if wifi.sta.status() == 5 then  --STA_GOTIP
    print("Connected to "..wifi.sta.getip())
    tmr.stop(1) --Exit loop
    func_read_dht() --Retrieve sensor data
    print("Going into deep sleep mode for "..(dsleep_time/1000).." seconds.")
    node.dsleep(dsleep_time*1000)
  else
    print("Still connecting...")
  end
end

tmr.alarm(1,500,tmr.ALARM_AUTO,function() func_exec_loop() end)  

init.lua

NodeMCU uses init.lua as the auto executable which is invoked upon boot-up. The script below calls the dht22.lua. It contains a 15 second delay to allow for cancelling the excution in the situation of an error in order to interrupt and endless loop.

--[[
init.lua | Tiest van Gool

Init.lua is automatically executed on bootup of the NodeMCU. This launcher file loads the actual init_XYZ file only when everything has been tested and debugged.  
A 15 second delay has been added in case of error and enable abort.  
--]]


-- Set local variable
FileToExecute="dht22.lua"

-- Set timer to abort initialization of actual program
print("You have 15 second to enter file.remove('init.lua') to abort")  
tmr.alarm(0, 15000, 0, function()  
  print("Executing: ".. FileToExecute)
  dofile(FileToExecute)
end)  

With all the Lua based scripts they can be transferred to the ESP8266 using Luatool. If all scripts have been successfully transferred and NodeMCU is restarted the result should be something as depicted in the screenshot below.

Even though wifi connectivity is established its not leveraged for communication of the sensor data. The next blog entry will introduce the NodeMCU's mqtt module. MQTT is a machine-to-machine (M2M)/"Internet of Things" connectivity protocol. Leveraging this protocol the DHT22 sensor data will be wireless communicated to a broker/server for visualization without a serial communication channel.

Tiest van Gool

Boulder, CO

comments powered by Disqus