The little device shown above will cost you (at retail prices) US$1.xx. It’s a complete computer with a 32-bit CPU, RAM memory, flash storage for programs and data, and as you can see, it’s smaller than my return key. It also includes hardware and software for WiFi and Bluetooth 4.x (low energy). Amazing, no? But wait — there’s more! This little computer can put itself into “deep sleep mode” where it uses almost no power at all! Why is deep sleep cool? Well, it means you can power this thing doing useful work for over a year with just the pair of AA batteries shown above. In this article I will guide you through making a little Internet of Things (IoT) device with this hardware, to send temperature and barometric pressure data to a (free) global cloud service. Total materials costs for this device can be less than you would pay for a single fancy Starbucks coffee.
Let’s Make This Thing!
Follow the step-by-step here and you will build and connect this little battery-powered “thing” (for free) to one of the world’s largest commercial Internet of Things cloud services — IBM Cloud’s “Watson IoT Platform” service. When you finish it, you can seal it up and toss it into your back yard for a year or more before it will need new batteries. All the while you will be able to monitor its output from anywhere on the planet, for free. To give it a practical use, for about $2 more I’ll show you how to attach an even smaller module that will let your “thing” monitor temperature and barometric pressure.
Here’s what mine looks like on IBM’s cloud service:
That’s My Tiny ESP Thing Talking To The Big Blue IBM Cloud! Ahhh, they grow up so fast.
Let’s walk through step-by-step how you can this little bundle of joy yourself. The steps are:
1. buy the (inexpensive) hardware
2. setup your free (limited) account on IBM’s cloud
3. start up your own personal Internet of Things backend service (for free) on the iBM cloud
4. wire up your ESP8266 “thing”
5. set up an appropriate software development environment (you will install install free software for this)
6. clone my example code from GitHub (a free download)
7. modify my code (for your WiFi access, and your IBM Cloud access)
8. build, install and run the code on your ESP, observing the output in the monitor
Then after all of that, I’ll get into some more hardcore technical stuff:
A. reducing the power consumption from the NodeMCU
B. using the bare ESP8266 module (no support chips) for best power conservation,
C. computing battery life estimates for these devices
Then at the very end, I’ll talk a little about the newer cousin of the ESP8266, the ESP32. I’ll compare and contrast them for you. Each has different strengths.
1. Order Your Hardware
Below is the parts List with links, mostly for Amazon, which I find convenient. Many of these things can be purchased elsewhere (like ebay.com, or sites nearer their manufacturers in China). Please read the “Note About The Parts Choices” at the bottom of the parts list before you buy anything. You need to choose one of 2 options and they each have plusses and minuses. Depending on which you choose, you will buy different stuff from this list:
Optional suggested hardware for no soldering (US$8): NodeMCU prototyping board containing ESP8266 (contains a CP2102 USB-to-UART chip, a 3.3V regulator, and is “breadboard-friendly”)
You will also need a micro-USB cable, if you use the NodeMCU above (not required if you are going “old school” with the bare module below.)
Old School hardware (US$1.76): Bare module ESP8266MOD 12-E
Optionally, you can make your ESP8266 breadboard friendly by soldering it to an adapter plate like this one. It’s a bit pricey (at about US$5 — so the powerful ESP chip is a small fraction of the price of this thing) but it might make the wiring easier for some people.
Required battery pack for power in the field (5 packs for $10): A battery holder for two US “AA” alkaline batteries (also called UM3, or U12).. And of course you need a couple of alkaline batteries to put in it. Note that you will want alkaline AA batteries because they have about 2500-3000 mA hours of power each (about 2-3 times as much as standard AA batteries and NiCad batteries). Also, please don’t substitute a 3.7V Lithium battery pack, because the ESP chip is only rated for a maximum of 3.6V and Lithium batteries can exceed 4V on a full charge.
You only need a USB-UART convertor if you are going “old-school” and using the bare ESP module by itself, and you only need it for the programming phase.) Any 3.3V USB-to-UART convertor will work here, but careful of the wiring because different ones have the pins in different orders. Also, if you get the one linked here (which works for both 3.3V devices and 5.0V devices) be sure to set the toggle switch to 3.3V or you may fry your little ESP with 5V! Note also that this is a great tool to have in your toolbox for other projects with Arduino or other small serial devices.
Here is an Amazon link for the (optional) BMP180 temperature and pressure sensor I use in this article. You can buy them from China for about US$1 (e.g., try banggood.com, or aliexpress.com).
You will need wire too, and if you don’t have basic electronics supplies I recommend something like a breadboard and wires kit like this one (US$11): This kit has a few breadboards, and lots of wires too. . Breadboards are very helpful in working out the wiring for a project. Soldered connections are much harder to change when something doesn’t work, so I always prototype on breadboard first.
So that’s it for your parts list. You have some choices to make before buying.
Note About The Parts Choices
My goal here is to show you how to use the bare ESP8266 module, the one at the bottom of the photo above. I want you toachieve the ultra-low-power feature, so you can power your “thing” with just batteries for long periods in the field. However, I know soldering is hard for some, so I will also show you how to use the NodeMCU board for this project (the one at the top in the photo above). I personally always use the NodeMCU myself for experimentation (both wiring and software development) then I copy the code over to the bare ESP module (and make some small required changes) for deployment. So ideally, I’d suggest you buy both, but use the NodeMCU just for development.
If you choose to only buy the NodeMCU board (e.g., to avoid soldering), then:
– the “things” you deploy will cost you a bit more, and
– it will be easier for you to wire them up on a breadboard (no soldering at all), but
– it will be hard to get it to use low power in the field (the support chips suck power so you will need to disable them them or they will eat your batteries fast — and that’s not easy).
That last point is only a concern if you plan to deploy it with two AA batteries for power. If you plan to have it powered from an A/C adapter instead then you don’t need to worry so much about the extra power consumption. Also, since the VIN connector can receive higher voltages (see below), you could power it with more batteries in series so it will last longer even though it uses more power. You might also be able to power it from some other power sources, like the 12VDC power system in your car. I’ll discuss the NodeMCU input voltage tolerances later in this article, and I’ll work through the math on power consumption later in the article too.
Impressive Espressif Devices
Before we get started I just have to say a few words about these impressive little devices from Espressif (the Chinese manufacturer behind these ESP8266 boards). I bought a bunch of these things when I first heard about them a few years ago (Western makers like me started discovering them in late 2014). I was very impressed that a $1 computer had WiFi and Bluetooth — wow! Previously I had been paying $80, then later $50 for WiFi “Shields” for Arduino devices (and frankly, none of them were very reliable). So I embraced devices like the ESP8266MOD 12-E bare boards manufactured by AI Thinker, which I am using in this article. They are very small, as you can see, and quite powerful too (with a 32 bit Tensilica CPU, and 1M of non-volatile flash memory on board for your programs and data). They also have a bunch of GPIO pins like the Arduinos and Raspberry Pis, and exactly one analog-to-digital (ADC) input. Perhaps more impressive is their radio capabilities (full WiFi, and Bluetooth 4.x). A full 32-bit microcontroller, with ADC and WiFi tht costs almost nothing! Many people buy the ESP8266 boards only as WiFi add-ons for other microcontrollers.
For me though, the really amazing thing about the ESP boards is that they can be powered by small batteries for long periods. They can achieve this because they have a built-in deep sleep mode that only consumes a handful of microamperes (i.e., millionths of an ampere). Specifically, in deep sleep mode this device consumes only 6.5 micro-amperes (i.e., 6.5uA, or 0.0000065 of an amp, at 3.3V, or 0.00002145W). What does that mean? It means:
– my ammeter has a uA scale but is not sensitive enough and registers 0.0uA when the ESP sleeps
– a single AA battery of ~3 amp hours could power it in deep sleep for 15+ years
– you can’t do anything in deep sleep except have the built in clock monitor the passage of time and create a signal to wake up the chip when a specified amount of time elapses
You will use ESP8266 deep sleep like this:
– power up, do something useful, then go into deep sleep (specifying the sleep duration in microseconds)
– CPU, memory, etc are powered down during sleep, but the onboard real time clock (RTC) continues to run
– when the specified sleep time elapses, the RTC module brings HIGH one of the GPIO pins on the ESP8266
– by wiring that GPIO pin to the ESP8266’s chip-reset pin, the board will reset and power up automatically
– on power up the ESP8266 will find itself back at the start of your program, so the cycle repeats
Why I Use The NodeMCU Board For Development
The ESP8266 bare board is a bit tricky to work with on its own. It requires an external USB-UART board for programming, and it requires a 3.3V power supply. To solve both of those issues I would typically use an FTDI or CP2102 USB-to-UART cable for 3.3V. In the field you will also need a 3.3V supply. You will also need better-than-average soldering skills I think, since the module’s connectors are very small, are “castellated” (no holes for the wires), and they have nonstandard spacing (i.e., it won’t work on a standard breadboard, or standard perfboards).
The easiest way to get started with an ESP8266MOD 12-E is to get a NodeMCU board (or a similar board made by other manufacturers, like Adafruit and Sparkfun). These boards contain a microUSB port, wired to a CP2102 USB-to-UART, and wired to the ESP. They also contain a voltage regulator to convert the 5V USB power to 3.3V for the ESP. And lastly they have standard 2.54 pitch pins and usually come with them pre-soldered so you can simply push the whole thing into a typical prototyping breadboard. So that’s what I suggest you use to start with, and I did my prototyping with one of these. Note that the voltage regulator uses a lot of power, so when you deploy the device you will want to bypass it and wire the AA battery pack directly to the 3.3V rail. To get power consumption down into the microampere range, you will also need to disconnect the USB-UART chip, and that’s not easy. So for battery-powered uses, I use the bare board in the field. But I prefer to work out all the wiring and the software details on the NodeMCU board first.
As you can see, it’s pretty easy to wire up the NodeMCU (that’s the running prototype above). You can compare this to the larger breadboard I have wired up for the bare module at the bottom of this article and it should be clear why this is a good place to start.
2. IBM’s Cloud
While you are waiting for your hardware to arrive, you can set up a free account on IBM’s Cloud. To begin, go to:
Tap the Create a Free Account button, then fill in your details on the next page and tap Create Account. Once you have done that, it will direct you to check your email for a link that you can use to continue. That email will come from “IBM Cloud” and you need to tap on the link labelled Confirm Account in that mail message. After you have done that you can return to the console link to sign in and get started:
(i.e., the same link as above, but this time tap the “Log in” button). You may have to accept the GDPR privacy statement and acknowledge that you are an adult in order to proceed. Ultimately you should arrive at the IBM Cloud dashboard page.
3. Start Up Your Personal IoT Backend Service
Starting with your account logged-in at the IBM Cloud dashboard page, with this URL:
tap the “Create Resource” button.
A large complicated page will show up full of resources you could create, but over on the left side there is a list of resource categories. Tap on the Internet of Things category and the complexity on the right will shrink down to to just one choice. Tap that “Internet of Things Platform” to create your IoT backend service. A page similar to the following should come up (but with your email address in the organization field):
Leave all of the editable fields as they are, and just tap the “Create” button at the bottom right. After a moment (presumably while cloud resources are being set up for you) you will be presented with a “Launch” page. Tap the “Launch” button and start your backend cloud service running! Wow! That was easy! And free!
When it is done, you will be sent to your personal IBM Cloud “Watson IoT Platform” backend “dashboard” page. Your dashboard has a URL of this form:
The one above is my personal dashboard URL. The first part of the domain name, “nzjnxq” is the catchy name IBM generated for my organization in the Watson IoT Platform. Your URL will be the same except that your organization will be different. Please note the URL of your dashboard. You will use it to connect to your backend and configure things, or watch your data flow (like I showed in the image farther above). My dashboard looks like this:
Before you can send data to your backend, you need to establish some credentials for your “things”. So let’s do that now.
– click DEVICES in the menu on the left (computer chip icon?)
– click the Device Types tab
– click Add Device Type
– I think you can choose either Device or Gateway here, but I used Gateway and the rest of the instructions in this article assume you did the same, so please click Gateway
– give your new type a cool name — having a spectacular lack of imagination when I did this, I used “BBG_TYPE” as my type name
– click Next, then Next, and then Done
– click the Browse tab
– click Add Device
– in the pop-up menu, select the type you just created
– give your new device instance of your new type a cool name — I used “BackyardBarometrics001”
– click Next, then Next
– now you need to create an “authentication token” for this specific device. This is the password you will use when communicating with the Watson IoT Platform from your device. PLEASE NOTE: record the token now, because it is not possible to retrieve it from Watson IoT Platform later. This is you one chance to record it!
– after you have entered it, and recorded it, click Next, and then Done
At this point you need to have saved the following information:
– your Watson IoT Platform “organization” name (mine is “nzjnxq”, and yours will be similar scrambled letters and/or numbers)
– your device Class (i.e., Device or Gateway, and mine is a “Gateway”)
– your device Type (mine is “BBG_Type”)
– your device ID (mine is “BackyardBarometrics001”)
– your secret token
With that, your backend is completely ready. You can go to the Devices tab in the left menu, then select your specific device name from the table, then tap Recent Events to see the display of messages from your device, like I showed near the top of this article. You can set up a read-only access token to share with others too, then they can see your data too, but not modify it or change anything in your backend.
So now let’s build your device and get it sending messages to your backend.
4. Wire It Up!
First, I’ll show you how to wire up the NodeMCU board, then I will go through the “old school” approach with the bare ESP8266 module a bit later in the article. By the way, I like to use Fritzing to illustrate circuits as I have done in this article. It’s free and it’s really great.
Googling gives the pin wiring diagram for the NodeMCU board. This NodeMCU board is going to provide USB-to-UART services so we can connect to the board from our computer to program it over a standard USB cable. It also provides 3.3V power for the ESP8266 (by converting the 5V supplied by our computer over the USB wire). Everythinng else we will have to wire for ourselves. Fortunately there’s not much else we need to hook up.
Begin by pressing the NodeMCU into the breadboard across the split (i.e., so one row of the NodeMCU pins are on one side of the gap in the middle, and the other row of pins is on the other side. Then press the BMP180 into the breadboard somewhere else not connected to any of the NodeMCU pins. Wire them up following the Fritzing diagram below, but do not connect the battery holder at all yet since we will be powering it using the USB cable during development. Don’t forget the Prince Charming wire from D0 to the chip reset pin (the yellow wire in the Fritzing diagram) or your ESP8266 will become a Sleeping Beauty, unable to wake up from her deep sleep!
The Fritzing file used to make the image above is in GitHub for you.
I was actually unable to find a Fritzing part for the NodeMCU, so in Fritzing I wired to an empty space on the breadboard then pasted a photo of my NodeMCU over top. In case it’s not obvious, the micro-USB connector is on the right.
Please do note that the 2xAA battery pack will be wired to the 3.3V rail (the bottom power rail in the above Fritzing diagram) later, not to the VIN pin, which is the 5V power input before the voltage regulator. But that will be later, not now. Note that some articles show that the voltage regulators on the NodeMCU boards are NCP1117ST33T3G which are rated for a max 20V. If this information is correct, you could install one in your car and connect it’s 12VDC supply directly to the VIN pin on the NodeMCU. The car’s 12V system may provide a bit more than 12V but it should always be well below 20V.
Once you have the wiring all set up, it’s time to move on to the software side of things. Please don’t connect your NodeMCU to your computer yet (with the micro USB cabe). Instead, grab your computer keyboard and mouse and let’s get the development environment setup.
5. Install the Arduino IDE
You will need some development software to enable you to install programs on the ESP8266. Perhaps you already have the Arduino Integrated Development Environment (IDE) software installed on your development machine from a previous project on an Arduino. If not, you will need to use the link above to download and install it now. It is possible to run this software on a Linux desktop, or in Windows or MacOS. My long time preference is to use Apple’s MacOS, but in the latest versions of MacOS I always seem to have trouble with the Arduino IDE not being able to communicate properly. I think the drivers for the USB-UART chips are just not as good. If any readers have any tips on this, I would appreciate them. As a result, with regrets, I recommend using Windows if you have access to a relatively recent Windows machine. I personally always have a Windows machine hanging around somewhere. Most of the time I try not to get any Windows on me, but when it comes to Virtual Reality (VR), or first person (3D) games, or programming Arduinos or ESPs, it’s still the best choice. If you can’t use Windows then you might want to try the new Arduino “web editor” a web-based version of the IDE (details at the link above) but I have never used it.
Once you have the Arduino IDE installed, you will need to add board support for ESP8266 boards, and add a library that simplifies accessing the BMP180 sensor. Let’s do those steps now.
To install the ESP8266 board support, you need to use the Arduino IDE “Board Manager” feature. In the IDE go to the File menu, and select Preferences. There you should see a text field labelled Additional Board Manager URLs. Paste the line below into that text field, then tap the okay button:
Then go to the Tools menu and select Boards, and in there, Boards Manager. In the Boards Manager window, type “esp8266” in the search bar. You should find the entry labelled “esp8266 by ESP8266 Community”. Select that entry then tap its Install button. That will supply the required definitions for multiple ESP8266 boards, including the NodeMCU board I am recommending.
Now lets’ install the SparkFun BMP180 library. The small BMP180 sensor board has a complicated way of communicating, and the SparkFun library will take care of that hard coding for us. Begin by downloading the library as a ZIP file, using the link below:
Don’t decompress this library zip file. Just download it into your downloads folder. When you finish downloading, go back to the IDE and go to the Sketch menu and select Include Library, and in there select Add .ZIP Library. Then in the file selection box navigate to your downloads folder and select the “BMP180_Breakout_Arduino_Library-master.zip” file.
Now your development environment should be ready to go for development on this ESP8266 plus BMP180 project.
6. Clone the (Free) DarlingEvil Example Code
If you have a git client program installed on your computer (many modern Linux distributions, and Apple MacOS pre-install a git client for you) then you can open a terminal window and clone the DarlingEvil git repository, e.g.:
git clone https://github.com/MegaMosquito/darlingevil.git
You will find the example ESP8266 Code in the darlingevil/Examples/ESP8266 directory. The source code file is named “ESP8266.ino”.
Since there is only a single file of source code for this project, it may just be easier to navigate to the file in GitHub, and copy the text from there to paste into a file in the Arduino IDE. You will find that one source file here:
7. Modify The Example For Your Credentials
At the top of your new ESP8266.ino file, you should see these exact lines of code:
// Configure these for your WiFi, Watson IoT org, and BMP wiring to the ESP8266
const char* wifi_ssid = "MY_WIFI_SSID_WAS_HERE";
const char* wifi_pass = "MY_WIFI_PASSWORD_WAS_HERE";
const char* mqtt_host = "nzjnxq.messaging.internetofthings.ibmcloud.com";
const uint16_t mqtt_port = 1883;
const char* mqtt_id = "g:nzjnxq:BBG_Type:BackyardBarometrics001";
const char* mqtt_topic = "iot-2/type/BBG_Type/id/BackyardBarometrics001/evt/status/fmt/json";
const char* mqtt_token = "MY_TOKEN_WAS_HERE";
You will need to modify most of these lines to customize the code for your WiFi, and for your credentials in the Watson IoT Platform. So fire up this file in your favorite text editor, or just double-click on it to open it in the Arduino IDE (which is a text editor among other things).
The first two of these lines will need to contain the SSID and pass phrase for your WiFi access point.
Next, change the mqtt_host to the URL for your organization in the Watson IoT Platform. That is, change my organization name “nzjnxq” to whatever your organization name is (you saved it earlier).
Leave the mqtt_port setting unchanged. Port 1883 is the unsecured MQTT port, and we are using unsecured MQTT here.
Create the appropriate mqtt_id for your thing. It must contain 4 tokens separated by 3 full colon (“:”) characters. The first token is the class of your IoT thing. I used the Gateway class, so I used a “g” here. If you followed my instructions then you need to use “g” here as well. If you were more adventurous and used the Device class, then you need to put a “d” here. That should work but I haven’t tried it. The second token is your organization name (mine is “nzjnxq”). The third and fourth tokens are your Type and instance ID (“BBG_Type”, and “BackyardBarometrics001” respectively, for me).
I recommend editing only your Type and instance ID into the mqtt_topic, and leaving the rest of it alone. You have some flexibility to change the last few bits of the topic, but you should get things working first then go back and tinker with that if you wish. If you change things now then it might not work. So you will want to change the bits in uppercase below:
And then finally you will need to store in mqtt_token the token you created for your thing and saved earlier.
Save your changes, then let’s run this thing.
8. Run This Thing!
Now you are going to open the Serial Monitor window, and interact with the ESP8266 directly. Then you will compile your modified ESP8266.ino program into the machine language of the ESP8266 and that program will be uploaded into the flash storage of the ESP8266, and finally it will start running. As it runs you will watch the program’s output scrolling by in the monitor. You will see it collect the temperature and pressure data from the sensor. You will see it attempt to associate with your WIFi access point. Once that succeeds, you will see it attempt to connect to the MQTT broker in your personal IoT backend. When that succeeds, you will watch it send your data to the IBM Cloud (a few times for good measure, in case some get lost on the way). Getting the upload in the middle there to work properly can be problematic if you deviate at all from these instructions, so please try to follow along carefully.
At this point I suggest exiting the Arduino IDE if that program is currently running. It is always best to plug in the development board first, then start up the Arduino IDE. So after you exit the Arduino IDE, please connect your NodeMCU to your computer using a MicroUSB cable. Give it just a few seconds, then start up the Arduino IDE again and open your ESP8266.ino file. Probably the easiest way to do this is to find the file on your desktop and double-click it. One thing to note is that the Arduino IDE is very particular about requiring a file like ESP8266.ino to be inside a folder named ESP8266 (i.e., same name as the file but without the “.ino”). In general there should only be code files that are part of this program in that folder… other files may cause problems for the IDE). If you cloned the git repo, you have this set up already, but if you created the file and pasted in the content, you will need to enclose it in an appropriately named folder before opening it (or the IDE will complain).
In the Arduino IDE, with your program open, go to the Tools menu, open its Boards submenu, and select NodeMCU (either one of the NodeMCU choices will work, I think, but I chose the 0.9 version which worked with my NodeMCU. Now reopen the Tools menu and you should see something like what is shown below:
If your settings are different from those shown above, then use the submenus to fix them. It is especially important that you select a valid Port number. So open the Port submenu and make sure you have selected one from the list shown. The Port selection can be tricky if the appropriate drivers for the USB-UART chip you are using are not correct. There are a few different USB-UART chips, but the NodeMCU uses the CP2102 chip, and I did not need to manually install a driver for that on Windows. Anyway, you will know soon if the Port setting is working correctly.
In the Tools menu, select Serial Monitor, and a new window should open. At the bottom of the window make sure that the baud rate pop-up menu is configured to 115200 baud (this is the serial communications rate configured on the NodMCU board). Once you have done that, press the RST (chip reset) button on the NodeMCU. After you do this you should see some text appear in the serial monitor. It might look something like this:
ets Jan 8 2013,rst cause:1, boot mode:(5,0)
But it should not look like a slew of random characters. If it’s random garbage then the baud rate is probably incorrect fro your board. Try other rates.
Before you do anything else it’s a good idea to make sure your program has no simple typographical errors in it. At the top left of the text editor window in the Arduino IDE, there is a button containing a check mark (“✓”). Tap this button to attempt compilation of your program. Status messages will appear in the black area at the bottom of the window. The final result “Done compiling” should appear in the bar between the editor window and the black status message area when it is done. If compilation was a success, great, move on to the next step. If it fails, try to understand the error messages and go back up to the editor to fix your typographical errors.
Now you are ready to upload your program to the NodeMCU and run it. Press and hold down both of the buttons (RST and Flash) on the NodeMCU, then release the RST button first, followed by the Flash button. Once you have done that you should see the “Waiting for host” message in the serial monitor, e.g.:
ets Jan 8 2013,rst cause:1, boot mode:(5,0)
waiting for host
This means that the NodeMCU board has been placed into flash write mode. Now tap the button at the top right that has a rightward-pointing arrow (“➔”). This will cause the IDE to re-compile your program and then upload it onto the flash of the NodeMCU. At the end you should see a message of “Done uploading” in the bar between the editor text area and the black status message area below it. Your program will likely start running right away, showing its output in the Serial Monitor window. If it doesn’t start right away, press and release the RST button on the NodeMCU.
If successful, you should see something like what appears in this shaky video (maybe someone drinks more coffee than he should). I’m sorry if it feels a bit long. It runs a bit over 1.5 minutes, but I wanted to show a full cycle of it going into deep sleep and waking up again. If you are bored, see if you can hold your breath for the full time it is asleep (60 seconds).
Now, assuming everything is working properly, you will be seeing messages similar to those in the video above. That would imply your data is being sent to the IBM Cloud. So head on back there to your dashboard and verify that it is. My dashboard URL is:
Your dashboard URL will be the same except your organization name will replace mine (mine is “nzjnxq”). From your dashboard select DEVICES in the left slide-out menu, and then select your device ID, and tap “Recent Events”. After a few minutes you should start to see messages coming from your “thing” similar to those shown from mine near the top of this article.
If you are interested you could also explore the cloud side and use some of its free features. You can do many things for free in the IBM cloud, such as:
– set up cloud side triggers for openwhisk actions to send SMS messages or emails on thresholds in events
– write a simple program to pull down your data from the cloud so you can save it somewhere for posterity
Now it’s time for the more technically hardcore part of the article.
A. Reducing NodeMCU Power Consumption
As you are aware now, the NodeMCU development boards connect to your host computer using a USB cable. That USB cable delivers 5 volt power to the board. But the ESP8266 daughter board requires a 3.3 volt power supply, and it may fail permanently if it receives more than 3.6 volts. So the NodeMCU board contains a voltage regulator that “bucks” down the voltage to 3.3V for the ESP. It also brings this 3.3V wire out to an external pin, which I used to power the BMP180 temperature and pressure sensor used in the project. I assumed that I could just directly attach the two-AA-battery pack to the 3.3V rail of the breadboard, and bypass the voltage regulator. The alkaline batteries provide around 3.2V, give-or-take about 0.2V — perfect. So I did that, and it worked, and I thought I was done. So I left the project running for a few weeks on that pair of batteries. Then to my surprise, it stopped working and the batteries were dead.
So I went back an did what I should have done right from the beginning. I measured the amperage being consumed by the device when it was active and when it was asleep. This is what the ammeter showed when it was active:
My old multimeter shows 81.7mA when the ESP8266 is active, and communicating over WiFi. That’s not a lot of power, really. It’s similar to around 10 (give or take) typical LEDs. And it is the approximate expected current draw of the ESP8266. So that’s as expected, fine. Then shortly thereafter it finishes the work cycle and drops into “deep sleep”. At that point, and for the next 60 seconds, I see this on my multimeter:
Wait. What? 10.8mA! That is not okay. The data sheet says it should be 6.5μA. 10.8mA equals 10,800μA, or almost 1,700 times too much power is being consumed! So what is going on here? Maybe my old multimeter (I think I bought this one in 1984) is just very inaccurate? But then there is the whole dead battery situation. So maybe my multimeter is telling the truth?
Well, eventually I realized that even though I eliminated the power loss of the voltage regulator (by connecting the power supply to the 3.3V pin, after the regulator) the other big support chip on the NodeMCU was still being powered! That is, the USB-UART chip (CP2102) was still fully powered (even though it was not being used at all). That chip is the likely consumer of all those milliamperes.
Now, you could fix that by cutting the power pin off the cp2102 so it can’t drain power from the NodeMCU. If you do that you will no longer be able to communicate over USB to the ESP8266. So you might want to solder-in a switch to enable that wire to be easily reconnected (if you ever want to reprogram it or use it with the monitor window). That kind of funky hacking I generally try to avoid because it rarely goes well when I try it. So what I recommend is leaving the NodeMCU alone and moving on to use the bare ESP8266 module, without on-board support chips. I’ll walk you through doing that in the next section.
If you want a primer on how to measure voltage (volts) and current (amperes) in your circuits, I have written a short article on that for you.
B. Naked ESP8266 (Minimize Power Consumption)
Well, that’s the little devil above. I have shown it with a millimeter ruler on the left, and a standard 2.54mm perfboard into which I typically would solder components. The ESP8266 package however, does not play nicely with a standard breadboard (also 2.54mm pitch) or a standard perfboard. The ESP8266 pins have 2mm spacing instead. They are nonstandard as well because they are what is called “castellated” instead of being round holes through the circuit board (those through-holes make soldering easier). Finally, the connectors also wrap around 3 sides of the package, so even if they had the appropriate larger spacing, and standard holes, they could not be easily used in a standard breadboard (due to the internal wiring scheme of the standard breadboards. So there is some slightly fancy soldering in your future if you go ahead with the bare ESP8266 module. But I think you can do it, and I think you should.
So it’s time to sharpen your eyes, and get out your soldering iron. If you are new to soldering, there are many great tutorials on YouTube. I also plan to publish one someday, with some tips and tricks. When I do, I will link it here.
I made 11 connections to the ESP8266 package, using 10 wires (the ground wire is soldered onto two pins of the package). I usually try to use distinct colors for all connections, but I ran out of colors here so I doubled-up on white and brown. Start by soldering wires to the pins like I have below. I used breadboarding wire for this, because I plan to wire the resulting octopus into a breadboard to verify the circuitry and test the software, before I do the final soldering together of everything.
I recommend using some kind of magnification to check your soldering. I use this US$5 little 45X magnification “microscope” most of the time for that. This is what mine looks like:
Above, the black wire is used for ground, red for 3.3V. Note that the black wire is soldered to both ground and also to GPIO #15. Pulling GPIO #15 low tells the ESP8266 that it is to boot from its on board flash, which is what we want to to do. Yellow and orange are TX (transmit) and RX (receive) respectively, and they will be cross-wired to the corresponding pins on the external USB-UART board. Blue and green are the I2C data wires for connecting to the BMP180 sensor. The remaining 2 brown and 2 white wires are sued for control signaling to the ESP8266. The brown wires will be connected together to serve the same function as that odd yellow wire seen with the NodeMCU board at the top of this article, i.e., to enable automated chip reset after deep sleep. A manual switch will also be wired to those brown wires and to ground, to enable manual reset. The white wire on the “EN” connector is for chip enable, and it is simply wired to 3.3V (perhaps I should have just used red there). The other white wire, connected to GPIO #0 will be pulled high normally, but switched to ground to enable flashing the chip.
Here’s a photo of the result connected to a USB-UART board for 3.3V power and to communication with my Windows laptop. I also wired a small switch here so I can switch over to using the two-AA battery pack instead of the power from the USB-UART board.
In the photograph, notice that the there are two small pushbuttons on the left side. The bottom one is connected to the two brown wires, and this is the manual chip reset switch. The topmost of these switches is connected to the white wire that goes to GPIO #0, and this is the button we will use to flash the chip (in the final soldered version I used a toggle switch for flashing instead). This GPIO is pulled high by that huge 10KΩ resistor (it’s physically big because it is rated for 2W — I had a bag of them in my parts bin, so I used one of them… a more typical 1/4 watt resistor would be fine here). There is a superfluous LED (and 220Ω resistor) on the left as well, as a clear visual indicator that the 3.3V power rail at the bottom is active. This LED will not be soldered into the final “thing” we build because it alone consumes about 10mA which would greatly exceed our power budget. Notice also the BMP180 at the top of the breadboard, slightly left of center. Its 4 wires are for 3.3V, ground (GND), and the two I2C pins (SDA and SCL). On the right is the switch to alternate between the two power sources. Like the LED, this switch will not be built into the final soldered “thing”. At the bottom of the breadboard, to the left of the power selector switch, is a small capacitor which is used to minimize the impact of sudden voltage drops, like when the chip switches on after deep sleep. This is not strictly required for the ESP8266, but I added it prophylactically because it costs almost nothing, and I have found that a capacitor is necessary for it’s newer cousin the ESP32, which consumes much more power when waking up. To completely smooth out the power consumption spikes (caused by the WiFi radio, I expect) you will need something like 2000uF, but my parts bin had a bag full of 1000uF and no 2000uF, so I went with that in the final soldering.
Note that I didn’t include any switches in the parts list, but hopefully you can find what you need there, or just manually jumper wires as needed (remember you only need the switches for flashing and reset). I usually buy this sort of thing in bulk from https://banggood.com, my favorite Chinese supplier. If you have trouble finding anything, let me know with a comment and I will provide precise links.
Below is a Fritzing diagram to more clearly illustrate the wiring I used (much clearer than a photo of the breadboard in this case). Please note that when you wire your USB-UART board to the breadboard there are two important considerations:
1. (most important) if your USB-UART board is dual voltage, make sure it is set on 3.3V (5V will fry your little ESP)
2. the pins on your USB-UART may be in a different order than mine. The ESP transmit pin (yellow wire in the photo and in the Fritzing diagram) must be connected to the USB-UART receive pin (e.g., “RX”, “R0” or similar) and the ESP receive pin (orange wire) must be connected to the USB-UART transmit pin (“TX, “T0” or similar). So it’s T-to-R, and R-to-T. After you wire it up and run it, if you can see any text at all from the ESP8266 in the Arduino IDE’s monitor window then your transmit and receive pin wiring is correct.
Here’s the wiring diagram:
The Fritzing file used to make the image above is in GitHub for you.
Perhaps now it’s easy to see why I prefer to work with the NodeMCU board at the beginning of a project. It’s so much simpler to wire up!
The programming (flashing) process for the bare ESP8266 is a little different and you need to make a minor code change from the code you used for the NodeMCU board above.
The code change is here:
// Serial.begin(74880); // For bare module
Serial.begin(115200); // For NodeMCU
Change that code to this:
Serial.begin(74880); // For bare module
// Serial.begin(115200); // For NodeMCU
That is, comment-out the bottom line instead of the top line. I’m not certain why, but the bare module I have communicates at 74880 baud instead of the 115200 baud that the NodeMCU board uses. So I needed to make this change in order to view the ESP8266 output in the monitor window.
The difference in the flashing procedure is that you need to press both buttons, then release the reset button, but continue holding the flash button down until the “Done uploading” message appears on the bar between the code editing window and the black status messages window. After doing this a few times I found it made my fingertip uncomfortable, so you might want to just use a breadboard wire to connect that pin to ground during the process. Just be sure to remember to disconnect it later so that GPIO goes back to high state. After flashing you may need to press the reset button to get the chip started running the code and doing its cycle.
Now that it is running, we can measure its power consumption. I actually had to buy a new multimeter for this purpose. Here is the power situation when the code is actively running (WiFi radio is on and working):
The multimeter on the left is configured as an ammeter, and set on the milliampere scale, and it registers about the same as the NodeMCU when active but slightly less power consumption at 73.6mA. The multimeter on the right is configured as a voltmeter, and it shows the voltage drops down to 3.06V when it is active.
Now I think we need a little drum roll… how does it look when it drops into deep sleep mode. The next picture shows that:
At first glance that 30.3 might look scary high, but look again. Notice that the ammeter is now configured for microamperes, not milliamperes as in the previous photo! That is, this ammeter is reading 30.3μA, which is pretty great. To put it in perspective, the NodeMCU board was using over 350 times as much power in deep sleep as this bare ESP8266 board is using. Now, 30.3μA is not the low, low, 6.5μA that the ESP8266 documentation claims, but it is in the same ballpark. Also, remember the BMP180 is also being powered here, and some power is being used to pull the GPIO high through that 10K resistor. And my new multimeter is nothing special. I paid $35 for it. So it may not be entirely accurate near the bottom of the μA range. So I am pretty happy with this number. Also notice that when in deep sleep the voltage (voltmeter on the right) has popped back up to 3.33V (it was barely over 3V when active). Again, if you want a primer on how to measure voltage (volts) and current (amperes) in your circuits, I have written a short article on that for you.
Once all that dust was settled I migrated the ESP8266 from the breadboard to more permanent packaging, soldered on a perfboard, with pins to attach a USB-UART board for more programming if desired, and a with a common JST socket for the battery pack to connect. The result is shown below:
I glued a thin piece of white plastic between the ESP8266 bare module and the perfboard to ensure that no inadvertent connections were made between the wires by touching the perfboard solder points below. I used silicone adhesive for this and to glue the wires down in back. Here is the ugly mess on the backside after soldering then gluing:
It later occurred to me that probably the power for the BMP180 should be turned off when the ESP8266 is in deep sleep mode. You could accomplish this by wiring the BMP180 3.3V power pin to one of the free GPIO pins, and then in your code just setting that GPIO pin high at the start of the program. That is, power the BMP180 from the GPIO pin. When the ESP8266 goes into deep sleep that GPIO would drop low and the BMP would be turned off. I’m not sure how much that would help since we are already down to 30.3μA.
Anyway, let’s do some math on these current measurements and see if we can forecast the battery life of this thing.
C. Computing Battery Life Estimates
From timing the running of the code it appears to run in active mode for about 15 seconds, before dropping into deep sleep for about 60 seconds. It may be closer to 14 and 58, but let’s use round numbers.
When the bare ESP8266 is in active mode, my new meter shows 73.6mA. In deep sleep mode, it shows 30.3μA.
In any 75 second period, this thing is expected to be active for 15 seconds or 0.2 of the time and asleep for the other 60 second or 0.8 of the time. For the sake of simplicity, let’s just assume that 0.2 of the time it is awake and the remaining 0.8 of the time it is in deep sleep. So on average this thing consumes (0.2 * 0.0736A + 0.8 * 0.0000303)A or about 14.7mA of current. That’s worse than the NodeMCU deep sleep performance. How long would a pair of AA batteries last at that rate?
Alkaline batteries each contain about 2500-3000 milliamp hours (mAh) of power. So being conservative, and assuming 2500mAh per battery, that 14.7mA would last around (5000 / 14.7)hr or 340.136 hours, or about 14.167 days. Clearly this thing needs to spend a greater percentage of its time in deep sleep, or those two batteries will only last a couple of weeks.
What if the device wakes up only once every 10 minutes? Then it would be sleeping for 600 seconds for every 15 seconds it was awake. This changes the math a lot. Now it is awake for only 0.024 of the time (and in deep sleep for the other 0.976 of the time). Mean power consumption is then (0.024 * 0.0736A + 0.976 * 0.0000303A) or 1.766mA. At this rate the batteries would last around 2831 hours, or about 118 days. Still not really long enough.
How about sampling every 30 minutes? That’s 1800 seconds of sleep for every 15 seconds awake. That’s 0.008264 of the time being awake. Mean power consumption works out to (0.0006823 + 0.000030049601)A or 0.712349601mA, which will consume 5000mAh in about 7023 hours, or about 293 days, or almost a year. So I am going with that on my “thing” and we’ll see how that goes. Since the amperage measurements are probably not accurate, this math may be off, but we’ll see.
Of course, waking only once an hour would about double the battery life again. So you can decide what you want to do with your “thing”.
During development even a 60 second pause seems like a long wait, so the code as you cloned it from GitHub has a 60-second sleep built in (not 30 minutes). To change the sleep time to 30 minutes you will need to modify this line of the program:
#define DEEP_SLEEP_USEC 60e6 // i.e., 60,000,000 uSec == 60 seconds
Change that code to this:
#define DEEP_SLEEP_USEC (30 * 60e6) // i.e., 1,800,000,000 uSec == 30 minutes
Then you must re-flash the ESP8266 using the procedure above (press both buttons, then release reset but continue to hold flash until “Done uploading”).
I set the sleep time to 30 minutes, attached the batteries, pressed reset one last time. Then I sealed the whole thing in an old peanut butter jar, scribbled with the date, and battery life estimate (see below) and placed this jar in my (shaded) plastic garden shed in my back yard where I keep my pool chemicals. I didn’t punch any holes in the jar, so the temperature and pressure readings may be inaccurate, but this is a battery life experiment and I don’t really care much about the data it’s collecting.
It’s working away in my garden shed now and will be for about 293 days, if my calculations above are correct. I put it out there on Friday, May 18, 2018, so it should last until approximately March 7, 2019. You can observe its output anytime you want, from anywhere on the planet. You should see something like this there:
Remember though that this little ESP8266 only publishes data every 30 minutes, so you may need to wait a while to see any action. The code for the “esp8266.html” web page at that link, and a simplified version (“simpler.html”) that might be easier for you to modify for you own use, are in the same GitHub directory with the ESP8266 source code.
There’s one last thing I want to tell you about, the newer cousin of the ESP8266:
The photo above shows the new ESP32 (top left) beside our old friend the ESP8266MOD-12E. As you can see, the new form factor is similar to the old, but the ESP32 has more connectors, and they are even more finely spaced. Below the two ESP chips is a standard perfboard, and a metric ruler for size comparisons.
The ESP32 (specifically this is an ESP-WROOM-32) is significantly more powerful than its predecessor. It has a dual core 32-bit CPU, clocked at 240MHz (ESP8266 is single-core at 80MHz or 160MHz). It has 520KB of RAM (more than ten times ESP8266). It also has up to 16MB flash for your program and data. It also has 18 pins that can do analog-to-digital conversion for input (ESP8266 had 1) and all GPIO pins can do digital-to-analog output using PWM (see the Analog vs Digital article for more info about analog circuitry and why it is important). Link the ESP8266, the ESP32 has a deep sleep mode, and it can apparently achieve 5.5μA in deep sleep.
I went through the same progression of steps as I showed above with the ESP32…
Above, from left to right, is the NodeMCU board for the ESP32, the bare ESP32 module, and then the soldered project board I made using the bare ESP32, and then on the top right is the NodeMCU board for the ESP8266, for comparison).
The ESP32 board does not require an external wire from a GPIO to the chip reset pin like the ESP8266. There is internal wiring for that now.
The ESP32 uses much more power when awake than the ESP8266, and I was unable to get any projects to owrk with it using only two AA batteries. Where the ESP8266 consumed about 73mA when active, the ESP32 consumed over 150mA active. Also, it seemed to have brief power dips that my multimeter could not read. In any case, I could not stop it from having “brownout” problems when active (voltage drops so low that chip reset occurs immediately after going active).
I was able to achieve a very, very low current deep sleep with the ESP32 (better than I ever managed with the ESP8266) as you can see in the photo below:
Nevertheless, I could not power this device with a small battery pack of 2 AA batteries even for a single active cycle, let alone weeks, months, or a year. As soon as the chip would go active, the voltage would drop, and the chip would reset. It would rapidly cycle like this every time I tried. So that was a big disappointment. I tried adding a big capacitor to mitigate the downward voltage spike issue, but I was unable to successfully prevent brownouts,
Also, it’s worth mentioning that soldering the ESP32 requires even more skill than soldering the ESP8266. Here’s a photo showing standard spacing 2.54mm pins on the left, then the ESP32, then the tip of my soldering pen on the right:
I was able to do the soldering to this package, but I was not successful the first time. Although I inspected my connections with my tiny plastic 45X microscope (shown earlier in the article) one of the connections turned out to be bad. After fixing it, I switched to using my 500X digital microscope to check the connections:
I tend to think I can solder well until I see my handiwork at 500 times magnification. Those connections look terrible! But they work. I just wanted to show that the soldering is a bit tricky. There are helper boards that may make the soldering easier (without adding support chips like the NodeMCU to consume more power). I have ordered some of those and I will add info here when they arrive and I try them out.
For right now, my recommendation is that if you want a more powerful microcontroller, the ESP32 certainly is a more powerful choice than the ESP8266, but that power comes at a cost. If you don’t have any need to power your ESP32 thing with small batteries, then the ESP32’s power consumption may be irrelevant to you. On the other hand, if you need to power your thing with small batteries for long periods, and you don’t need a lot of processing power in the microcontroller, then I think the ESP8266 is a better choice. In active mode, the ESP8266 uses less than half the power of the ESP32, and the ESP8266 does not brownout when powered with two AA batteries.
I look forward to hearing about your experiences with the Espressif devices, in the comments below.