A wee bit late for Xmas, but…

Here’s a very seasonal item, courtesy of Hackaday  …Sean Hodgins’ ESP8266-enabled Xmas ornaments.  They’re worth checking out for the really neat, multi-coloured PCBs (although I’d probably decide to do without the piezo speaker if I were to build any).

Sean Hodgins' Xmas Ornaments

No word yet on where Sean sourced the PCBs, or on what the battery life is like (even with deepSleep(), not long, I’d guess).

Sean’s GitHub repository has all of the code, if you fancy knocking a couple of these together on Xmas morning.

Z83-II Mini-PC (Quad core 8350)

Another departure from the ESP8266, but for something that ESP8266-hackers might find interesting.

Over the past couple of years I’ve been ditching most of the big, ugly, power-hungry desk-top and server machines which used to run my mighty empire (aka “the house”) and replacing them with machines that are a lot smaller and a great deal less power-hungry.  I’ve got a few SBCs of various sorts; all ARM based, mostly multi-core and almost all still shamefully naked and gathering dust, even though they’re alive and kicking and running various essential services on our home network.  In addition to the lack of a case, almost all of them have other drawbacks of some sort (not well supported by the operating systems which I prefer to run, missing critical hardware, etc), so I keep looking for the perfect mini system.

I thought I’d found it a while back when I splashed out on a SolidRun CuBox-i4.  It’s small (very small, in fact), has a quad-core processor, 2GB of memory, GbE, USB ports, HDMI and (a major plus) comes in a diddy little black-plastic case.  Unfortunately, it turned out to be a major pain in the proverbial trying to install and run a reasonable operating system and lots of hoops needed to be jumped through (in the correct order) to even start the OS installation.  It has been running FreeBSD for quite some time now, but it suffers greatly from the lack of a real-time-clock (and unlike a Raspberry-Pi, for instance, it’s not easy to add one), has limited USB functionality and tends to fall over in a messy heap at reboots if the moon happens to be full or the wind is coming from the east.

So the quest goes on for a truly great (cheap) mini system and, right in the middle of the purple Thursday (or was it cerise Saturday?) sales, I found a new system on GearBest that seemed too good to miss.  Because it was on sale, it was a few dollars more expensive than normal (???) , but it was still a pretty good price, given the specs.

ZX83-II Z8350-based mini-pc

It’s an Intel quad-core Atom X5-Z8350 based system, with 2GB of main memory and 32GB of eMMC.  It has GbE, two USB-2.0 ports and one USB-3.0 port.  There’s also an SD-card slot and an HDMI video connector.  For those who care (and I don’t), it also comes pre-loaded with Windows-10 (don’t ask me for more details on what specific version, because I don’t know).  It’s a 64-bit system (but read on for the limitation on that) and it also comes with built in Bluetooth and a/b/g/n/ac WiFi (neither of which I’ve used).  More importantly for me, it’s also a fanless system.  It is advertised as coming with an “English User Manual”, but you can save yourself a few seconds of “I don’t believe this crap!” frustration by throwing said “manual” straight into the bin; there is nothing in it which is even remotely useful.  It does come with a fairly substantial looking mounting bracket (to attach it to a monitor, or wall) and two HDMI cables — one short and one long(er).  A power adapter is also included (but you need to make sure that you order the correct version for your particular country).  The shipping box is also very sturdy and should hold up well if a passing elephant accidentally treads on it.

I would have been quite happy to boot into some sensible operating system and immediately wipe Windows from the disk (eMMC), but it was not to be.  The one, big gotcha with this system is the BIOS.  At first glance, the BIOS menus are very sparse indeed and you’re not going to get very far at all with this system unless you know the magic incantations (it may also help to have a spare chicken to sacrifice …I haven’t actually tried this yet, though).  I did get through quite a few blank CDs and DVDs while trying to get various distributions to boot from a USB-connected DVD.  No matter what I did though, the dang machine just kept on booting into Windows (which was quite disconcerting at first, as I couldn’t see how to shut it down).  Some ‘net searches turned up suggestions for adding BIOS passwords (there are two in the version of BIOS which my machine has) to trigger extra BIOS menu items — Nope, doesn’t work.  You can forget that.  There was also one quite long diversion where some folks (seemingly correctly) noted that some functions which affect BIOS start-up are only available from within Windows, despite how stupidly chicken-and-egg-ish this seems to be (for those who want to try it, you need to select the shutdown function from the start menu and then hold down the shift key while selecting “shutdown”.  This will bring up a whole scad of extra menus which will change the UEFI boot settings …and then it will just merrily boot straight back up into Windows again).

It turns out that the UEFI boot  (which stands for “Unified ‘Effing Firmware Interface, by the way) is the key to all of this.  It’s a versatile system which is replacing the outmoded BIOS of years gone by with an updated and secure method of booting you into Windows …and booting you into Windows …and booting you into Windows (you get the picture), no matter what you actually want to do.   On some systems (and yes, the Z83-II is one of them) it has the added twist of limiting a 64-bit system to booting from 32-bit code (you’d better go back and read that sentence again …I wrote it and I still can’t quite grok  it!).  For some reason (lost in the mists of Redmont),  Windows was/is limited to booting from 32-bit bootloaders, so because everyone-and-his-dog only ever runs Windows, some machines (like the 64-bit, Z83-II) have a UEFI which will –only– handle 32-bit bootloaders.  Now before you start jumping up and down with your hand in  the air shouting “Teacher!  Teacher! I know!  Just  run a 32-bit OS!” you should also note that, because UEFI is new-ish and 32-bit systems are just so last decade, very, very few 32-bit distributions of any sort actually have any UEFI boot capability bundled into them at all.

I know the mantra is “never give up!”, but by this stage my fingers were twitching and the old grey-matter was sending signals to my hand to grab hold of that handy, 3kg lump-hammer and send the Z83-II and its UEFI back to meet its maker in very, very small pieces.  It was only the nagging annoyance of those extra couple of dollars for the maroon Monday “sale” price that held my arm in check.

By this point I’d read so many posts and articles on the UEFI and booting systems that I’d actually stumbled across one piece of related (and essential) information which actually worked with the Z83-II.  I’d discovered already that hitting <ESC> during initial, power-on boot would bring up the BIOS menu, but in a couple of posts related to other mini-pc systems people mentioned that <F7> would bring up the boot-device selection menu.  It worked, too.  Not only did I get a device menu (what the system had detected at boot up, rather than the BIOS preferred-device list), but it also gave a tiny bit of extra information about what the system thought it had detected on each particular device.  For the most part, to begin with anyway, that information was limited to “Windows boot manager” on the eMMC device.  This turned out to useful, though.  It quickly became apparent that having a DVD in the drive with something that the BIOS (and, presumably the UEFI) could read would result in that entry in the <F7> menu changing to give the maker’s name and model, instead of just a vanilla “USB CD/DVD” entry.  Unfortunately, very few of those DVDs would boot successfully, but at least it meant I didn’t have to go through the tedious process of having the system boot into Windows, yet again,  if there was obviously no readable disk in the drive.

I’d read in a couple of places that the latest Debian versions (greater than 8.0) had solved this 32/64-bit problem, so I burned a couple more DVDs and tried them.  I could get the extra info in the <F7> menu, but they wouldn’t boot.  A couple of other mainstream Linux distributions were also flagged (in Distrowatch) as being fixed, but none of the ones I tried actually booted.  Then I came  across a reference to Ian Morrison’s Linuxium site.  Ian obviously spends a lot of time mucking about with set-top boxes, mini-PCs and PC-sticks and has done a ton of work to get Linux booting on those devices.  He has also modded some mainstream distributions to boot on these infamous 32-cum-64 bit devices.  Ian’s modified Ubuntu 16.10 was the first thing that successfully booted on the Z83-II and proved that it could successfully bot and run something other than the dreaded “W” (thanks Ian!).  If you’re looking for a stable Linux distribution you could do a lot worse than to mosey on over to Ian’s page and check out his offerings.

Finally there was light at the end of the tunnel.  The Windows reboot cycle was broken.  I went off to see what I had to do to get OpenBSD or FreeBSD onto the system.  I didn’t have to look very far.  In another one of those “Duh!” moments, it turned out that OpenBSD had also introduced the 32/64 UEFI fix and the latest snapshot (booted from a USB thumb drive this time) not only installed, but also automatically created a dedicated UEFI “i” partition and populated it with the required boot files.  Not only that, but the BIOS now “knew” about the new, bootable drive and I could easily make it the default power-on boot device.  Yay!

So, in summary …at poweron, use <ESC> to get into the BIOS and <F7> to get into the boot device selection menu and use Ian Morrison’s modified versions of Linux, or OpenBSD 6.0 or greater, to prove that you can boot and install something other than “W” on the Z83-II.

…and don’t buy anything during a turquoise Tuesday sale.


Connecting the Yellow Dev board to a TFT display

Previously I mentioned using a modified version of Squix’s Weather Station Colour as a test application for a 2.2″ TFT 240×320 display with an SPI interface.  If you have a Yellow Board hanging around unused, I really would recommend this as a useful application.  My photo doesn’t really do it justice 2.2" 240x320 TFT Display(it is a rainy day here and the light is bad).  The actual display is quite crisp and sharp (even with the protective plastic shipping sheet still attached to the screen).

What you see to the left is Keith Fowler’s modified version of Neptune2’s modified version of Squix’s original (got that?).  The middle and bottom areas on Keith’s version dynamically update every few seconds to give you expanded information (for instance, the bottom 1/3 of the screen will change to show you the current phase of the moon, while the middle will give you the same style of iconized weather for an additional three days).  It really is quite neat, even for someone with eyes as poor as mine.

Squix has build instructions on is site, which I’d just like to add to here.  He’s using a NodeMCU board, where the GPIOs are numbered a little strangely, so here’s the connection map for a normal ESP-12 (or, in our case, the Yellow Dev board):-

  • MISO   –   N/C
  • LED   –   3v3
  • SCK   –   GPIO14
  • MOSI   –   GPIO13
  • DC/RS   –   GPIO02
  • RESET   –   RST
  • CS   –   GPIO04
  • GND   –   GND
  • VCC   –   3v3

There’s nothing special which needs to be done (other than watching out for upper-lower case issues with the names of the included font files if you’re compiling on a non-Windows machine).  Once the connections are made, you can load either Squix or Keith’s code and it will burst into life …except that you won’t get much useful weather information until you get your own developer’s ID from Weather Underground (it’s free).

The display connections leave us with GPIOs 16, 15, 12, 05 and 00 to play with (remembering that 00, 02 and 15 need special attention because of their specific pull-up/down functions at power-on).  One obvious addition would be the use of a P-channel MOSFET in the display LED backlight line to only light up the screen when a button is pressed.  That could save quite a bit of power over time (and I don’t particularly want bright flashing screens at night).

Personally, I plan on stealing some of Squix, Neptune2 and Keith’s ideas to implement a little controller which will display inside and outside temperature (using a local DS18B20 for the local sensing) and allow override control of a fan heating system via MQTT.


PlatformIO and JSON woes…

Yesterday was, for the most part, quite a good day for me.  The weather was bad, so it gave me an excuse to stay inside and play, at least for a couple of hours in the morning.  I’m still slowly working away at implementing a simple, forced-air heat distribution system in the house (our only permanent source of heating is a wood-stove in the lounge/kitchen area, so I’ve added some ducting to take hot air from behind the stove and gently and quietly push it out through a vent in the bedroom).  The latest idea is that I’ll have an ESP8266 with a small screen and a DS18B20 (or similar) in the bedroom which will display the temperature and allow manual on/off override of the fan control via a couple of buttons.

Anyway, I’ve had one of those 2.2″ TFT displays sitting around for ages waiting for me to get going, so early yesterday morning I wire-wrapped it to one of the spare “Yellow Development” boards that I have hanging around and then looked around for something to burn into the ESP as a quick test.  I remembered Squix’s weather station and vaguely recalled seeing a TFT version too, so off I went and grabbed it from his GitHub repository.  After a couple of false starts (what is it with Windows and non-case-sensitivity?!?!) it fired up beautifully and (almost) everything sprung into life (be warned, this application uses a lot of flash memory space to store image files, so you might not be able to fit all of the moon phase .bmp files onto your particular ESP).  The display was impressive enough to divert me into going to the Weather Underground site and signing up for a developer’s API ID, just so that I could play with the application a bit more.

So after duly playing around for a while, I noticed from the comments section on Squix’ page that a couple of people had already added some new features, all of which looked interesting, so off I went to GitHub again and cloned Keith Fowler’s latest and greatest version.  This is where the fun started and my free time went down the plughole (and none of the palaver related below is in any way Keith’s fault, I hasten to add).

I’m using PlatformIO as my build environment (it generally works flawlessly and automatically does neat stuff, like shoehorning everything into memory, or finding your FDTI adapter, without having to be told).  When you need libraries you can just do a word search on, say “DS18B20” and then choose the most suitable looking candidate from the list returned.  Keith’s updated version of the application I was trying to install was looking for “simpleDSTadjust.h”, so I duly typed “simpleDSTadjust” into the library search, got one hit and installed that library.  The next run through produced exactly the same error message as previously, “simpleDSTadjust.h not found”.  Having been bitten once earlier in the morning with a case-mismatch between the #include line and the actual file name (just for refererence, “ArialRoundedMTBold_14.h” as opposed to (ArialRoundedMtBold_14.h”), I went back and scanned the #include and file name with a magnifying glass.  Nope, they’re both the same.  Hmmm….

I quickly looked at the library properties files, library.json and library.properties and discovered a minor typo with the repository URL in the .json file.  A quick check with the spec’ showed that this was a required field, so I corrected it and tried again.  Nope, same error.

Ran the platformio “run” (compile) command again, this time with the -v option.  I got a lot more information on the libraries which it had found, but nothing at all on the missing “simpleDSTadjust.h”.   Next, I went to GitHub and found the repository for simpleDSTadjust.  The most recent changes were to the library.json and library.properties files, but the GitHub diff showed only a single character change in both cases; the version number had changed from 1.0.0 to 1.1.0, unlikely to cause such a problem, I thought.

At this point I was beginning to suspect that maybe there was some sort of bug with PlatformIO that perhaps the length and composition of this particular library’s name was triggering.  On a lets-just-try-it-anyway hunch, I updated my platformio.ini file with a line to change the behaviour of the library dependency finder — lib_ldf_mode = deep+.  That didn’t help at all (so much for hunches!).

Next I removed the simpleDSTadjust library from the PlatformIO local cache (.piolibdeps) using the “lib uninstall” command and then downloaded the GitHub version to the local “lib” directory (normally used for your own, locally created libraries which aren’t available in the global, PlatformIO library system), giving it a different, shorter name.  I  updated both the library .cpp and .h files, as well as the #include lines in the TFT application source, to match the new name.  And …exactly the same.  PlatformIO ignored the newly created library and repeated the boring old “not found” error.  This was starting to get a little tiresome.

Working on the assumption now that the problem lay with the library itself and not, after all, with PlatformIO, I went into the library directory and moved all of the files which seemed to be non-essential into a newly created sub-directory.  The next compile actually worked.  It did fall over on some other errors, but we’d got past simpleDSTadjust.h for the time being.  Okay, what was the actual culprit?  Moving the non-essentials back, one by one, then re-running the compile proved the the library.json file was definitely at fault, but staring at it didn’t yield any obvious clues, so back to the on-line manual pages and the examples to see what a good file should look like (I’ve never knowingly created a .json file, so I definitely classify as a bona-fide novice).  It all looked fairly simple …quoted text, colon delimiters between defined name and data and comma delimiters at the end of data lines, except for the last one.  Okay, squint, squint, squint.  Nope nothing obvious.  Back to the examples — curly braces for multi-field data, comma after the closing curly bracket.  More squinting …and finally an answer; that comma delimiter after the closing curly is missing.  I quickly edited the file to include the errant comma and …Yay!  A working compile.  Finally!

Phew!  A couple of hours of precious free time wasted (but only because I was stupid enough to pursue the issue at hand instead of getting on with the actual project) mainly because there was no error message displayed (or perhaps generated) when parsing of the library.json file failed because of a syntax error.  Anyway, the author of the simpleDSTadjust library (Neptune2)updated the library.json file within a few hours of the issue being raised, so a very big thank you to him/her for that.

Now I suppose that I should buckle down and get back to work on that simple temperature display, now that I’ve proved that the hardware works.  🙂


Another low-power option

I’ve been using the DS3231 RTC module as one means of reducing the consumption of battery-powered ESP8266 sensors.  The idea being to set up an alarm on the DS3231 which will take the (DS3231) interrupt pin low when triggered.  That pin is connected to the gate of a P-channel MOSFET, which functions as a power switch for the battery supply to the ESP8266.  Once powered, the ESP takes a sensor reading, connects to the network and sends the reading and then programs a new alarm into the DS3231, clearing the interrupt and thus turning its own power off.  This actually works very well.  The DS3231 module runs on its own button-cell battery and the ESP on three AA alkaline batteries (fed via a low quiescent current, LDO 3v3 regulator).  The standard set up will run for many months and this can be extended by using the RTC memory as a data store and only initializing the ESP wireless to send on every 10th (or whatever) reading of the sensor.

LowPowerLab's TPL5110 ModuleI recently came across a very similar implementation on the LowPowerLab’s forum, where user “TomWS” published a circuit using the TI TPL5110 “Nano-power system timer” to drive the MOSFET (instead of the DS3231 in my implementation).  The advantages are simplification (the TPL5110 only needs a resistor to set the delay between power-ons, no programming) and a pin saving (the TPL5110 only requires a single GPIO “done” signal from the ESP, as opposed to the two pins required for the i2c bus connection to the DS3231).LowPowerLab's TPL5110 Schematic  The TPL5110’s timing range is a little more restricted than the DS3231, with effective delays between fractions of a second and 2-hours.  Having said that though, that range probably covers the usage requirements of most hobby applications.

The TPL5110 module (which includes the P-channel MOSFET) is available from LowPowerLab’s web site for about $5.  The TPL5110 chip itself is available from Mouser/Digikey, etc for slightly more than a dollar.

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 “broker.hivemq.com”, 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).