Want to join the Internet of Things device making frenzy? This short guide introduces the ESP8266-01, the brains behind many hobbyist IoT devices, by making a simple temperature and humidity sensor. It offers a chance to practice your soldering skills and lets you get aquainted with flashing the ESP8266-01 with custom firmware and at the end you’ll be able to build your own swanky dashboard for viewing the sensor readings.
You’ll need the following tools to complete the project, most hobbyist are likely to have these already and they are available in pretty much all DIY stores.
- Soldering Iron & Solder (try and get decent solder, it flows much better than the cheap stuff)
- Small Hack Saw
- Veroboard / Stripboard Track Cutter (or 4mm drill bit)
- A computer with a USB port for programming
- 3.3v USB TTL UART Converter Module
- WiFi Internet Access
- Micro USB Phone charger capable of >500mA @ 5v (Do not power this device directly from your computer’s USB port, it could draw more power than the USB standard and damage your PC)
- Dry & clean washing up sponge
- A webserver capable of running a PHP and a MySQL DB (You can substitute this for Python / Ruby / Perl and different storage if you prefer)
You’ll also need the following components to complete the build, most of these are available at electronics shops although some of them like the ESP8266-01 are probably easier to source on eBay / Amazon.
- ESP8266-01 Serial WiFi Module – ESP8266 Datasheet – Buy ESP8266
- DHT22 Digital Humidity & Temperature Sensor - DHT22 Datasheet – Buy DHT22
- LD1117AV33 3.3v Voltage Regulator – LD1117AV33 Datasheet
- 2x 10µF Electrolytic Capacitors
- Header pin strip with 4 pins
- Micro USB breakout module
- 24AWG “Prototyping” Wire
- Small(ish) peice of Veroboard / Stripboard
Working with electronics can be dangerous, please take caution when working on projects described on this website, I cannot be held responsible for any injury to any individual or damage to any equipment as a result of trying these projects. If at any point you are unsure please seek the advice of a professional who is suitably qualified.
Apologies for the lack of bridges on the schematic. Please note not all traces that overlap are actually joins, only those marked with a dot should be considered as connections.
First off clean up the veroboard (stripboard) by lightly rubbing the copper striped side with the washing up sponge, use the abbrasive part which is usually green and more coarse in appearance. Do not rub so hard to scratch or remove the copper tracks, just enough to remove any oxide or dirt that may have build up whilst it has been in storage. Check all your parts are present and free from any obvious signs of damage, and if the pins on components are not shiny and ready to solder give those a small rub with the sponge also to ensure good contact / prevent dry joints when soldering.
Next you should prepare any individual components that require assembly, in my case the Micro USB breakout module came without the pins attached to the board. So I started off by soldering the pins to the USB breakout board, technically only the VCC and Ground pins are required, however I would recommend soldering all the pins even though we are not using them to provide some rigidity to the connection. After soldering I checked the connection by plugging the USB board into a mobile phone charger and checking 5v DC can be obtained accross the VCC and Ground pins with a multimeter.
Once any components which require assembly are completed decide where you want all the components to go on the veroboard, you can probably get it looking a bit cleaner with less links compared to my efforts below, mine looks messy as I wanted to keep the DHT22 on the same side as the USB Micro port so it’s easier to get it in my desired case. For this task I used VeeCAD Free Edition to produce the layout.
Bear in mind the layout diagram does not indicate the direction components face, so this needs be checked against the datasheet prior to soldering components to the board. Start by cutting the veroboard to the required size using the hacksaw and then begin soldering components. Begin with the shortest components first and any components which may be difficult to solder due to the over hang of other components. Also ensure the gaps are cut at this stage, it is alot easier to perform this now before the board gets cluttered, but make sure you use a check twice cut once technique else you’ll end up wasting alot of board.
Here is a photo of my board after attaching the power supply side of things, once you get to this stage its probably a good idea to check the relevant tracks provide 5v, 3.3v and ground respectively by plugging the device into a USB Phone Charger and checking the tracks with a multimeter. You may notice my board looks slightly different to the original plan, I decided to condense the size of the board down a little and to reduce the number of links by stretching component legs further than VeeCAD allows for some components. A good example is the attachment of C1 in this photograph. Remember when placing the capacitors to ensure the polarity is correct, the side indicated with the light stripe and the shorter leg is the negative. Also notice the direction the voltage regulator is facing.
Eventually all links and components are added and the board is ready for programming, you can now perform a power on test. If all has gone well when applying power the ESP8266 power indicator should illuminate.
I used a jumper cable to connect the 4 pin header to the USB TTL UART converter. Remember to set the jumper or switch on your USB adapter to 3.3v mode to avoid causing damage to your ESP8266. Remember the most northerly pin on the header from the perspective of the photograph below is RX and TX followed by a blank pin and then Ground. Hook up the ground cable to the ground, the TX to the RX and the RX to the TX of the USB adapter as photographed below. Once all the cables are connected use another jumper cable to short out the GPIO0 pin of the ESP8266 to the Ground pin, these can easily be accessed from the top of the ESP8266, once these pins are shorted apply power to the board via the USB Micro port. This puts the board in to flash mode and the firmware can be loaded. Do not make the connection between GPIO0 and Ground permanent else your ESP8266 will boot to flash mode with every power on, this connection is only temporary.
Next if you are using Windows download the ESP8266 firmware flashing tool from https://github.com/nodemcu/nodemcu-flasher. If you are a Mac or Linux user you can use the command line Python equivalent available at https://github.com/themadinventor/esptool or installed from PyPi, e.g. pip install esptool
Next download the following firmware image, this gives you the NodeMCU firmware with some additional extras compiled including native SSL, DNS & DHT support – nodemcu-esp8266.bin
Open the flasher and on the config tab click the settings button and select the bin file you just downloaded, ensure the position is 0x00000 and then head back to the operation tab and hit flash. The indicator on your ESP8266 and USB TTL UART adapter should violently flash whilst the firmware is uploaded, if this doesn’t happen investigate as neccesary. The software should auto select the correct COM port although if it gets it wrong select the correct port from the drop down menu.
After the firmware has finished uploading and the flasher tool displays a tick logo in the bottom left corner proceed to remove power from the board, and reapply power. This should reboot the ESP8266 into the firmware rather than flash mode. When doing this ensure the jumper from GPIO0 to Ground has been removed. Next continue to download Esplorer - https://github.com/4refr0nt/ESPlorer), a relatively nice Java app for dealing with LUA scripts and various other functions of the ESP8266 with a friendly UI.
Once you have ESPlorer open you’ll notice it’s split into two panes, the left hand pane is for commands and lua scripting, the right hand pane gives output and control for the ESP8266. In the right hand pane select your COM port if using windows or /dev device if using Linux / OSX from the drop down and click open at the top of the window, if all is good you should see ESPlorer connect to the ESP8266 and provide a serial console.
Now you can test the ESP8266 is working as expected by issuing a few commands directly into the console, first put the device into client mode and then try connecting to your Wifi network and see if you get an IP from your DHCP server, something like the below should do the trick...:
wifi.setmode(wifi.STATION) wifi.sta.config("<WIFI NAME>", "<WIFI PASSWORD>") wifi.sta.connect() print(wifi.sta.status()) print(wifi.sta.getip())
Providing everything has been setup, flashed and connected as required your console should echo back a status value or 5 and an IP address, subnet and the default route for your network.
Next lets upload the code that checks in the temperature and humidity to your webserver. I have configured mine to perform this operation every 15 seconds which is uber extreme although you can edit as you feel appropriate. Do not make this too often though, if the ESP8266 is busy all the time it’s likely you’ll never be able to write to it via ESPlorer again as it’s constantly blocking, and you may need to reflash it prior to being able to upload new scripts. Providing you used the firmware provided on this page you should have full SSL and DNS support out of the box, however if you have not used the firmware from this page you may only be able to submit the data unecrypted or without DNS lookups.
Copy the code into the left hand pane of ESPlorer and edit as required...:
function do_update() print(wifi.sta.status()) print(wifi.sta.getip()) print("Checking DHT22 Sensor") pin=4 status, temp, humi, temp_dec, humi_dec = dht.read(pin) print("temp: "..temp) print("humi: "..humi) print("Submitting result") http.get("https://<your webserver>/<your script.php>?sensor_id=<esp8266 device id>&temp="..temp.."&humi="..humi, nil, function(code, data) if (code < 0) then print("HTTP request failed") print("Sleeping until retry") else print("HTTP request successful") print("Status Code:"..code) print("Sleeping until retry") end end) end print("Configuring WiFi Connection") wifi.setmode(wifi.STATION) wifi.sta.config("<Wifi Name>","<Wifi Password>") wifi.sta.connect() tmr.alarm(0, 300000, 1, do_update)
This script configures the wifi upon boot up of the ESP8266 with the Wifi network and password you define and then starts a timer to run the do_update function once every 300 seconds, you can make this shorter or longer if you like but 300 seconds is probably a reasonable resolution. When the function runs it prints some debug information, fetches the readings from the DHT22 and then submits the results to a URL you define. If the HTTP request is succesful or not it exits cleanly and then waits until the timer executes the function again. Once you are happy with your script click the save button and save the script as “init.lua”, anything in init.lua will be ran immediately on boot of the ESP8266. Once saved click the “Send to ESP” button in the bottom left of the editor. This will upload the script to the ESP8266. Once the upload completes it will begin to execute.
Configure the Web Server
You should now check that your webserver is receiving requests from your ESP8266 at the interval you specified. Login to your webserver and cat the access.log file or if you are using something like cPanel or Plesk login to your control panel and checkout your website stats in your preferred plugin.
Here is an abstract from my Apache log file showing the URL specified in the lua script being hit at the interval specified...:
188.8.131.52 - - [23/Jul/2016:17:04:36 +0100] "GET /submit_metrics.php?sensor_id=555555&temp=27.7&humi=51.8 HTTP/1.1" 200 2878 "-" "ESP8266" 184.108.40.206 - - [23/Jul/2016:17:09:38 +0100] "GET /submit_metrics.php?sensor_id=555555&temp=27.7&humi=51.8 HTTP/1.1" 200 2878 "-" "ESP8266" 220.127.116.11 - - [23/Jul/2016:17:14:34 +0100] "GET /submit_metrics.php?sensor_id=555555&temp=27.5&humi=51.6 HTTP/1.1" 200 2878 "-" "ESP8266"
Notice the user agent is set as “ESP8266” and that I decided to send my ESP8266’s device ID as well as the temperature and humidity to my webserver so I can see which sensor has been reporting statistics, with this method you can have multiple sensors reporting in to the same script / db. In my log you can see I have already created my PHP script as the server is responding with a 200 response, in your case the file you specified probably doesn’t exist yet so you’ll probably be sending back 404 responses.
Next it’s time to create your MySQL DB. Login via your favourite MySQL DB editor, in my case I like to use the CLI client but you are free to use PHPMyAdmin, MySQL Workbench or any other tool. Create a new database to store your data and create the tables using the following statement. It’s also probably good practice to configure a user specifically for this application and configure their permissions to only have read and write access to this DB.:
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!40101 SET NAMES utf8 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `sensor_results`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `sensor_results` ( `result_id` int(11) NOT NULL AUTO_INCREMENT, `sensor_id` varchar(30) DEFAULT NULL, `datetime` datetime DEFAULT NULL, `temp` float DEFAULT NULL, `humi` float DEFAULT NULL, PRIMARY KEY (`result_id`), KEY `fk_sensor_id_idx` (`sensor_id`), CONSTRAINT `fk_sensor_id` FOREIGN KEY (`sensor_id`) REFERENCES `sensors` (`sensor_id`) ON DELETE NO ACTION ON UPDATE NO ACTION ) ENGINE=InnoDB DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `sensors`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `sensors` ( `sensor_id` varchar(30) NOT NULL, `sensor_name` varchar(45) DEFAULT NULL, `sensor_description` text, PRIMARY KEY (`sensor_id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
Now would be a good time to add your ESP8266 device ID to the sensors table, if you do not add this the foreign key constraint will prevent you from writing your results back to the DB.:
INSERT INTO `iot`.`sensors` (`sensor_id`, `sensor_name`) VALUES ('<ESP8266 Device ID>', '<Your Sensor Name e.g. Living Room Sensor>');
Next either create your DB writing script on your webserver or upload it via SFTP / FTP, ensure it is positioned in the same path as previously written in your LUA script. You can write your script in any language supported by your webserver to write back sensor values to your DB, although in my case I decided to use PHP as I was feeling lazy… Feel free to use my script below.:
<?php $sensor_id = $_GET['sensor_id']; $temp = $_GET['temp']; $humi = $_GET['humi']; $sensor_id = mysqli_real_escape_string($db, $sensor_id); $humidity = mysqli_real_escape_string($db, $humidity); $temperature = mysqli_real_escape_string($db, $temperature); $dbconn = mysqli_connect('<DB HOST>','<DB USER>','<DB PASSWORD>','<DB NAME>'); $SQL = "INSERT INTO `iot`.`sensor_results` (`sensor_id`, `datetime`, `temp`, `humi`) VALUES ('$sensor_id', Now(), '$temp', '$humi');"; mysqli_query($dbconn, $SQL); mysqli_close($dbconn); ?>
It is a very dumb script that does no validation or error detection, however data types and a valid sensor_id are enforced by the constraints on the DB tables so no bad data as such can be commited to the DB. Feel free to beef up the script as you feel neccesary.
Next ensure your IOT Temperature and Humidity sensor is powered up via it’s USB Micro port and see if temperatures and humidity values are being written back to your DB. Everything should be working now, if values are not being written go back over the guide and troubleshoot and issues, remember checking out your webservers access.log and error.log files as well as following the printed output on the ESP8266’s serial connection can be a great help.:
mysql> select result_id, datetime, temp, humi from sensor_results ORDER BY result_id desc LIMIT 5; +-----------+---------------------+------+------+ | result_id | datetime | temp | humi | +-----------+---------------------+------+------+ | 146931 | 2016-07-23 17:27:36 | 28 | 51.4 | | 146930 | 2016-07-23 17:32:06 | 28 | 51.1 | | 146929 | 2016-07-23 17:37:51 | 28 | 51 | | 146928 | 2016-07-23 17:42:36 | 28 | 51.1 | | 146927 | 2016-07-23 17:47:06 | 28 | 51 | +-----------+---------------------+------+------+ 5 rows in set (0.00 sec)
After everything is confirmed working as expected you can disconnect your programming cables from the debug header. I chose to trim down my veroboard a little so I could fit the project into a small prjects case, however if you choose to do this be careful you do not cut through or remove any tracks which are used. Here is what the board footprint looks like following the cleanup. If you choose to mount the project in a projects box remember to cut a few holes for the DHT22 and USB Micro Port to poke through the case else you will not get reasonable humidity / temp readings at the atmosphere the device is in is limited.
Now you can get creative and make a custom dashboard for displaying your sensor’s stats rather than viewing it directly from the MySQL DB on the CLI / PHPMyAdmin. You can write this in any language you please / is support by your webserver. Simply select the results you wish from the DB and display them however you see fit, maybe try using gauges from the Google Charts API or some other cool JS libraries to animate changes in temperature / humidity.
Hopefully now you have a pretty good grasp on getting something basic up and running using the ESP8266-01 including flashing with the NodeMCU firmware and uploading LUA scripts. How about trying to mod this design to do something different, maybe try replacing the DHT22 with a reed switch on a door frame to alert you when somebody enters your house, or use a light dependent resistor to measure the luminosity of your room. If you’d like to reuse your ESP8266-1 you can put it into flash mode by bridging the GPIOO pin and the ground during power up and reflashing it using the flash tool, now it’ll be ready to accept a new LUA script via ESPlorer.