How to enable/use ESP8266 modem sleep on ESP-01?

I have been struggling with building a rain meter application where the rain is detected using a reed switch on a tipping bucket sensor.
The main problem has been the power drain since it must run on batteries. So I have tried the deep-sleep method where the switch activates reset and the sketch will run once and open the WiFi connection and post a "new pulse" message via MQTT and then go to deep sleep.
The wifi connect time on reset is upwards of 5 seconds...
So the pulse interval must be greater than that....

But the start time problem was apparent when there was a rain storm the other week, which caused detector pulse intervals to get down to a few seconds only (it was really pouring)...
Then the operation time to start up from reset and connect to WiFi AP and post the MQTT message took too long and was interrupted by the next reset pulse...
So this is no good to actually detect all pulses.
I need to do this inside loop().

So I have been looking for a way to let the pulse detection live in loop() rather than in setup(), but I must somehow get down the power drain when the device does not need the WiFi.

One possibility is to use what I have found in a document from Espressif called "Modem sleep".
With that I may get down to some battery drain that is OK....
Does not say how low it gets, though.

So how exactly do I enable this mode such that I can have my loop running checking the input from the switch (using GPIO2) and when detected enable WiFi and transfer the data via MQTT and then set it back to the "modem sleep mode"?
And how much will it then use when idling between pulses?

This issue is now the last remaining item for me.

I was going to point you at a document, but you already have it.

comes down to 15mA it states during the sleep mode, that is still significant.

what you could consider is adding another opto-coupler that can disable the LOW pull of the RST pin, (or disables the reed switch by removing power to it) and instead just pulls a GPIO pin down, making sure that at least the whole process is completed before the ESP can be physically reset. I can't quite remember the complete circuit you have at the moment, can you post it again ?

Well not much connected.
I have two buttons, one for reset on RST and one for flash programming on GPIO0 both with 10K pull-ups.
The sense switch is connected in parallel over the RST pushbutton.
Rx/Tx go to connector pins where I can connect my USB/TTL adapter for flash programming. For programming I push the flash button then use the RST to start it into programming mode.

All my code is in setup() which ends with a call to deepsleep.

If you need good battery life, deep sleep is your way to go. You could for example cover half of your bucket to scale down pulse interval.

-or to replace that esp01 with some other board like I recommended long time ago...

Well how about the reed switch circuit powers an Opto-coupler like a PC817, and you use one of the GPIO pins to disable that circuit. On top of that you would have to count any additional pulses that may come in and you can use another GPIO for that.

So after power-up, first you disable the reset, next you enable an interrupt on the counting GPIO, since you want to make sure not to miss any pulses en during WiFi connection. Then once you complete the transmission of the number of pulses, you go back to sleep. The re-enabling of the Reset system should be automatic.

I have a dedicated little board that i use for uploading, since in many cases i use the RX & TX pins as GPIO pins and they serve other purposes. The other thing is of course that i tend to use OTA updates , which is an option which is more practical, and faster. Of course that won't work while the unit is in sleep mode, but anyway in the scenario i was depicting, most likely you will need at least the RX pin, most likely as a pulse counting pin, since it's the only available pin which can be pulled LOW at boot, without affecting the boot mode,

Or add an ATtiny13 to do the counting and transmit the information to the ESP-01 periodically, either at a number of pulses or at a time interval. Personally i would go for that option, for reasons of reliability.

Love that !! Low tech, definitely looking into, but of course it may rain even more.

Yeah, I know, but if I remember well the original setup was something like: vacation on cottage, no tools, no additional components, just esp01 , battery, sensor and computer.... :wink:

Well, I've been once back home and retrieved some tools and parts so I could modify the circuit a bit. And tomorrow I am returning home again over the day.
The big problem is that I had envisioned a powered system with 5V wired to the device (with a regulator to get to 3V3), but that turned out to be not possible unless I drilled holes through the house wall where it has to be located, which I do not want to do....
But, is it possible that a standard phone charger can be plugged into an outdoors 230VAC outlet without electricity problems in case of rain?
I.e. are they weather proofed?
I do have one such outlet available on an outhouse...

Yes, and it says the following:

So, in Arduino/PlatformIO how do you execute that call?
Is that implemented in some helper function?

No, but neither your esp01 is "waterproof". Somehow you need to protect them.
Why don't you just replace your esp01 with any board that have internal wake up capability?
Or add Attiny13 like Deva_Rishi proposed?

Well, I do have an enclosure for the battery plus ESP01 board, which is weatherproof. So what I was asking is really about the power supply itself. But since they have USB-A connectors they cannot be weatherproof. I have to look for a power supply with a fixed cable that I can use.
If so all the issues connected to the battery usage is moot...

Now that means I will be putting the detection code inside loop() and letting it continue running waiting for the pulse to arrive not via the RST trigger but an ordinary read operation of the switch input.

In such a case the WiFi must be set to low power usage until the pulse arrives and it needs to be reported. (Unless with a power supply)

Hence the question about the Modem-Sleep operation and how to make it get there. Is it so simple that a single delay(1) inside loop() will initialize Modem-Sleep?

And I still need to figure out if the power goes down enough for the batteries to last...

Check This (first hit on Google)

That is the challenge. For the battery powered version an ATtiny13 would be the easiest. It has swSerial TX. I you let the Attiny decide whether to wake the ESP-01 up, wait for a ready signal and transmit something. Pretty straight forward solution. You will need an ATtiny and an ISP programmer of some kind.

So put your PSU in that enclosure. Outdoor extension cords are waterproof.
I think you have plenty of solutions here, just pick one and move on.

No, it's built in.

I guess you are referring to my question:

Just for clarity in the thread....

Follow-up:
If I only connect to WiFi when there is data to send and then when done I immediately disconnect (WiFi.disconnect()), will the power usage drop and if so to what level?
Is it then going to be less than using the "modem sleep" function?

And when connecting when there is new data, will that be quicker than the original connect (i.e. are the connection metadata cached inside the WiFi object)?
I have not found any WiFi.reconnect() in the documentation even though I have read about such a function elsewhere...

That is because it's not related to this part. WiFi.reconnect() is intended for when there is a device connected to the ESP when it acts as an Access Point. You then try to connect the ESP to a network in Station mode as well, once this is successful, you call WiFI.reconnect() to reconnect the the device that was connected to the AP. It has nothing to do with your current situation. WiFi.disconnect() is used to disconnect the ESP from a network, so a network scan can be performed.

So from the link i posted earlier.

Auto Light Sleep

Behavior:
After an idle timeout of 10 seconds the WiFi hardware will be shut down. It wakes up every <100 ms * Access Point DTIM interval> to check for incoming data. Furthermore while the program is running delay() the system clock will be shut down too.

Note: If the WiFi connection is not configured or not reachable, the chip will not sleep at all.

Note: Auto Light Sleep will not happen if there are no delay() or only delay(0) calls in the code.

Consumption:
If Wifi is idle, about 70 mA until timeout, then about 2 mA.
When to use:
Recommended power state if you need Wifi connectivity.

Because of the halted system clock some peripherals might not work in this mode, use Auto Modem Sleep in those cases.

extern "C" {
  #include "user_interface.h"
}
void setup() {
  wifi_set_sleep_type(LIGHT_SLEEP_T);
}

And if i understand correctly the ESP will sleep for the period of time that you call delay() and run using about 2mA, that would be great, still more than with an ATtiny controlling it but really not bad.
Now you should use a pin change interrupt to monitor the bucket i think, because during delay() not code gets executed. This requires testing. It's all in theory, how it works out practically i don't know.

Is it acceptable for you to have an indoor ESP32 to run 24/7 ?
If you use the ESP-NOW-protocol it takes 1.5 seconds from switching power on and send an ESP-NOW-message.

Another option is to use an ESP32-board that is optimised for deep-sleep-mode to draw
only 15 µA. I have these boards and measured the current which was even below (13.5 µA)

How about laying a flat cable through a window to go from inside to outside
and then go into a small box where you go in with the cable in a rain-protected way?

No these standdard wall-plugs are not sealed against rain !

If you mount some kind af extra-housing around your outhouse 230V-outlet
and manage to seal it 150% against rain. This would work.

Otherwise use such a power-supply
sealed 230V side, sealed 12V-side.
https://www.leds-com.de/lc-ss-324-12w-led-netzteil-fuer-stecksystem-dop-stecker-12v-dc-schwarz-ip67.html

protecting against rain for years requires a minimum of professionality of the equipment.

Well, I already have a proof-of-concept set up using an indoors Raspberry Pi Zero wired to the rain gauge through the window. But wiring for that purpose through the window means that the meter cannot be placed where I want it to be permanently.
Right now I am leaning towards using that RPiZero packaged into a weatherproof box and using power from the outdoors outlet. That will surely be a lot quicker than having to deal with minimizing power usage in order to use batteries with an ESP-01.
But I cannot place the meter anywhere then...

It would be interesting OTOH to know how low one can get power-wise on an ESP-01 by these means:

  • Use fixed IP and DNS addresses for WiFi config to bypass DHCP on the router
  • Start WiFi using the AccessPoint's MAC as the BSSID parameter
  • Put a delay(1) into loop() so that the ModemSleep will be invoked
  • Shut down WiFi as soon as the message has been sent (maybe not this but rely on the ModemSleep instead?)

If the idling power use then will be such that batteries give a good enough life then it might be worth a shot.

Have you looked at the following
esp8266-low_power_solutions_en_0.pdf (509.1 KB)