Using an esp8266 and a DHT11 (temperature + humidity) sensor, I created a network of battery-powered sensors that I can put anywhere in my house. In this post I’ll explain how you can make your own.
The esp8266 WiFi modules are great, with their embedded microcontroller you can control a lot of devices via your WiFi network (your coffee machine for example!). With the help of a home automation server such as Domoticz, you can gather all the information from your sensors and switches into one space that allows you to monitor and control you whole house.
One of the basic sensor is temperature, and today you can find sensors that packs both temperature and humidity in one handy module, the DHT11. Its precision and range is not incredible (+-2 °C, cannot measure temperature below 0°C, etc…) but it is very cheap. (If you need a better sensor, the DHT22 is a great alternative, which of course comes with a higher cost).
Because I want to have my sensors anywhere without having to think about cables, I’ll use batteries for them (see this post about how I got a lot of cheap li-ion batteries, and this one about how I built a protection circuit for them). This of course means that the consumption needs to be minimal.
Lastly, the code running on the esp8266 needs to be very robust, as I do not want to go and restart them everyday because they crashed or lost connection to the server.
So, let’s get started! First we’ll see how we can make sure the esp8266 use a little power as possible by activating the deep sleep mode.
esp8266 and deep-sleep
As many of you, I’m using NodeMCU as a firmware for my esp8266, that allows me to upload lua scripts to them. Looking at the API of the lua scripts, I saw that there was a deep sleep mode available. This allow the module to almost entirely shutdown for a given period of time. Using this function I will be able to send the data from the sensor and go to deep sleep for a couple of minutes before sending the data again, hence having the module (almost) off most of the time.
But there’s a problem, in order to activate the deep sleep mode, you need to connect two pins of the esp8266 chip together: RST and XPD_DCDC. In later version of the esp8266 module, these pins are available easily and can be connected without problem. The version I use (ESP-01) do not have these pins available, so I had to actually solder them on the chip directly.
This was a very scary operation, but I managed using a 0.1mm insulated copper wire.

The end result.
Another way to reduce the consumption of the modules is to remove both the power and status leds from the board. I’m planning on doing that in the next version of my sensors.
Creating the circuit
The circuit is really straightforward, it contains three components:
- A 4×2 female pins socket for the esp8266 (so it can be easily removed for programming)
- A large capacitor to absorb peaks of current (bigger the better, I used 2200uF)
- The DHT11 module (that only adds a resistor and a capacitor to the sensor)
The two modules (sensor and esp8266) are powered with a 3.3V line, the capacitor is placed between the + and – of the power input and the DHT11 middle pin is connected to GPIO2 on the esp8266. (don’t forget to put CH_PD at VCC on the esp8266, otherwise it won’t work.)


OK, so you’ve got the hardware all setup, now we need to add virtual sensors to Domoticz, we will then use these placeholders to store the sensors data.
Setting up Domoticz
You will need to add a virtual hadware device, I called mine “esp8266_sensors”:
- In Domoticz web interface:
- click on the last tab “Setup”
- click on “Hardware”
- Under the list are the field for adding hardware, enter the name you want, select “Dummy” as type
- No data timeout
- Click ‘Add’ – Do not leave the page
Now that we have the higher level hardware, we can add virtual sensors
- While still on the Hardware page, click the “Create virtual sensors” button next to the new hardware you created
- As a type, put Temp+Hum
- Repeat this operation for each sensor you are setting up ( I did it 5 times)
- Now, we’ll configure the sensors, go in Setup > Devices
- You will see your newly added sensors in the list, if you click on the green arrow on their right, you’ll be able to input a name for it (something like balcony or fridge).
- You’re now all set. You need to take note of all your device unique identifier, in the column Idx. You will need to put this number in each esp8266 program.
Now, let’s program the modules to send temperature and humidity data at regular intervals.
Some programming
The code
You can find the program on github here. I tried to put a lot of comments in the code to make it as readable as possible, feel free to ask me if you have some questions about it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
-- Measure temperature, humidity and return the values as a combined string. -- Based on DHT11 code from esp8266.com local dht11 = {} local pin = 4 local Humidity = 0 local HumidityDec=0 local Temperature = 0 local TemperatureDec=0 local Checksum = 0 local ChecksumTest=0 function dht11.getData() Humidity = 0 HumidityDec = 0 Temperature = 0 TemperatureDec = 0 Checksum = 0 ChecksumTest = 0 --Data stream acquisition timing is critical. There's --barely enough speed to work with to make this happen. --Pre-allocate vars used in loop. bitStream = {} for j = 1, 40, 1 do bitStream[j]=0 end bitlength=0 gpio.mode(pin, gpio.OUTPUT) gpio.write(pin, gpio.LOW) tmr.delay(20000) --Use Markus Gritsch trick to speed up read/write on GPIO gpio_read=gpio.read gpio_write=gpio.write gpio.mode(pin, gpio.INPUT) --bus will always let up eventually, don't bother with timeout while (gpio_read(pin)==0 ) do end c=0 while (gpio_read(pin)==1 and c<100) do c=c+1 end --bus will always let up eventually, don't bother with timeout while (gpio_read(pin)==0 ) do end c=0 while (gpio_read(pin)==1 and c<100) do c=c+1 end --acquisition loop for j = 1, 40, 1 do while (gpio_read(pin)==1 and bitlength<10 ) do bitlength=bitlength+1 end bitStream[j]=bitlength bitlength=0 --bus will always let up eventually, don't bother with timeout while (gpio_read(pin)==0) do end end --DHT data acquired, process. for i = 1, 8, 1 do if (bitStream[i+0] > 2) then Humidity = Humidity+2^(8-i) end end for i = 1, 8, 1 do if (bitStream[i+8] > 2) then HumidityDec = HumidityDec+2^(8-i) end end for i = 1, 8, 1 do if (bitStream[i+16] > 2) then Temperature = Temperature+2^(8-i) end end for i = 1, 8, 1 do if (bitStream[i+24] > 2) then TemperatureDec = TemperatureDec+2^(8-i) end end for i = 1, 8, 1 do if (bitStream[i+32] > 2) then Checksum = Checksum+2^(8-i) end end ChecksumTest=(Humidity+HumidityDec+Temperature+TemperatureDec) % 0xFF return Temperature.."."..TemperatureDec..";"..Humidity.."."..HumidityDec end return dht11 |
Here is the main program, the important part here is to replace the following informations:
- deviceID is the sensor identifier within Domoticz, you can find it in the Idx column, in the Devices page of your Domoticz web interface.
- server_ip is the ip of the server hosting Domoticz
- wifi.sta.config(“yourSSID”,”yourpassword”) needs to be replaced by the informations from your WiFi router
- Thelocal cfg part needs to be set like this:
- ip needs to match your network mask, for me it is 192.168.0.X, but it might very well be 192.168.1.X or anything else.
- netmask should stay that way
- gateway is your WiFi router IP (generally)
- Tip: if you are not sure about what to put in there, you can type “ifconfig” on Linux or “ipconfig” on Windows, you should get these informations (netmask, getaway, IP base) from there.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
-- Starts the module and connect to server. print("DHT11 Domoticz v0.1") -- variables local dht11 = require("dht11") local deviceID = "20" local server_ip = "192.168.0.148" local server_port = 8080 local deep_sleep_time = 180 --seconds -- wifi connection config wifi.setmode(wifi.STATION) wifi.sta.config("yourSSID","yourpassword") local cfg = { ip="192.168.0.1"..deviceID, --static ip based on id netmask="255.255.255.0", gateway="192.168.0.1" } -- check every 0.5seconds if we can get an ip, once we get it start the TCP client tmr.alarm(0, 500, 1, function() gotIP = wifi.sta.setip(cfg) if ( wifi.sta.status() == 5 ) then print("connected to WiFi") tmr.stop(0) -- restart the module after 30seconds if it's still ON: -- it probably means it's stalled tmr.alarm(1, 30000, 1, function() node.restart() end) initSocketAndTransmitData() end end) -- initializes the connection with the DOmoticz server and sends the current data. -- Once data is sent and an answer is recieved, either restart the node or go into deep sleep -- (depends on what's the answer from Domoticz) function initSocketAndTransmitData() local socket = net.createConnection(net.TCP, 0) socket:connect(server_port, server_ip) --once we're connected, send the data socket:on("connection", function(conn) print("Connected to Domoticz") sendStatus(socket) end) -- once we get an answer from Domoticz, either: -- go into deep sleep if the command succeeded -- restart the node (and send another packet immediatly) if there was an error socket:on("receive", function(conn, message) if string.match(message, "\"status\" : \"OK\",") then print ("Got OK, going to sleep for a while now") node.dsleep(deep_sleep_time * 1000000) else print ("Got something else: "..message) node.restart() end end) end -- sends the sensor data (temperature and humidity) to the Domoticz server. function sendStatus(socket) local temperatureAndHumidity = dht11.getData() print("got "..temperatureAndHumidity) local json = "GET /json.htm?type=command¶m=udevice&idx="..deviceID.. "&nvalue=0&svalue="..temperatureAndHumidity.. ";0 HTTP/1.1\r\nHost: www.local.lan\r\n" .."Connection: keep-alive\r\nAccept: */*\r\n\r\n" socket:send(json) end |
1 |
require("main") |
Let’s program the esp8266 modules!
You can now plug all the sensors on the modules and install the batteries. You should see the result in Domoticz:
I hope that was helpful to you, I’ll be happy to help you out if you need help with your project!
The sensors are working great for em now, and the battery life is over a week. My next step is to put each sensor in a plastic case (because it looks less bomb-ish than the bare batteries with some circuits on them) and remove the LEDs from the modules to save even more power. I’ll make another post once I’m done with that.
[…] How-to: battery powered temperature and humidity sensors […]
Awesome write up! I’ve been working on the same thing but had not yet gotten this far, It looks very well done! Thank you for the write up. 😀
Hello Quindor,
Thanks for the kind words! I’ve been using your posts a lot to get inspiration on the Domoticz code, and I’m planning on making a dimmable led strip using your tutorials.
Hey, been having some trouble with the sensor, it seems to always return the temperature and humidity both as 255.255;
I have everything running off two double-a batteries, and the connection to the wifi is successful. Using the code from this site to read the DHT11… did I miss something?
Cheers!
Steve
Hmmm….build it , flashed and programmed it, but Always all values are 0.0;0.0
I am watching the signal on my scope and it seems to be ok, but still a no go.
Any help would be welcome
Ok, got mine working, two issues: 1, the blue bit with the 4 pins connects to a black bit with 3 pins, but the black bit changes the wire positions. Two different fixes, A, look at what the blue bit is mounted on and figure out how to change the wires (left and middle switch position), B, cut the blue bit away from the black bit. Second issue, with two AA batteries at full charge there’s a 10% fail rate. At half charge it fail 70%. Last 1/4 of the battery life are zero correct reads. Sensor wants 5 volt, two AA is only 3v. Separate power source for sensor corrects issue.
Hello Steve,
glad to see that you fixed the issue you had before – indeed the problem with 255;255 values is due to an incorrect polarity on the sensor (been having the same issue).
Concerning the power supply, the sensor is rated 3-5.5V for input power, so using the same 3.3V input as the esp8266 should works fine – but I can see how it might be an issue with non AA batteries.
Hello Henk,
I would try to connect a serial connection to the esp8266, you should get some debug output on the sensor.
If the value measured is 0 in the debug console, maybe the issue is on the pin you used to connect the sensor on the esp8266?
Tell me how it goes!
Hey guys 🙂 Thanks for the support. I’ll check all my connections again ( although I am pretty sure I made no mistake). And I’ll let you guys know what the result is.
@ Steve: Thanks for thinking with me, but I was aware of the 2 versions of the sensor. I use the blue casing with 4 leads, so i need to connect a resistor between + and data line. When I monitor the signal line on my scope, I can clearly see a data train every time the 8266 asks for data. And that’s the strange thing…..data is presented, but the 8266 comes up with 00.00 :00.00.
Ok….back to fiddeling with electronics and I’ll keep you posted.
ps. One more thing: Could it be the code is somewhat critical about reading the data? Maybe another version of sensor would help? I could order the DHT12….
TTYL guys!
I’m going to try using an ESP-12 and an analogue temperature only sensor, esp12 had an analog pin I believe. perhaps better to do analog read of a 2 pin sensor that doesn’t connect to battery instead of digital off a 3-pin that does
Sorry, my bad….it is a DHT22, and the pinout is the same as the 11, so no analog output, but much better resolution on the temp and humidity 🙂 Please let us know how it goes.
Again a ps : It’s an amazing project you made, mr Dumas! I love working on it!
After a busy week i started again, and still a no go 🙁
I have uploaded some pics of the DHT11 outgoing signal so maybe you guys have a clue why it is not working. Please have a look at them.
http://s772.photobucket.com/user/henkhulshof/library
Ok…update ☺
Last Night I flashed the latest floating point firmware.
I was amazed tot see the readings where correct ar last! Domoticz displayed temp and humity as is should. My happiness was short, howrever. After 1 reading the 8266 stopped running the code? I had to upload the code again tot get it working. After that I flashed the .95 floating firmware. This gave me an out of memory error when running the code.
Now is my question obvious: WHAT version of firmware are you guys using with a working module?
Tia. Henk
Henk: try compiling the script and delete the code file
Steve, you’re my hero 🙂
Compiling did the trick!
Temp sensor is up and running now.
I want to thank you all for the input and help.
I am so happy now, and probably sleep better!
THANKS.
Henk
Have a good one!
Thank you for manual. I want use Domoticz with esp-12 and arduino DIY sensors 433mhz with gate 433 to ethernet for my home.
Why you use LUA for this project? Maybe Arduino IDE for ESP more better?
Which esp8266 version would you recommend using for your project now?
There are version from ESP-01 to ESP-13.
You mentioned something about deep sleep mode and IO pins on newer versions of the esp8266.
Or the ESP-201 with antenna?
Just wondering: why add the deviceID in ‘ip=”192.168.0.1″..deviceID, –static ip based on id’
Bonjour,
merci pour votre travail. J’ai essayé mais voici ce que j’ai en retour dans esplorer :
21808
> dofile(‘main.lua’)
DHT11 Domoticz v0.1
> connected to WiFi
192.168.0.192
Connected to Domoticz
got 8.191;2.192
Got something else: HTTP/1.1 401 Unauthorized
Content-Length: 91
Content-Type: text/html
Unauthorized401 Unauthorized
c_ÇÏRSöâFjSöâFj›vêè
NodeMCU 0.9.6 build 20150704 powered by Lua 5.1.4
DHT11 Domoticz v0.1
>
et rien n’est mis à jour dans domoticz.
Merci par avance si vous pouvez m’indiquer quoi faire.
best regards.
Thierry.
Hello Thierry,
It looks like you are not allowed to send stuff to Domoticz.
you can try sending a JSON command directly to see what you get::8080/json.htm?type=command¶m=udevice&idx=&nvalue=0&svalue=TEMP and with values for your system.
– Go in your browser from a computer, and type something like this:
http://
change
This should write something like :
{
“status” : “ERR”
}
This step is to check if you are allowed to post things to Domoticz. If it doesn’t work check out this page, that talks about authentication for Domoticz JSON:
https://www.domoticz.com/wiki/Domoticz_API/JSON_URL's#Authorization
Tell me how it goes!
Cheers,
Benoit
Hi Benoit and everybody,
Congratulations on this project. Its simple and very powerfull. Nevertheless, I have been experiencing some trouble with it. I will expose the symptoms and I hope you can help me troubleshooting it.
I am developing the project with the ESP8266 -12Q. This should not be a problem since it is the same as the ESP8266 – 01 but with more exposed ports.
I am using a DTH22 sensor. I asume this also should not be a problem since is the same as DTH11 but with more accuracy.
I had uploaded the three files described above. (init.lua, main.lua, dht11.lua)
When I run the ESP8266, and I track over the serial port the stages of the main loop, I only get to “WIFI CONECTED” and then the module reset. Obviously this is the tmr.alarm. I had added some text into the main.lua file in order to track the failure but it seems the module cannot conect to the DOMOTICZ server. Here I have started to doubt about the configuration of the DOMOTICZ. I have never use it. I downloaded it. When I run it, the server seems to be 127.0.0.1 and the port is 8080. Since I cannot connecto to domoticz server I am asuming that I am doing something wrong with the following data:
deviceID is the sensor identifier within Domoticz, (This is OK, I’ve got it)
server_ip is the ip of the server hosting Domoticz (Which is the server hosting domoticz??? where do I need to look?? could it be 127.0.0.1 )
wifi.sta.config(“yourSSID”,”yourpassword”) (This is OK, I’ve got it)
Thelocal cfg part needs to be set like this:
ip needs to match your network mask, for me it is 192.168.0.X, but it might very well be 192.168.1.X or anything else.
netmask should stay that way
gateway is your WiFi router IP (generally)( with the IPCONFIG I get also an IPv4 could it be right? or should I put something else here?)
Should I do some setting configuration on Domoticz applications settings?
Other strange thing that happens to the module is that sometimes it seems to loose the firmware configuration, and in order to use the module I have to flash the firmware again. Any clues?
If somebody can help me with this questions I will be very gratefull.
Thanks again and greetings from Argentina!! (sorry for my english)
Juan Manuel
Hello Juan Manuel,
– server_ip is the ip of the server hosting Domoticz (Which is the server hosting domoticz???
Alright, so Domoticz is running on a computer, that’s your server. So the server is reachable via your computer IP.
127.0.0.1 is a special IP that basically means “myself”, so you can not connect to another computer using 127.0.0.1 as it will always refer to the computer itself.
What you want is the IP address of your computer (the ones that runs domoticz) on the network.
To do that you can either:
– On windows:
Click on the Start menu and type cmd.
When you see the cmd applications in Start menu panel, click it or just press enter.
A command line window will open. Type ipconfig and press enter.
You’ll see a bunch of information, but the line you want to look for is “IPv4 Address.”
– On linux:
Start a terminal and type “ifconfig”.
Once you get the IP; (Often looks like 192.168.0.XX or 192.168.1.XX° you can enter it in the lua file under “local server_ip”.
That should work, hopefully 🙂
Tell me how it goes,
Benoit
Hello Benoit,
It works like a charm now!! I thank you for the time you take to answer not only my questions but everyone’s questions!! I had many of the troubles the other guys had too. I also thanks Henk and Steve. Their little chat about the firmware version and the compiling trick help me troubleshooting the sensor reading and the out of memory issue.
Now I am encouraging con keep developing my home automation system!
Thanks again! and cheers from Argentina!
Juan Manuel Dominguez
Great projects, thanks a lot for sharing! What I wondered is: how do you know when to change the batteries? Is there some way to get a “battery level” measurement? Or do you go around each week and replace them?
When the battery are dead, Domoticz highlights the sensor in red, saying it didn’t get any data for more than X hours. That’s how I know I need to change the batteries.
Benoit
What if I don’t want to use deep sleep mode.
So I don connect the two pins of the esp8266 chip togetherRST and XPD_DCDC
Do I need to change the code ?
congratulations for the project ..
I tried to load it on my system and I wanted to ask you a couple of things
I loaded nodemcu_float_0.9.6 – dev_20150704 , then I will explore loaded main.lua order, init.lua , dht11.lua .
did I do something wrong?? does not work..
You have also tried to use the BMP180 Barometric Digital Pressure Sensor
thanks for your attention
Hello Michele,
Can you tell me a bit more about what you tried? Do you get any errors in the console?
I never tried the BMP180, but I recently ordered a couple of BME280, they do temperature, humidity and pressure – I’m planning on trying them out with the ESP as soon as I get them. Check out some info on them here: https://learn.adafruit.com/adafruit-bme280-humidity-barometric-pressure-temperature-sensor-breakout/overview
Cheers,
Benoit