Battery powered ESP-01 smart switch

No, I haven’t looked at all into RF443, thank you for the recommendation. I will still continue experimenting with the ESP-8266 however, as I have some understanding of the platform, already the parts, and it’s generally fun. And if people have been able to have them run for months on end on batteries, I should be able to do it too.

Out of the gate, there are some obvious improvements I could make to turn this experiment into something more useful:

  • Don’t wake up for 20 seconds, the ESP probably needs way less time to connect to MQTT and check the topic before going back to sleep
  • Make sure to use fully charged batteries
  • Understand why the ESP stays on for more than a minute at a time randomly when waking up and make sure it stops doing that
  • Implement a better deep sleep during the night

I will continue toying with it and report here. Thanks for all the suggestions and support!

Sorry to come late to this discussion, and to do a quick read through.
I have been trying to get my head around deep_sleep on an ESP32-S3 - but know only that ESP01 or ESP8266 are much more limited.
A few thoughts:

  • You want to turn your book nook light on from Home Assistant, but it can then take up to 10 minutes for the ESP to connect and turn the light on. Probably not a winner for WAF (Wife Acceptance Factor) :wink:
  • Connecting to MQTT can take a variable time. First it has to connect to Wi-fi … which can be affected by signal strength, interference, other packets on the same radio frequency (not just on your SSID).
  • Since each sleep is a power-off, on waking the ESP has to establish a new Wi-fi connection … which uses a fair chunk of power (as Spiro mentioned) … especially if there was an issue.
  • A standard relay needs the control pin to be powered on all the time the relay is on. If you want the ESP to sleep, the ESP will power off and the relay turns off. Consider a latching relay instead.
  • You could certainly use a larger battery pack; or consider Li-Po battery. I also had your concerns, but understand the problems with Li-Po batteries catching fire are due to (a) using the wrong type of battery charger and/or (b) letting them overheat over 60°C. There are lots of everyday household devices (including your USB powerbank) these days which use rechargeable Li-Po batteries without problems.

I have done a couple of searches for latching switches, but almost all the results are automotive or industrial components. Are you aware of any breakout boards suitable for hobbyists like me whose eyesight and soldering are lousy ?

My guess is that they were programming the ESP chip in C++ directly; and not using ESPHome. In ESPHome there are several priority levels available in the on_boot: section which could be useful … and I personally count number of wakeups in a global variable as Karosm mentioned - but i’m not so worried about the amount of flash on my ESP32. I haven’t seen any ESPHome function to write to flash or RTC RAM.

Here is an example of one that can handle more current.
https://www.digikey.com/en/products/detail/omron-electronics-inc-emc-div/G5QK-1A-HR-HA-VH-DC3/24814062

You would need some breadboard and the ability to solder and a driver circuit for the two relay coils. There are some with a single coil, which just switch on/off/on (so possible to get out of sync).

1 Like

Hi everyone,

I’m back after a long hiatus, still determined to see this idea through. I reworked some details, but didn’t change the overall approach.

After reading this blog article, I decided to charge my 3 AA NiMh batteries to the max, even if the combined 4.2V given by the pack is over the documented limit of 3.6V for the ESP8266 in the datasheet. I figure that someone else has been running their device at this voltage with no problem, at worst I destroy mine and lose $1. Doing away with figuring out voltage regulation saves me some headaches right now and also helps improve overall battery life.

I’m still trying to use ESPHome, because I like the convenience of it, but I might switch to programming it directly in C in the future if I’m not satisfied.

I have had some success with the following configuration which I am providing as a reference:

substitutions:
  name: esphome-web-abcdef
  friendly_name: test

esphome:
  name: ${name}
  friendly_name: ${friendly_name}
  min_version: 2024.6.0
  name_add_mac_suffix: false
  project:
    name: esphome.web
    version: dev

esp8266:
  board: esp01_1m

logger:

ota:
  - platform: esphome

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  fast_connect: true
  manual_ip:
    static_ip: 192.168.1.51
    gateway: 192.168.1.1
    subnet: 255.255.255.0

output:
  - platform: gpio
    pin:
      number: 2
      mode: output
    id: LED

deep_sleep:
  id: deep_sleep_1
  sleep_duration: 600s
  run_duration: 10s

mqtt:
  broker: 192.168.1.165
  username: !secret mqtt_user
  password: !secret mqtt_password
  discover_ip: false
  discovery: false
  log_topic: null
#  on_connect:
#    then:
#      - wait_until:
#          mqtt.connected:
#      - mqtt.publish:
#          topic: "test-topic-publish"
#          payload: !lambda |-
#            return std::string("Msg: ") + std::to_string(os_random() % 10000);
#      - output.turn_off: LED
#      - delay: 200ms
#      - deep_sleep.enter: deep_sleep_1
  on_message:
    - topic: test-topic-consume
      qos: 0
      then:
        - logger.log:
            format: "Received payload: %s"
            args: [ 'x.c_str()' ]
        - output.turn_off: LED
        - delay: 50ms
        - output.turn_on: LED
        - delay: 50ms
        - output.turn_off: LED
        - delay: 50ms
        - output.turn_on: LED
        - delay: 50ms
        - output.turn_off: LED
        - delay: 50ms
        - output.turn_on: LED
        - delay: 50ms
        - output.turn_off: LED
        - delay: 50ms
        - output.turn_on: LED
        - delay: 50ms
        - output.turn_off: LED
        - deep_sleep.enter: deep_sleep_1

I am planning to further strip down the config to remove unnecessary modules such as ota: and logger:, before running another endurance test.

I also took some measurements with my Zoyi ZT219 multimeter and I have been surprised by the results. Indeed, when the device is on, it seems to be drawing on average 70mA at ~4V (I can’t see the spikes, transient currents might be much higher), but when it’s in deep sleep, it seems to be drawing 150uA. That last figure really surprised me, as the datasheet indicates 20uA, which is 7 times lower. I do have a few resistors and a capacitor on the board to allow to program the ESP8266 using serial, but I don’t know if they can explain this discrepancy. And anyway, I think most of those are required in a real circuit to avoid floating GPIOs.

Oh, and one other thing. Now, instead of waiting 20 seconds in awake mode as my test back in 2024 was doing, I am now going to deep sleep as soon as I have checked the MQTT topic. Of course, that’s a best case scenario, where the smart switch is expected to stay off, but that should give me an upper-bound for the autonomy. From measuring the time it stays awake (from the time the LED turns on), it seems to be able to boot up, connect to WiFi and read from MQTT in just over 3 seconds. That should also be a big boost to autonomy, as it is at least 6 times faster than my initial test.

I will run the endurance test next, and I’ll report back my results. I hope to make it at least to 2 weeks, using the 2500mAh Duracell AAs.

Getting low power is very hard.

4V/100uA = 40K ohm so a single resistor could be causing your excessive current draw.

I purchased, but haven’t measured yet, Fire beetle boards, since they are known to work well for low power needs.

That’s a super interesting forum thread and a fascinating article that was linked (https://diyi0t.com/reduce-the-esp32-power-consumption/). Thanks a lot for sharing that. Long story short, I’m going to buy some RT9080-33GJ5, as their characteristics are impressive and seem to be a great fit for my use case.

I charged my AA batteries overnight and decided to do one last test measurement this morning. The results utterly baffled me. Indeed, now instead of 150uA during deep sleep, it seemed to start around 250uA and climb up to 350uA, with current slowly increasing during the sleep duration.

I could not figure why the figures were so different from my test of the day before, until I had the idea to test with only 2 AA batteries. This is not a configuration I would consider running normally, as the 2.7-2.8V max voltage drops quickly below what is required by the controller, but I wanted to make sure that my running of the ESP-8266 so far outside the specs (4.2V instead of 3.6V max) was not the cause of the high deep-sleep current. And indeed, it seems to be related. At 2.7V, I measured around 17uA during deep sleep.

So something rather interesting, and quite unexpected to me, seems to be happening inside the controller during deep sleep when running it way above its max voltage, and it’s leading to much higher idle power consumption.

I could of course leave it at that, accept the higher power consumption while the batteries are fully charged, knowing that it would normalize after a while. And maybe I’ll do that in the beginning. But since I have found out about RT9080-33GJ5 and their 4uA quiescent current and 0.3V voltage drop, I think this will be a perfect solution for my current (pun intended) conundrum.

Get some lifepo4 cells, they have the whole voltage range from full to empty within esp specs.

After reading and watching some content on LifePo4, I’m not against the idea of using them, but I don’t really know where to start. I saw some cells on Aliexpress, but they come in various sizes and usually don’t seem to be protected. From what I gathered, you need to worry about 2 things:

  • charging at constant current first (0.5 or 1C), then constant voltage when you reach 3.6V
  • protect the cell against deep discharge when using it

So it sounds like you need a dedicated charger that you can trust not to set fire to the cell or kill it, as well as a low-voltage protection device for when the battery is in circuit.

Do you have any recommendation for getting started with that?

Lifepo4 batteries are like more common li-ion /lipo batteries. You can find protected/non-protected, low/high discharge rate etc…
Generally they are more stable (safer) than more common li-ion cells.
Esp would turn off before battery voltage goes below safe level, so even unprotected cell could be an option if you take care of it.
Have a look at Soshine cells, they have many protected ones at reasonable price.

I’d consider using espruino. Could sleep mostly (very low power) then scan for BLE advertisements every x seconds. If it detects an advertisement signalling lights on it could turn on MOSFET (not sure power requirements of your lights).
Advertisment could come from and esphome connected esp32 somewhere with a power supply. Think this would get you much better latency for less power, especially since it’s never having to connect and auth to wifi, connect to mqtt etc it just scans then sleeps on repeat.
I was working on something similar for a battery powered smart airfreshner but ended up just butchering a fingerbot and made it ZigBee controlled instead (also an option to toggle a switch on and off)

Edit:

5uA deep sleep. 12ma to scan.
Doing a 50ms scan every 5-10seconds is getting you into years of battery life (not including the lights themselves)

And a 0.5 to 1% chance of actually listening when you tell it to turn on. Could be solved by spamming the ON for 5-10s to make it 100%, but also means up to 5-10s delay before it turns on.

I know I noticed a 100ms delay for light turn on and find 500ms and over intolerable. If that long delay is acceptable to you, it could be a good solution.

How are you arriving at 0.5-1% chance of it turning on?
Say 20ms advertising interval (since that side would be permanently powered we don’t have to be cautious although probably over kill) each 3 packets across 3 channels for say 10 seconds, these are not perfectly aligned. In any given 50ms window in which the controller happens to wake there’ll be and average of 7.5packets and we only need 1.

As for latency he was working on a 10minute sleep cycle so even 10 seconds would be 60x faster than whats proposed.

That is not what I said. I said listening 50ms/5-10s is the math. To increase the chances of turning on, you need to keep sending (spamming) the turn on message till it eventually gets heard.

That’s an interesting idea. Well not the part about using Javascript on a microcontroller (what an unholy alliance :sweat_smile: ), but the idea of using a central command&control device plugged on wall-power to serve as relay for commands to the battery operated devices and use a more efficient communication method. I will definitely give it some thoughts. I’m also planning to give ZigBee a try later with a different device, but at the moment I’m focusing on the ESP-8266.

Thanks for link and ideas, it’s very much appreciated!

I think the consumption calculation works differently for the ESP-8266. Deep-sleep is around 20uA instead of 5, and I am not sure what it looks like when it’s only scanning for BLE and not turning on WiFi, but likely higher than 12ma. I’ll make a small sketch to test it.

Indeed, for this application I don’t have a strong latency requirement, and 10 minutes is perfectly acceptable. Of course, anything lower is even better, and I have to say that your proposal is elegant in that regard.

If I understood @tom101 correctly, they are indeed suggesting to spam the message for 10s. I am not sure what consequence it has on other Bluetooth devices nearby during that time.

Oh, and meanwhile the ESPHome deep sleep experiment on the NiMh batteries is still running. We’re almost at 7 days, so we’ll soon know if it beats the 8 days of the previous experiment, but I’m hopeful, the approach is much better this time.

Edit: I had forgotten that ESP8266 don’t have Bluetooth. Thankfully I have a handful of ESP-12F devices I can test that on.

Tiny update, the MQTT ESP8266 AA battery experiment is still ongoing (day 15).

I received the LDO (RT9080-33GJ5) and mosfet (IRLML2502) I ordered, but I think I was a bit too optimistic about my ability to reliably solder SOT-23-5 packages. I managed it, but it took a few attempts and was a total pita. So I’ll be ordering some SOT23 breakout boards to simplify my life.

I’ll leave you with a picture of my handiwork, as a cautionary tale to whomever would have the same delusions about hand-soldering 3mm-wide components :sweat_smile:

2 Likes

When I was young at least I was able to see them… :cry:

1 Like

I wanted to share this video that I found while researching low power modes for the ESP8266.

I am not sure how I missed it before, possibly you already know about it. I think it’s way above my skills at the moment (using custom SDKs and tweaking them), but what I found really interesting was the part about how short the wake-up time can be. It seems like the official SDK (and probably ESPHome) is quite inefficient and it’s possible to drastically reduce the time it takes for the ESP to wake up, connect to WiFi and send a message. Currently with ESPHome, my tests show that it takes between 3s and 6s on average. In the video, the author talks about 100ms for the same operations.

Assuming you can indeed reduce the awake time by a factor of 30 (and assuming you don’t need the features that were removed from the SDK), that would considerably extend battery life for a project like mine. At this point, we’re probably talking about years of autonomy. My back of the envelope calculations give 26 months (0.0166% duty cycle at 50mA on / 20uA off with a guesstimated self discharge rate of 3% / month). At this point, the self-discharge rate becomes the biggest limitation, which I guess is to be expected.

I will keep that in a corner of my mind, in case at some point I become knowledgeable and skilled enough to implement something like that.

A short update on the project. I received the SOT23 breakout bords and soldered my LDO (RT9080-33GJ5) and logic-level mosfet (IRLML2502). It is soooo much easier, even if I didn’t do a perfect job of it.

I’ve also tested both components together on a breadboard and everything works, so that’s one less roadblock for this project.


(ignore the Arduino, I’m just using it to provide a stable 5V to the LDO for the test)

I am not sure if I have wrong expectations or if I’m measuring incorrectly however, because the LDO current draw reads 82uA even when there’s no load on VOUT, while I would have expected 2uA (its rated quiescent current) according to its datasheet. I just put my multimeter in series between VCC and VIN, but maybe that’s not the right way to measure this current. Let me know if you have an idea of what’s wrong here.

In other news, my ESPHome battery experiment is still running. It’s been 46 days so far and I can still see the ESP-01S wake up every 10-ish minutes. I haven’t measured the battery’s voltage because I don’t want to disrupt the experiment, but I’ll keep an eye on it and will report when it stops working.

It depends on your multimeter, not all are good to read uA range.

I’m using the same Zoyi ZT219 as before. It seemed to be able to accurately measure 17uA deep-sleep current for the ESP-01S, so I assumed it would be fine with measuring 2-5uA too.

As to why I am measuring 82uA instead of 2-5uA, I can see the following possibilities:

  • The “fake” RT9080-33GJ5 I ordered from Aliexpress are just not as good as the real components
  • My multimeter is not good enough to measure such a small current, as you suggested
  • My approach for measuring such a small current is incorrect
  • I damaged the LTO when soldering it (though it still seems to reliably output 3.3V)
  • I was unlucky and the individual component I tested is just not up to specs.
  • There’s an unexpected “high” resistance somewhere in my circuit, maybe from the breakout board or the way I soldered it
  • I misread / misinterpreted the datasheet and it only consumes 2uA in some specific use circumstances which I am not respecting

I mean, it’s not the end of the world, 0.08mA quiescent current is still low enough to be perfectly usable, I’m just a bit surprised.