Adafruit Huzzah ESP8266
The ESP8266 processor from Espressif is an 80MHz microcontroller with a full Wi-Fi front-end (both as a client and an access point) and TCP/IP stack with DNS support. While this chip has been very popular with hobbyists, it has been difficult to use in practice. The Adafruit HUZZAH ESP8266 breakout board has been designed to make working with this chip a lot easier by adding:
- Reset button
- User button that can also put the chip into bootloading mode
- Level shifting on the UART and reset pin
- 3.3V out, 500mA regulator
- Two diode-protected power inputs (one for a USB cable, another for a battery)
Two parallel, breadboard-friendly breakouts on either side provide access to:
- 1 × Analogue input (1.8V max)
- 9 × GPIO (3.3V logic), which can also be used for I2C or SPI
- 2 × UART pins
- 2 × 3-12V power inputs, reset, enable, LDO-disable, 3.3V output
This project aims to explore the capabilities of this device in our smart home and assess its potential to be part of the IoT. What we particularly like about this device is that we can re-use our existing experience and software (the same IDE) as we have used with Arduino boards.
The construction process is well defined here. You don't need to solder all these pins on (depending upon your project), but for our evaluation it makes sense to do this so we can try out different things using a breadboard.
USB - Serial Connector
The next step is to connected the USB lead as defined here. We are using the 'Console Cable':
Our device showed up on COM5 port and using Putty we could see the welcome message, when we did a reset.
This process is well defined on the Adafruit website.
NOTE: NodeMCU's pinouts are not the same as the Arduino/gcc pinouts. The Arduino pinouts are printed on the board. Also note: Rev A of this board has GPIO #4 and #5 swapped, so if #4/#5 aren't working for you, try swapping them over. These were correctly labelled on our board.
We have Arduino IDE V1.6.5 installed.
ESP8266 Board Package
Following the instructions we successfully installed the board package within the Arduino IDE and managed to get the 'LED Blink Test' demo uploaded and working. To get to this point had taken less than an hour :-)
We then quickly moved on to the Wi-Fi example and using our library of Arduino code, had it connected and sending sensor data in less than another hour. That was enough to make us order a few more :-)
The ESP8266 requires 3.3V power voltage and peaks at around 500mA. Assume the ESP8266 can draw up to 250mA. To make it easier to power, there is a high current 3.3V voltage regulator on the board. It can take 3.4 to 16V input but 4 to 6V is much preferred, since the ESP8288 has high current usage when Wi-Fi is on.
There are two inputs for the regulator, V+ and VBat. Both have Schottky diodes in-line, so you can connect both at different voltages and the regulator will simply power from the higher voltage. The V+ pin is also on the FTDI/serial header at the bottom edge. Adafruit recommend connecting a LiPoly or AA battery pack directly to VBat and keep the V+ unused for when an FTDI cable is attached. There is also a 3.3V output from the regulator available on the 3V pin.
Typically, we power our slave processors with a protected 12V dc power supply. We use tiny dc-dc convertors near the processor to accommodate any voltage drops and they provide a stable 5.0V dc from a wide range of input voltages.
RX and TX are the serial control and bootloading pins and used to communicate with the ESP module. The TX pin is the output from the module and is 3.3V logic. The RX pin is the input into the module and is 5V compliant (there is a level shifter on this pin). The pins are available in two places, one set is on the right side breakout and the same pins are also at the bottom on the "FTDI/Serial" breakout.
The pinouts are described on the Adafruit website.
This breakout board has 9 GPIO: #0, #2, #4, #5, #12, #13, #14, #15, #16 all GPIO are 3.3V logic level in and out, and are not 5V compatible. The maximum current drawn per pin is 12mA. The pins are general purpose and can be used for any sort of input or output. Most also have the ability to turn on an internal pull-up resistor. Some have special functionality:
- GPIO #0 does not have an internal pull-up, and is connected to a mini tactile switch and red LED. This pin is used by the ESP8266 to determine when to boot into the boot loader. If the pin is held low during power-up it will start bootloading! It is best used as an output, to blink the red LED. We typically use this as an output and blink it to indicate lack of Wi-Fi connection or any other errors.
- GPIO #2 is used to detect boot-mode. It also is connected to the blue LED near the Wi-Fi antenna. It has a pull-up resistor connected to it and you can use it as output, to blink the blue LED. We typically use this as an output and blink it to indicate within our main code loop as a visual heartbeat.
- GPIO #15 is used to detect boot-mode. It has a pull-down resistor connected to it, so make sure this pin isn't pulled high on startup. It is safer to use it as an output.
- GPIO #16 can be used to wake up out of deep-sleep mode by connecting it to the RESET pin.
Typically we enable the internal pull-up resistors and pull the input pins to ground with our sensors. To be really safe, we do this via a 1KΩ resistor (In case they are misconfigured as outputs). This works well with door contact sensors and PIR sensors which are usually closed. It is very easy for us to reverse the logic in our software if required.
We have implemented code to enable input debounce in software. The same code also effectively rate limits the speed at which the ESP8266 will send updates to our Home Control System (HCS). Typically this is used to ensure (as examples) that a PIR sensor doesn't report pulses more than once every second or a door contact sensor doesn't report changes more than once every three seconds.
The quoted specification on the Adafruit website says the analogue input is 1.8V maximum but, in their more detailed pinouts description this is quoted as ~1.0V maximum. The linked specification (PDF) provides no information on this topic. Our reading and research points to the limit being about 0.95 Vdc.
The analogue sensors of most interest to us are these humidity sensors. These use our local 5V dc supply but we have to ensure that the limit on the analogue input pin is not exceeded. We do this with a voltage divider. This one component is more expensive than all the other bits of this project added together but a smart home is only as good as the data collected within it.
We are using the AnalogRead function to read the single analogue input on the ESP8266. This provides an integer value between 1 and 1024. In order to accurately convert this into a voltage we need to know what input voltage results in the maximum value of 1024. We tested this with a variable voltage power supply and the result was 0.968 V.
Our HIH-4000-004 humidity sensor datasheet (PDF) says it needs a "minimum resistance of 80 KΩ". This is a confusing statement and actually means that the load on the output must have a resistance higher than 80 KΩ and not draw too much current from the output pin. In other words it is expecting to see a high impedance from the Arduino analogue input pin.
With this in mind we created our voltage divider using two fixed value resistors. The actual value of the resistors is not too important but the ratio needs to be about 1:4 (to divide the voltage seen by 5) and the sum of the resistor values needs to be about 100KΩ. We chose resistor values of 20KΩ (measured at 20.0KΩ) and 75KΩ (measured at 75.2KΩ).
This means that an input voltage of 5.0 V into this voltage divider will result in an output voltage of 5.0 × (20.0 / (20.0 + 75.2)) = 1.05 V. This means we need to multiply measured voltage by 4.76 (95.2 / 20.0) to get actual voltage from the humidity sensor.
Knowing this value should enable a fairly accurate voltage reading on the analogue input but, in reality the internal impedance of the analogue input might also affect the voltage divider. The only way to know exactly how much difference it makes is to calibrate the input with the voltage divider in place. We do this by applying a known voltage to the voltage divider (e.g. 4.59 V) and measuring the voltage at the analogue input (measured as 0.964 V). The actual voltage divider ratio can then be calculated (4.59 / 0.964 = 4.761). This proves that the affect of the analogue input impedance is negligible.
There is a small amount of noise on the analogue input readings which results in minor fluctuations in the humidity values read. Ordinarily these wouldn't be an issue but our code explicitly reports only significant changes in humidity, to minimise the amount of traffic received from each sensor over the course of a day. Random variations due to noise result in more changes being detected and hence more values being sent. To overcome this issue, we use a smoothing algorithm in our software which stores an array of previous values. Because we read the sensor value about once a second, this introduces minimal delay in detecting real-world changes.
We rate limit updates from humidity sensors in our smart home (via software) to a minimum time period of 30s between humidity updates. We also enforce an update being sent at least every 15 minutes, regardless of values seen by the sensor.
We have tested the DS1820 1-Wire temperature sensors successfully with this device.
Initially we had issues with this error:
Multiple libraries were found for "OneWire.h"
Not used: C:\Users\Rob\AppData\Roaming\Arduino15\packages\esp8266\hardware\esp8266\2.0.0\libraries\OneWire
The only way to fix this appears to be to rename the standard OneWire library folder and restart the IDE.
Once we had resolved this issue, we used our existing code to report temperatures back over Wi-Fi. We tried to use pin #16 for the DS1820 but it was not happy and we couldn't get it to work on this pin. We then tried pin #14 though and it worked fine.
Wi-Fi range is very good considering the tiny aerial on the board. We are testing the device against a secondary access point initially, so that we can check its Wi-Fi failure modes and write code to handle things like the wireless access point being unreachable.
We will be testing I2C support next.
We will be documenting our smart home applications that use this device very soon.
This was our first test application and we have left it in-situ, so that we can experiement and try thinsg out. The device has a 1-Wire temperature sensor, humidity sensor connected. It also has 4 digital inputs with one used for a smoke sensor and the other 3 used for testing new sensors.
This was our second test application. We are using the ESP8266 device in our garage to test out the Wi-Fi range nd reliability. It has a 1-Wire temperature sensor, humidity sensor connected. It also has 4 digital inputs with one used for a smoke sensor and two used with PIR sensors.
As we have described it here, it provides a cheap and easy way to easily connect 4 digital inputs, a 1-Wire DS1820 temperature sensors and a humidity sensor to our smart home.
The ESP8266 is not multi-thread capable and is therefore best used either for control or sensing but not both, unless you don't need fast response or real-time data.