Rummys Blog An world of endless Monday

Monday, 8 October, 2018

An IoT Mousetrap Part 2

Filed under: ESP,ESP32,World of Warcraft — Andrew.Rowbottom @ 11:35 am

The Mousetrap code has gone through several iterations, this iteration Number 2  has changed the code quite a lot..

The aim of this iteration was to significantly reduce the “ON” time from 3seconds to reduce the consumed watts in this phase.


I have switched from connecting to WiFi (about 3 seconds on time!) to using espNow sending to a “receiver” permanently connected to my Raspberry Pi, this is to reduce the “On” time during the regular status updated. I’ll try to post some information about using espNow in another post.


The “On” time is now reported as approx 300ms (mainly due to the huge number of status messages I send), well down from the roughly 3 seconds connecting to WiFi and sending using MQTT/HTTPS takes.

Unfortunately this has not made a huge difference to the overall battery life which is still running at around 3 months for a fully charged “600mAh” LiFePo4.

Further investigation is showing 2 major current draws:

  1. the LDO at approx 70µA
  2. the pullup/down current approx 70µA

Iteration #3 will look at how to reduce this .. until I un-solder the LDO Voltage-Regulator I’m limited to removing the pull-up/pull-down current. There are a few options:

  1. switch from using the internal pullup/down to an external resistor
  2. use the wakestub and poll the switch/mousetrap state regularly but not too frequently
  3. use the ULP and poll using that.

An IoT Mousetrap

Filed under: ESP,ESP32 — Andrew.Rowbottom @ 11:23 am
NOTE: this has been sat waiting to post for many months. I am posting it because I have updates incoming.


IoT! Who needs a mousetrap on the internet! Turns out I do.

We occasionally have some mice visiting our cupboards, so we tucked a mousetrap in a dark corner of a cupboard.

But the old adage “out of sight out of mind” really applies to us! And, after checking daily for a week only to find nothing we got lazy and started checking only when we remembered. Predictably one day we found a particularly smelly little corpse! Finally a potential use for those ESP boards I’ve got lying around!

Thus is born yet another IoT mousetrap!


  • Mousetrap
  • ESPea32
  • A replacement LDO voltage regulator
  • A bit of Soldering skill to replace the LDO
  • Edge Connector
  • Wire
  • Tin Foil salvaged from a tea-light
  • Battery Box
  • Internet

Modding the trap.

My mouse trap comes in three parts a white top and a base and a red “tongue” which is the lever that triggers the top part.

When its armed the top is tilted “backwards” and makes contact with the lever.

To wire it up for IoT all I needed to do was to put a contact on the top part and and one on the tongue, and then detect when the two are (or aren’t) in contact.

For the contacts I have used the tin-foil cup from a tea light, originally I used cooking foil, but it proved too thin, the foil cup on a tea-light is thick enough to hold its shape and still easy to trim with scissors.

The top contact is cut to fit neatly onto the top section. I left a couple of tabs of foil to fold over and tuck under the metal spring. I shove a piece of wire under the spring to complete the connection between the ESP and the top contact.

The bottom contact is nothing like as tidy, it’s a strip of foil, soldered at one end, and placed lightly over the tongue so it makes contact with the upper plate when the trap is armed. A bit of tape at one end stops it moving around too much without interfering with the action.


Using an ESP32ea (any ESP32 should do) I wire one plate to GND, and the other one to a GPIO, it doesn’t matter which way around, the voltages are low and it’s only “contact” that is important.

The GPIO is set to “INPUT_PULLUP”, so when the two plates are in contact it is pulled “LOW”, and when separated it goes “HIGH”.

The ESP is put into Deep Sleep (to conserve battery), set to wakeup (esp_sleep_enable_ext0_wakeup) when the GPIO goes into the opposite of what it currently is (ESP32 feature) It will wake up when the trap is closed, or when I open it ready for the next mouse.

When the ESP wakes up (either GPIO state change, or Timer), it checks the wakeup cause, and if the GPIO state is different from what it was when it went to sleep, it sends a whole bunch of messages.

I have a timer wakeup so I can sample the battery and send a “battery needs charging” message.


Modding the ESPea32 for low deep-sleep current

I only have a couple of esp32 boards, several cheap ESPea32’s and a more expensive FireBeetle-32. The firebeetle, although it has much better deep sleep current draw as supplied is slightly too long to fit in an AA battery box, so I’m using an ESPes32.

The ESPea32, though nice, is not really good for running off a battery in deep sleep.

The CP2104 seems to be correctly wired so that it is only powered when the USB is connected, something I checked on the schematic before I bought it.

But the voltage regulator is a bog standard AMS1117 with a quiescent current draw in the order of several mA, far too much for a deep-sleep battery powered device. Fortunately it’s a nice large (for SMD) SOT-233 package than can be reasonably easily un-soldered and replaced with a much more efficient device. Once that is done my ESPea32 now draws under 0.2mA in deep sleep, a 100 times improvement, though a “naked” esp32 can draw even less. NOTE: the LDO draws approx 70­µA

Headers / Terminals

I didn’t use standard headers for this project, instead I’ve used 2.54mm screw terminal blocks. This is the first project I’ve done this way, and so far I’m liking it! The wires don’t come loose as easily, the overall height (8.5mm, 11.5mm including pins) remains small enough to fit in the battery box. I can squeeze 2 wires into one terminal (for example GND to battery + a wire to the mousetrap), reducing the component count.

I did think about using the supplied PCB headers and dupont jumper wires, but the overall height is way too large to fit in the box. A standard PCB header is about 11mm overall, including through hole pins. The jumper wire pins add an extra 14mm onto that . And then the wire has to be bent. Lets call the overall height 25mm. An AA battery is only 14mm in diameter.

Wiring up the Mousetrap

My mousetrap is not your traditional wire one, which complicates things a little. Its a plastic module, so it needs some sort of conductive layer applying. I originally used cooking foil, but its thin, tears easy, doesn’t solder well and looks really horrible. The current version uses tin-foil taken from a “tea-light” which is thick enough to retain it’s shape with minimal gluing.

One piece is folded around the top, with a “tag” slid under the spring. Also slid under the spring is one of the “detector” wires.

Another piece is a lightly bent strip placed over the lever, and stuck to the bottom of the trap, a “detector” wire is soldered onto this strip.

Hardware choices


I have a stock of LiFePo4 batteries lying around, they’re not your usual LiIon batteries, they have a lower voltage, between 3.6 and 2.8v with a long flat stable period at 3.2v. A perfect voltage range for powering ESP devices directly without needing a voltage regulator. They’re less prone to catching fire, though I doubt they’re 100% safe in that regards – certainly you can short circuit them, and 10A even at 3.2v can cause a fire in thin wires.

In theory this means I should be able to remove the Voltage Regulator from the circuit, and if I had a supply of “naked” ESP32, that’s the path I’d have gone down.


I like these boards, they’re not ideal for this kind of project by a long shot, but they’re not bad. I managed to snarf some cheaply, and they fit tidily into my switched 4x AA battery box. They also seem to have a “correct” implementation of the USB/UART which reduces battery drain. Unfortunately they use the horrible LMS1117 in a comparatively large SOT-233 that has to be replaced or unsoldered if you want low deep sleep battery life. Perfectly you would unsolder it completely but then programming via Arduino would be a pain, unless you add a jumper.

My ideal board would look pretty much like the espea32 have a disableable/bypassable Voltage Regulator to remove quiescent current drain when powered by a LiFePo4. And had a Gnd pin immediately alongside the 3v3 connector .. perhaps a layout like 5v,GND,3v3 (or a second GND). And had an ADC pin connected to a voltage divider (and also 3v3 via a breakable PCB wire)… yes I know that would lose an ADC channel, but you’d gain a battery meter!

I’m actually a bit 50/50 about a LIPO connector/Charger, they’re extra cost, and you have to check carefully to see if they’ll fit in a cheapo project box.. 4xAA switched boxes are dirt cheap 🙂 !


Setting up the hardware

Break the dividers in the battery box so there’s room for the board and 1 battery.
Solder in the 3 screw connector so it covers 5v, Gnd, and a GPIO. I’d rather have used 3v3 direct, but it’s not besides the GND connector. Screw in the battery connectors, and the 2 detector wires.
Job done.. no extra components required


This isn’t a traditional “looping” arduino program, it does all of its work in setup, and goes to Deep Sleep before it enters the loop.

It will
Store the boot count in RTC memory, not strictly needed, but “tidy”.
Store the last state of the GPIO in RTC Memory, so it can tell if something has changed between wake-ups.
Store whether it successfully sent the notifications (in case there’s a WiFi or internet connectivity issue) [Distributed Computing Fallacy: The network is reliable]
Sample the battery voltage, so I can get low battery alerts.

Set the ADC to input (it’s input only anyway)
Set the GPIO to INPUT_PULLUP so it goes high unless it’s being pulled to ground by the mousetrap wiring.
Read the wakeup Cause
Read the GPIO state
Read the ADC
Set the deep sleep trigger to wake if the GPIO goes to the opposite of its current state.
Set the deep sleep to wakeup in 30 minutes in case the GPIO doesn’t trigger or it fails to send.

Decide if a status message should be sent, this will be sent if
it’s first boot (PREVIOUS GPIO level is -1).
the GPIO level is different from what it was last time it was checked.
the message didn’t get sent successfully last time.

Store the GPIO State for the next wakeup.


Current consumption in deep sleep is approx 0.12mA, NOTE: I *did* replace the abhorrent AMS1117 with a much more efficient LDO. I think that having WiFi connectivity enabled at all raises the deep sleep current by about 0.04mA, but I guess that’s something I’ll have to investigate further. Forgetting to turn off WiFi before going into deep-sleep [WiFi.disconnect(true /*means wifiOff*/)] changes the deep sleep current by a LOT more I measured 1.33mA!

Powered by WordPress