Getting started with PlatformIO and the ESP32

Here’s the shortest “Getting Started” you’ve ever seen (disclaimer†  …I’m making the huge assumption that you already use PlatformIO as your development environment for your ESP8266 projects.  If you don’t, you should!).

Add support for the ESP32 with:-

platformio platform install espressif32

Create your new development (project) directory and, in that new directory, initialize the environment for the type of board you have‡  with:-

platformio init --board=esp32dev

Start writing code, as normal, in the newly created src directory and then compile with:-

platformio run

At this point, PlatformIO will go off and automatically download the framework support for your environment (this first time, only) and then compile your code.

You just can’t get any easier than that!

† I don’t actually have an ESP32 board yet.

‡ List the available target boards with “platformio boards

Ψ If you’re tired of typing “platformio” in full each time, you can shorten it to “pio” (“platformio” is used for clarity here).

ω For more information on getting started with PlatformIO, see the full documentation at:-

433MHz/IR MQTT Gateway Project

It’s nice to see a project that develops over time and Florian has a good example on his blog.  He started off in the middle of last year by putting together a low-cost, arduino-based sensor for his garden and things seem to have just grown from there :-).  You can follow along on his blog from the initial version of his bidirectional 433MHz, ESP8266-based, MQTT gateway, progressing to the IR enabled version by the end of the year and his OpenMQTTGateway project this year.  It’s a good read and a great little project to follow.



How to do a Sonoff memory upgrade

Jonathan Oxer, over at SuperHouseTV, has been running a series of video episodes on the Sonoff product line recently and I really recommend his latest.  The theme of the video is Sonoff-specific hints and hint #1 is how to upgrade the memory chip in a Sonoff.  Jonathan does a great job of demonstrating how to remove the chip with nothing more than “a big, old, clunky soldering iron” and a screwdriver.  A picture is worth a thousand words, so you need to multiply that by whatever the frame rate of a YouTube video is.  Watch it!  It’s worth it.

Simple demo for the “Yellow” board

As promised in the previous post, we’re going to explore a simple application for the Yellow Development Board this time round.  The one thing that this board has plenty of is LEDs.Yellow Serial Development Board  There are half-a-dozen red LEDs and one blue across the bottom of the board, as well as a 5mm RGB LED.  So, not surprisingly, we’re going for the “Blinkenlights” option as the first demo.  You won’t need an MQTT server or even a working access-point to have this demo work, but the display does get a bit boring quite quickly.

If you have modified your board with the addition of the latching power switch described in the hardware article, this demo will turn itself off after three minutes of run time.  If you haven’t added the switch, you’ll have to remove power by pulling one of the batteries out, otherwise it will just keep on running until the batteries are completely depleted.

The code for this first demo is available (with the other demos) in the GitHub repository.  The filename is Initial_Power+LEDs.ino.  My preferred environment for compiling ESP8266 programs nowadays is PlatformIO (if you haven’t tried it yet, you should give it a go); it makes compiling programs for multiple different architectures a breeze and you don’t have to worry about shoehorning things in, it just does the right thing.  Anyway, the demo programs are basically Arduino-IDE format for the ESP8266, so whether your preferred  environment is PlatformIO or Arduino-IDE, they should just work for you (if you’re still in the dark ages, using Espressif’s SDK, you’re on your own!).

In addition to the base demo itself, Over-The-Air update functionality is also built in to each program, so assuming that you have a working network and access point, you should only need to upload to your ESP8266 by serial the very first time, after that you can use the normal Arduino or PlatformIO OTA commands to upload a new demo file.

Note that all of the demos are set up to use a static IP address, netmask, gateway and DNS server.  This is to ensure that the ESP starts up as quickly as possible in a real “button” application.  The WiFi channel number is also specified, again as part of a fast, robust start-up procedure.

Before compiling any of the demos, you need to go through the user_config.h file and change all of the default settings in there to match your local network.  The specific settings you should be interested in are:-

  • LOCATION   [optional]  Setting this to your general region may help you to find your own results when using a public MQTT server for the later demos.
  • STA_SSID  [required]  Set this to the SSID (name) of your Access Point.
  • STA_PASS  [required]  Set this to the (WiFi network) password requested by your Access Point when connecting.
  • WIFI_IPADDR  [required]  Set this to be the IP address which you want this specific ESP module to use (it is assumed that you know your own network …DO NOT simply choose a random IP).
  • WIFI_NETMASK  [required]  This should be set to use your network specific addressing scheme.  Generally, if your IP addresses begin with “192.” you should be okay to leave this as “”, but if you don’t know, please ask someone who does.
  • WIFI_GATEWY  [required]  This should be set to the IP address of your gateway router.
  • WIFI_DNSSRV  [required]  This should be set to the IP address of your local DNS server.
  • WIFI_CHANNEL [required]  This is the number of the WiFi channel which your access point is using (and can be between 1 and 14, depending upon where in the world you are).
  • MQTT_HOST  [required for later demos]  See later explanation for this option.

If you don’t know the answer to any of the “WIFI_*” settings, you need to find someone with a better knowledge of your local network and ask them;  DO NOT just guess.  You could effectively cripple the whole of your local network with a wrong answer to some of these questions.

If you have a good, robust working DHCP server and you don’t care about start-up speed, you might want to convert these programs to use DHCP instead.  As this is by far the most common option in ESP8266 programs generally available on the ‘net, I will leave this conversion as an exercise for the reader (it’s quite a bit shorter and simpler than the static address variation used here).

Although MQTT isn’t required for this first demo, I’m going to mention it here anyway, just so you know what some of the options in the user_config.h file are.  The default setting for MQTT_HOST in that file is “”, which is a publicly accessible server in Germany which HiveMQ very kindly make available for testing.  HiveMQ also provide a whole bunch of MQTT related resources and services, so please do send any business you can in their direction.  Please DO NOT bug them with support requests for these demos; those requests should come to me.  Please also note that the HiveMQ server gets -very- busy (it’s not unusual to see in excess of 1,000 concurrently connected clients), so it can be quite difficult to see any output from your specific device on their web dashboard.  Please resist the temptation to increase your publishing rate; the server is already busy enough.

If, on the other hand, you have a local MQTT broker (server‡), then you should change the MQTT_HOST option in user_config.h to point to it specifically from the very start (if you don’t yet have an MQTT server set up, I would recommend the Mosquitto package; it comes with the broker and with two command-line utilities, mosquitto_pub and mosquitto_sub, which allow you to easily publish or subscribe to topics on either your local broker, or any other publicly accessible broker service on the ‘net.  Mosquitto is available as an optional package for most Linux variants through the software manager and there’s also a binary package available for Windows).

The MQTT_CLIENT_ID is a symbolic ID used by your ESP8266 when talking to the server.  It enables the MQTT broker to differentiate between the dozens of ESP8266 modules which you have connected to your network.  The string “ESP8266_%06X” is automatically replaced at run time with a six-digit number created from the unique ESP8266 chip-ID, to provide something like “ESP8266_09C721”.  This prevents potential clashes where two (or more) ESPs sharing the same ID would cause each other to be disconnected from the MQTT broker when a new request comes from a different address.  This means that if 500 of my closest friends all decide to build the MQTT demo and use the default, publicly addressable HiveMQ server, they should all work perfectly, without trampling over one another.

Finally, note that our ESP client can handle three different topics (only two are defined by default).  TOPIC1 is defined as “timestamp” and we become a subscriber to that topic (the HiveMQ broker currently publishes a timestamp every few seconds).  TOPIC2 is defined as “Yellow/LDR” and our MQTT demo program will publish regular updates to it.  The data published to that topic is the ADC value of the ESP8266 pin with the LDR attached (so the value depends upon the ambient light level).

All of the demo programs, including the non-MQTT version, will print out info to the serial port, including regular LDR value updates.

The mood-light display mode on the Yellow is based on code by “Mike Mc” (Mike McRoberts, author of “Beginning Arduino”).  The code uses a 256 entry look-up table to compensate for our weird vision and produce what looks like a linear fade to our eyes.  Kudos to Mike for writing such a durable routine, which works very well on the ESP, despite its proclivity for running off and doing WiFi-ish stuff at unpredictable intervals.

Speaking of the need to service WiFi requests and other housekeeping, the reader will notice that there are calls to yield() sprinkled liberally throughout the code and that there is also an added function, Ydelay(), which is simply a call to the normal delay function with an additional call to yield() thrown in.  It seems like you can’t call yield() often enough in any ESP code that could get itself caught in a tight loop.


‡ I use the terms “broker” and “server” interchangeably, but strictly speaking, the “broker” is the MQTT process running on what we loosely refer to as a (hardware) server.  Your client devices all connect to and exchange messages with this server.  You’re not confused, are you?!?!

Yellow doorbell/dash project

In the previous post, I outlined how the “Yellow Development Board” from AI-Thinker had become my new, go-to ESP8266 board for projects, partly because the headers make it easy for interconnects and partly because it’s got lots of LEDs already on board.  Not to mention that it’s reasonably priced and comes equipped with a battery box and a low quiescent current voltage regulator (important when you’re running from batteries).

Even more recently, I wanted to experiment with a doorbell-cum-dash style button, based on one of the dollar-store LED push-button lights which seem to be available everywhere nowadays. The idea is that pushing the button will initiate a connection to the MQTT server Three-LED lightfrom the ESP8266 embedded inside the button and then, based upon which ESP just called, the MQTT server will initiate a process. That process could be anything from ordering another bottle of Rivella from Amazon, to switching on the stair lights, or announcing that there’s someone at the back door (or just about anything else you can think of where a momentary push button is used). The dollar-store light, as it comes, incorporates three, white LEDs and a latching switch, with a battery box for three, AA batteries built into the bottom. The construction of these lights is extremely flimsy (I just cracked the battery cover on the one pictured above while positioning it for the photo), but they are still amazing value for what they are. Taking the thing apart reveals that the LED “reflector” is nothing more than a flimsy sheet of white card, but that doesn’t matter, as we won’t be using it anyway. In fact, we can remove the LED PCB completely and just hold onto the white LEDs for some other project (our Yellow board already has more than enough LEDs) just keeping the base for our project. The original switch is a latching type, which isn’t what we want, either. On Prototype internalsthe first LED light that I bought, I tried to dismantle the original switch, with the idea that I’d convert it into a momentary type by throwing away the latching mechanism. However, the mechanism is so tiny that my motor skills weren’t up to the job (and that tiny little spring will no doubt be found by the vacuum cleaner, eventually). In the end, I simply removed the plunger from the original switch and glued a momentary “tact” switch on top of it (which put the new switch at exactly the right height to work with the push mechanism). The Yellow board (this time minus its own battery box) fitted perfectly on top of the built-in battery box (with that bit of flimsy white card insulating it from the exposed battery connectors), while some extra circuity fitted on a strip of prototyping board at the end of the battery box opposite to the switch. Despite the sticky-tape and hot glue, this prototype worked very well.

The circuitry on the prototyping board deserves a quick explanation here. The whole purpose of this project was to have an ESP8266 which would sit doing nothing at all for very long periods. Basically, that’s something that the ESP isn’t very good at. Even if it’s sitting there in deep sleep, it can still deplete three AA batteries in about three months, which is not very useful for a doorbell/dash type application, so the intention here was to have the ESP turned off completely, until it needed to wake up. The button implies physical interaction, so we know we can get the unit to switch on for the length of time that the button is held closed, at least. For a doorbell type application, that’s likely to be some significant part of a second, at a minimum, but still probably not long enough for the ESP to go from a cold start, through negotiating a connection with an access point to sending an MQTT message.  What  we needed was a method for the ESP to ensure, once it had been initially powered, that it could latch the power on until its work was complete and then (importantly) turn it back off again.

The answer is provided by the circuit below.  The ESP will start up very quickly indeed, especially if you don’t muck about trying to initialize serial ports, or wireless, or sending debug messages.  So what we do in our application is, as the very first thing, use the pinMode() command to initialize a designated pin as an output (which we’ll call “POWER_SW”, for power-switch) and then call digitalWrite() to set POWER_SW to “HIGH”, then we go back to our normal setup() routines.  This happens in a few milliseconds and we use the output of the GPIO pin designated as “POWER_SW” to drive the PWR_LATCH input signal of our latch circuitry, below.†

MOSFET power-latch schematic

Okay, so how does all of this work?  Well first of all, power is coming in from the battery box on the L/H side of the diagram on the pads marked as BAT+ and BAT-.  Our Yellow board is supplied from the R/H side pads, marked PWR_OUT and GND.  In between, right at the top, there are two more pads marked as SW_BATT and SW_VREG.  These are the two wires to our actual momentary contact “tact” switch, which we just pressed (a few milliseconds ago) to provide the initial power connection between the battery box and the ESP.  What we have now is a situation where the switch has been released, the battery is disconnected from the ESP8266 again and the charge on the smoothing capacitor next to the voltage regulator on the Yellow board is rapidly starting to deplete.

The ESP though, has already started up from cold, initialized the POWER_SW GPIO and set it to high.  As we noted, that GPIO is actually driving the PWR_LATCH line (bottom, R/H side of the diagram above).  This is connected to the gate of Q2, an N-channel MOSFET and will turn that device on, pulling the voltage at the junction of R1 and R3 low in turn.  This turns Q1 (a P-channel MOSFET) on, providing an alternative path for the battery power to reach the ESP8266.  As long as the “POWER_SW” signal remains high, the power will remain connected to the ESP8266.

As you’ve probably already guessed, once the ESP has finished running its designated tasks, it simply flips the POWER_SW signal from HIGH to LOW and, before the ESP8266 has time to print out “Goodbye cruel world!” to the console, the power is gone.

Why don’t we just invert the logic and have the ESP8266 drive Q1 directly, instead of adding the extra components around Q2?  Well the main reason is that the battery pack on the LED light has three 1.5 volt batteries in it.  When they’re brand new, the total voltage across all three cells can measure as high as 4.8 volts.  The ESP, as we all know (despite rumours to the contrary) is a 3v3 device and the voltage at the end of the resistor chain of R1 and R3 would float up to full battery voltage when the ESP was switched off and not pulling that line low, so Q2 is mainly there to protect the ESP from the full battery voltage (the N-channel used for Q2 needs to be chosen to withstand full battery voltage with some additional headroom, which isn’t asking much of a stand-alone MOSFET).  The chain of R1 and R3 is also there to protect the gate of Q1, the p-channel device, from being driven beyond its gate/source voltage limit (which is unlikely in this particular circuit, anyway).

Finally, the question is, which GPIO should we use as the POWER_SW drive?  Well, GPIO-0, GPIO-2 and GPIO-15 are bad choices, because they are all read at power-up time to determine which mode the ESP will boot into.  GPIO-16 is a good candidate though, as we definitely will not be connecting it to the reset pin for deep-sleep wake-up in this project.  If you want to change this on your particular board, feel free.  Just change the definition in the user_config.h file (and ensure that your chosen GPIO is not used for any of the other functions).

Update – The prototype auto-latching switch board worked very well, so I’ve knocked together a PCB using mostly through-hole components (that’s what I have in my parts drawers and besides, my hands are too shaky for SMD stuff nowadays …I can just about manage the AO3415, but only because I can’t find it in TO-92).  If anyone wants to roll their own, the board files (Eagle format) are available on GitHub.  My next version will probably provide an alternative SMD footprint for the 2N7000 (using the AO3414, which is what I had originally planned), but feel free to go 100% SMD if you prefer.

Okay, that’s our hardware.  The software is coming along next in two or three separate pieces.

† – It’s worth noting that if the GPIO on the ESP8266 isn’t initialized to “digital” mode, the MOSFET switch will be held “on” and you’ll be unable to switch it off (which is somewhat counter intuitive).

PlatformIO, the ESP8266 and an ancient Linux version

A couple of the sites which I list in the links section (see the menu to the right) have been singing the praises of PlatformIO in connection with ESP8266 development recently.   Squix actually goes as far as propose using PlatformIO as part of a “Continuous Delivery” workflow for the ESP8266 (no, I didn’t know what it was either, but apparently it entails adding automatic testing to verify that a given release meets certain criteria before being released to the target device), while Jan Penninkhof was so impressed with PlatformIO that he put together a very nice “How To” video on getting started with it on the Mac.

But hold on, just what is PlatformIO and why would I want it?  PlatformIO is a build system; it’s like “make” on steroids, as implemented by Superman, with help from Jethro Tull†.  If you want to build a project for the ESP8266, PlatformIO will help you to do it by (for instance) downloading the toolchain automatically for you.  If you decide you’d like to build for two disparate architectures (lets say ESP8266 and TeensyLC) you can just let PlatformIO know that at initialization time and it will magically download and install both toolchains and support when you first attempt to build the project.  If you include libraries (via the normal “#include <whatever.h>” method) in your code, PlatformIO will help you find the latest version and automatically download any dependencies which your chosen library may have.  Basically, if you’re a newcomer to the ESP8266 world, this is the easiest way to get started compiling and flashing.  Don’t bother trying to follow the (mostly conflicting) instructions on the 50 odd (out-of-date) web sites on how to install the toolchain, or how to configure esptool for flashing, or how to set-up the Arduino-ESP environment… just install PlatformIO and let it do it all for you.

All in all, it looked like something worth trying to me, especially after Squix and Jan had explained some of the features in plain language (which is wonderful, because  buzzword-laden sentences containing “framework”, “integration”, “extensible” and friends put my brain into deep-freeze mode).  My main issue with anything “new” like this though, is usually my ageing primary work machine.  I’m running a fairly ancient version of Elementary OS, which is based on Ubunt 12.04.  Attempting to install anything written after the Magna Carta on this steady old workhorse usually results in a raspberry from the speaker as well as the normal, copious error messages about the kernel, libraries, disk spindle bearing and user all being past their “sell by” date.  I’ve given up even trying to install anything which mentions “Java” anywhere in the description.  PlatformIO though, is written in Python and although I’m not a Python programmer, I do know that the version installed on my system is quite a recent one, as the ESP8266 loader program required it.  A quick check with “python –version” showed that it was actually 2.7.3.  Almost all versions of Linux have some type of updater attached to the package-manager,  so you should be able to update your system (no matter how ancient) to a recent revision of Python without too much effort.

Moving on to getting PlatformIO working, the next step is even easier.  We now need to use the Python package installer, “pip”,  to do the grunt work of adding PlatformIO itself.  You can check to see whether “pip” is already available on your machine using a command such as “which pip” or “whereis pip“.  If “pip” exists, they should return the fully-qualified location; something like “/usr/bin/pip“.  If it doesn’t exist, you’ll need to use the system package-manager to add it (which might be as simple as “sudo apt-get install pip“) to install it.  Assuming that “pip” is now available to you, simply do:-

pip install -U platformio

Note that the “-U” option comes after the “install” command.  It forces pip to update the install target to the latest available version.   And that, basically, is that!  You now have platformIO installed on your ancient Linux system and it’s going to do all of the rest of the heavy lifting for you.

Now that you have it installed, you can create a work directory for your projects.  I just made a PlatformIO directory directly under my home directory as an easy way to get started, but basically you can call it whatever you like (“work”, “projects”, “Eric-woz-ere” will all work equally well).  What we’re going to do now is to create sub-directories in the work directory for each different project that you build.  This is good practice anyway, but PlatformIO makes it almost essential, as it supports a metric ton of embedded processors (as well as their different toolchains), so one project might be built for the ESP8266, while the next might be for the STM32-Discovery and the one after that for the TI MPS430.  PlatformIO will quite happily build each of your projects for a different processor (or even for multiple, different processors) if you want it to.

Okay, so to start off, we’re going to build a simple door-bell project for the ESP8266.  Basically, this is going to be a battery powered project and, because it’s housed inside an enclosure attached to a wall, we want to enable OTA programming to allow us to update it without ripping the enclosure apart each time.  We have some basic code already available which has been developed (to date) in the Arduino-ESP environment.  Lets start…

mkdir DoorBell  && cd DoorBell

mkdir ./src

cp ~/Arduino/DoorBell/DoorBell.ino ./src

cp ~/Arduino/DoorBell/user_config.h ./src

So, we’ve created the “DoorBell” sub-directory, changed into it and created a “src” directory, then copied over our code (and an include file) from the existing Arduino build tree into the new “src” directory.  Now we need to tell PlatformIO which target processor we want to build this project for.  You can get a (very long) list of the available targets using the “platformio boards” command.  You’ll need to scroll up through the output to find the  “Espressif” section.  Most of the common ESP boards are in the target listing, including things like the Huzzah and NodeMCUv2; there are also some that I’d never heard of, such as the Phoenix and WifInfo (which seems to be this).  I’m actually using the “esp12e” setting for my project (even though it’s just a generic ESP12 processor), with no ill effects.  To implement your board choice and have platformio write it’s own, minimal configuration file for this new project, use the “platformio  init  --board=phoenix_v2” command (which, in this example, is setting the board type to “Phoenix V2” …replace this with your own choice).

The init command (above) will create a bunch of files and directories under your newly created project directory.  The main ones are:-

  • platformio.ini      – The configuration  file for this project instance.
  • src      – The directory where PlatformIO looks for the source code for this project.
  • lib      – The directory where PlatformIO will look for custom, local libraries which you might add.

We already created the “src” directory in our initial steps, above; that’s okay though, the “init” command will not overwrite an existing directory.  The other contents of this newly initialized project directory can change, depending upon (for instance) which IDE you choose to use.  As an example, if we tell PlatformIO that we want to use the “Eclipse” IDE, using “platformio  init  --board=phoenix_v2 --ide=eclipse“, we will end up with an extra “.settings” directory and “.project” file, both of which contain template information specific to the Eclipse IDE.

The platformio.ini file is fairly sparse at initialization time, but it is important.  For instance, the default framework environment for the Espressif processor is “arduino”, but by editing your platformio.ini file you could change this to “simba” (that’s actually the only other valid framework available for Espressif targets).  If you now start a compile with “platformio run”, PlatformIO will immediately go off and automatically download and install the Simba framework package for you, before kicking off the build of your project with a totally different framework (if you try this, please be aware that not all of the Espressif boards are supported by Simba, whereas most of them seem to be fine with the default Arduino setting).

This semi-automatic mode of operation is an intrinsic part of PlatformIO and does make life easier for the novice user.  Another good example is when it comes to uploading your newly built code to the target board.  When we start off, we don’t generally have any other option than uploading via serial.  To kick-off the upload process, plug your ESP board into your computer, as normal and then use the command:-

platformio run -t upload

PlatformIO will go off and automatically detect your serial device (this works very well if you’ve already been using your system for programming an ESP board …if you’re starting from scratch in a clean environment, you might have to check the 99-platformio-udev.rules file settings – this is Linux-specific BTW), and  upload to the ESP.

That’s it.  You’ve just built and uploaded your project using PlatformIO.

Once your ESP board is up and running and connecting to the network, you can very easily change to using the Arduino-style OTA upload method by going back and editing the platformio.ini configuration file.  Just add the line:-


(where “” is replaced by the actual IP address of your ESP board) to have PlatformIO alter its behaviour to the “upload” command to use OTA instead of serial.  Of course, you need to add the Arduino OTA support code to your project file too, before this will work (see the example file BasicOTA.ino for the lines of code you need to add …the basic OTA functionality is already incorporated into the PlatformIO/Arduino libraries).

A word here on libraries.  Normally we use libraries created by others to add functionality to our projects.  A good example of this would be the PubSubClient library for MQTT.  As you might expect, PlatformIO provides a method for handling third-party libraries like this and, naturally enough, one of the first things a new user needs to do is find the libraries needed for a given project.  We can query PlatformIO for the MQTT libraries it knows about using:-

platformio lib search MQTT

This will return a numerically indexed list of libraries matching the keyword “MQTT”.  Currently this returns 13 hits on my system.  As it turns out, Nick O’Leary’s PubSubClient library is the first one in the list, with the reference number “89”.  Okay, lets get PlatformIO to download and install it:-

platformio lib install 89

Note that we use the reference number, not the name.  PlatformIO downloads and installs the library and adds it to it’s own database.  What’s nice about this is that it will check every week or so to see whether the library has been updated recently and prompt you to refresh your installation if it finds that you’re not running the latest revision.

As you might expect, PlatformIO also runs the “latest and greatest” revision check on itself and will also prompt you to upgrade if you’re not at the latest rev.

I’m impressed!  Since trying PlatformIO for the first time a couple of weeks back, I’ve been moving everything over to it.  No more messing around with the horridible Arduino IDE.  Yay!



† – The man, not the group.  Implying that it does some basic, but essential stuff for you, not that you’re as thick as a brick.