ESP-Now support for ESP32 (and ESP8266)

All ESP32 boards running MicroPython.
Target audience: MicroPython users with an ESP32 board.
User avatar
glenn20
Posts: 132
Joined: Mon Jun 04, 2018 10:09 am

Re: ESP-Now support for ESP32 (and ESP8266)

Post by glenn20 » Mon Jul 12, 2021 3:32 am

WoutS wrote:
Sun Jul 11, 2021 7:26 pm
Or is there another way to wait for received messages in a non-blocking way?
Thanks!
Yes, you have several options. The more modern way would be to use micropython asyncio via the StreamReader class (assuming you are using ESP32 modules - see the docs). If you are not ready for asyncio, you can set the timeout for recv() to 0 to use non-blocking reads:

Code: Select all

e.config(timeout=0)  # To set the default timeout for recv()/irecv() (ESP32 only)
or

Code: Select all

host, msg = e.irecv(0)
If you choose the non-blocking IO method, you will need to poll by performing the recv()'s in a loop.

You may also prefer to just set the timeout to a smaller number (eg. 500 milliseconds) rather than 0.

Regarding callbacks, micropython does provide a mechanism for scheduling callbacks (and early versions of this driver used that mechanism), however, it is designed for lower-latency servicing of not-too frequent interrupts and the like. The mechanism is easily overflowed by high throughput or rapid bursts of ESPNow traffic (eg. many clients responding to an espnow broadcast) and especially if you have lots of callbacks from multiple sources (eg. hardware interrupts, bluetooth, espnow, etc). So, the current driver instead uses an internal buffer queue and a more traditional udp-like I/O model and is much, much more reliable and performant on a busy module.

User avatar
glenn20
Posts: 132
Joined: Mon Jun 04, 2018 10:09 am

Re: ESP-Now support for ESP32 (and ESP8266)

Post by glenn20 » Mon Jul 12, 2021 4:17 am

dhust wrote:
Sun Jul 11, 2021 11:01 pm
davef wrote:
Sun Jul 11, 2021 9:39 pm
Have you tried just sending to one slave and do you get a message back?
How do you get a message back? Is there a specific callback for ESP-Now using MicroPython?
You get a message back with:

Code: Select all

e.send(peer, 'Hello')
host, msg = e.recv()  # or e.irecv()

dhust
Posts: 40
Joined: Sun Jul 11, 2021 10:59 pm

Re: ESP-Now support for ESP32 (and ESP8266)

Post by dhust » Sat Jul 24, 2021 1:14 pm

If I put two devices into deep sleep, would I be able to have one wake up and send a signal to the other one to wake it up only using esp-now? It seems the only way to get a device in deep sleep to be able to talk to another device is to have at least one device always on and not sleeping. Is that true?

Basically, I have a moisture sensor that needs to tell the solenoid value to turn on. I would like both to be in deep sleep and run only on batteries.

davef
Posts: 811
Joined: Thu Apr 30, 2020 1:03 am
Location: Christchurch, NZ

Re: ESP-Now support for ESP32 (and ESP8266)

Post by davef » Sat Jul 24, 2021 8:37 pm

dhust,

A few things to sort out first. Which rev of ESP32? I read in the errata that there was an issue with random lock-ups when coming out of deep sleep (rev1). I have one ESP32_SPIRAM which I use for development then struggle to get the rev 1 to play-ball. I have played with light_sleep(), would that make enough difference?

Likewise, I have been considering a similar situation as I want to monitor a water tank about 1KM away and it would be nice to only send a signal back say once an hour.

I use ntptime to keep time on my other ESP32 systems. I get a new time once or twice day depending on when I send datalogs. Maybe, you could kick things off with getting NTP time, go to sleep and then have the RTC wake you up at specific times.

The ESP8266's RTC is crude and I had a use a virtual timer clocktick to get it to keep reasonable time over a day or so.

I haven't confirmed yet whether or not the client or the server need to be brought up in a certain order. I just did a test and it appears that the server end needs to be running before the client sends a request.

User avatar
glenn20
Posts: 132
Joined: Mon Jun 04, 2018 10:09 am

Re: ESP-Now support for ESP32 (and ESP8266)

Post by glenn20 » Sun Jul 25, 2021 4:36 am

dhust wrote:
Sat Jul 24, 2021 1:14 pm
If I put two devices into deep sleep, would I be able to have one wake up and send a signal to the other one to wake it up only using esp-now? It seems the only way to get a device in deep sleep to be able to talk to another device is to have at least one device always on and not sleeping. Is that true?
Short answer is yes - the two devices must be on at the same time to exchange messages. You can't wake a device from sleep via it's radio - as the radio is off when asleep.

I have tried two different strategies to manage this with moderate success:
  • The use of the radio drains the battery the most (especially transmission), so have the solenoid device wake perioidically (T1), turn on the radio and listen for messages for some period (T2 << T1). (Battery drain is moderate)
    When the sending device needs to send a message, it turns on the radio and sends repeated alert messages till the client responds. Once synchronised - exchange messages and then go back to sleep.
  • Use a third device connected to AC power as a message broker. (I am working on an espnow proxy to an mqtt broker).
I've abandoned work on option 1 - though it did work if tuned correctly to the needs of the application.

However, it seems that @davef has more solid experience with using devices like this in your use case.

dhust
Posts: 40
Joined: Sun Jul 11, 2021 10:59 pm

Re: ESP-Now support for ESP32 (and ESP8266)

Post by dhust » Sun Jul 25, 2021 6:46 pm

davef wrote:
Sat Jul 24, 2021 8:37 pm
dhust,

A few things to sort out first. Which rev of ESP32? I read in the errata that there was an issue with random lock-ups when coming out of deep sleep (rev1). I have one ESP32_SPIRAM which I use for development then struggle to get the rev 1 to play-ball. I have played with light_sleep(), would that make enough difference?
I'm using a 8266 D1 Mini. Light sleep would drain the battery too much. It sounds like adding clock times and such would be using more battery? Not sure how that all works.

davef
Posts: 811
Joined: Thu Apr 30, 2020 1:03 am
Location: Christchurch, NZ

Re: ESP-Now support for ESP32 (and ESP8266)

Post by davef » Sun Jul 25, 2021 7:36 pm

According to https://docs.micropython.org/en/v1.9.2/ ... rctrl.html it looks like only the RTC is running during deep sleep. Maybe an external RTC could be used to wake the ESP8266 up. Also, you wouldn't need to get the time every day. Getting the time should only take 5-10 seconds so I don't see that impacting battery life much, even if done every day.

If you want some code for getting the time I'll post my getUTC.py and my_ntptime.py

mhepp63
Posts: 8
Joined: Wed Apr 28, 2021 2:17 pm

Re: ESP-Now support for ESP32 (and ESP8266)

Post by mhepp63 » Fri Aug 06, 2021 9:57 pm

glenn20 wrote:
Sun Jul 25, 2021 4:36 am
  • Use a third device connected to AC power as a message broker. (I am working on an espnow proxy to an mqtt broker).
I have done it - I have a receiver/sender, which can be managed via HTTP. It is without documentation now, because it is freshly in production state. How to use it is in file src/lib/app.py and src/templates/index.html:
https://gitlab.com/mhepp63/espnow-gateway/

I am building it for home weather station with potential to use it as central point of home automation it can send messages to peers too. It is build for messages in format for example:

Code: Select all

"outer01;TIME:7205;BATTERY:1789;TEMPH:2500;RAIN:0;PRESS:97910;HUMI:6055;TEMPP:2434;WINDSPD:0;WINDDIR:2"
where "outer01" is sender ID, ";" is delimiter of key:value pairs. It is transformed and stored to JSON, while waiting for pick-up all received messages. Messages are stored in flash and removed when read (each message is read-once).

I will public all parts later, it is still under developement, but gateway is +-stable now...

mhepp63
Posts: 8
Joined: Wed Apr 28, 2021 2:17 pm

Re: ESP-Now support for ESP32 (and ESP8266)

Post by mhepp63 » Fri Aug 06, 2021 10:07 pm

And I found possible issue with lightsleep.

In my sender code:

Code: Select all

chan = 4
rece = b'\xff\xff\xff\xff\xff\xff'

w0 = network.WLAN(network.STA_IF)
w0.active(True)
w0.config(channel=chan)

e = espnow.ESPNow()
e.init()
e.add_peer(rece, None, chan, network.STA_IF)

while True:
    st = utime.ticks_ms()
    message = mk_message()
    sent = e.send(rece, message.encode())
    print("ACT msg:", message, "Sent:", sent)
    st = 6000 - (utime.ticks_ms() - st)
    gc.collect()
    machine.sleep(st)
This code will send only first message and after machine.sleep() messages are not sent - sent is always false. Using utime.sleep is possible, but ESP32 is warm and it makes error in measurements...

Problem is the same even with w0.active(True) etc... after machine.sleep().

davef
Posts: 811
Joined: Thu Apr 30, 2020 1:03 am
Location: Christchurch, NZ

Re: ESP-Now support for ESP32 (and ESP8266)

Post by davef » Fri Aug 06, 2021 10:22 pm

Looking at docs I don't see any reference to machine.sleep() for the ESP32. And to my surprise after using lightsleep() on the ESP8266 I don't see that for the ESP32 either.

Could you point me to the relevant docs?

Also, and maybe related I wanted to use a watchdog timer for my ESP-NOW links and found that the only why to stop the watchdog kicking-in was to repeatedly send the message before the watchdog timeout period. I don't think you can "drop-out" of the while loop.

Look at the top of this page maybe it applies to your situation.

Post Reply