ESP-Now support for ESP32 (and ESP8266)

All ESP32 boards running MicroPython.
Target audience: MicroPython users with an ESP32 board.
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 » Wed Aug 18, 2021 3:50 am

I seemed to have fewer problems with Rev 3 chips.

I would still try to isolate if it is a deepsleep() issue or not.

For what it might be worth here is my "receiver code":

Code: Select all

import network
from esp import espnow
import utime
import machine
#import ubinascii


#  A WLAN interface must be active to send()/recv()
w0 = network.WLAN(network.STA_IF)
w0.active(True)
mac = w0.config('mac')
print(mac)
#mac = ubinascii.hexlify(w0.config('mac'),':').decode()
#print(mac)

e0 = espnow.ESPNow()
print(e0)

retval = e0.init()

if (retval != None):
    print('init() did NOT work')
    machine.reset()

#peer = b'\xdcO"9(\xfe' #  MAC address of remote septic ESP-01S
peer = b'\x18\xfe4\xde\xea\xf3' #  MAC address of remote test ESP-01S

retval = e0.add_peer(peer)

if (retval != None):
    print('add_peer did NOT work')
    machine.reset()

print('send command')

retval = e0.send(peer, "pump off", True)
#e.send(peer, "pump off", True)
print(retval)

if (retval != True):
    print ('send did NOT work')
    machine.reset()

print('waiting for ACK')

while True:
    msg = e0.irecv()
    if msg:
        return_msg = msg[1].decode('utf-8')
        print(return_msg)

        if (return_msg == 'pump is now off'):
            utime.sleep(5)

            retval = e0.deinit()
            if (retval != None):
                print('deinit() did NOT work')

            w0.active(False) # take-down WiFi

            machine.reset()
maybe there is something in there that is helpful.

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

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

Post by glenn20 » Wed Aug 18, 2021 4:21 am

dhust wrote:
Tue Aug 17, 2021 2:04 pm
My two devices are having issues communicating. It's like the receiver and sender devices aren't in sync. The receiver should be getting a message every 6 or so seconds. Sometimes I'll wait minutes before it starts to receive something. Then the receiver will get a few messages in a row. Then it won't again. Does it matter if one device is an ESP32 and the other is an ESP8266?
In general, it should not, but the code base for the 8266 has had to be squeezed considerably, so it is possible that there may be bugs/issues - and tehre are subtle differences in the API for both.

Looking through your code, several things leap to mind to investigate/debug the problem:
  • Change

    Code: Select all

    e.send(b'msg')
    to

    Code: Select all

    e.send(peer, b'msg')
    This will exercise a slightly different code path which might help uncover a bug in the code (edit: to clarify - I mean a bug in the module code path - not your code ;)).
  • Check/print the return value from e.send(peer, msg). This will return True if the msg has been acknowledged by the peer and False if not.
  • I confess I haven't done extensive testing of the reliability of re-initialisation after wake from deepsleep(). Are you monitoring the sender to check that the wifi initialises correctly after wake from sleep. In particular, it may be more reliable to e.deinit() and w0.active(False) before calling deepsleep(). I would have thought that is not necessary, but it might. It is necessary before lightsleep().
  • On the receiver, change

    Code: Select all

    host, msg = e.irecv()
    to

    Code: Select all

    host, msg = e.irecv(500)
    (or 1000). You should now start to see "No message" appearing - but see if that has an effect on the non-receipt of messages.
This has prompted me to write soome more extensive lightsleep and deepsleep recovery tests - thanks.

Good luck.
Last edited by glenn20 on Wed Aug 18, 2021 12:46 pm, edited 1 time in total.

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

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

Post by glenn20 » Wed Aug 18, 2021 12:15 pm

glenn20 wrote:
Wed Aug 18, 2021 4:21 am
  • I confess I haven't done extensive testing of the reliability of re-initialisation after wake from deepsleep(). Are you monitoring the sender to check that the wifi initialises correctly after wake from sleep. In particular, it may be more reliable to e.deinit() and w0.active(False) before calling deepsleep(). I would have thought that is not necessary, but it might. It is necessary before lightsleep().
Actually, according to https://docs.espressif.com/projects/esp ... modes.html, "Before entering deep sleep or light sleep mode, applications must disable WiFi and BT (bluetooth)...".

So, I'd recommend trying that ;).

I'll add some guidance on espnow and sleep modes to the espnow docs (although it is not espnow specific - the same applies to any use of the wifi or BT and sleep).

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

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

Post by dhust » Wed Aug 18, 2021 8:08 pm

Awesomeness! I think everything is working properly now. Here is what I ended up implementing:
Check/print the return value from e.send(peer, msg). This will return True if the msg has been acknowledged by the peer and False if not.
I forgot about this. Great way to troubleshoot.
In particular, it may be more reliable to e.deinit() and w0.active(False) before calling deepsleep().
Makes sense to do this. I think this is what ended up helping.
host, msg = e.irecv(500)
Another nice way to provide more frequent feedback.
e.send(peer, b'msg')
I initially had this but changed it while troubleshooting. Didn't end up going back to this but I will if I have more devices.
Before entering deep sleep or light sleep mode, applications must disable WiFi and BT (bluetooth)...
Not sure if w0.active(False) disables WiFi. Also, not sure how to disable BT.

Crossing my fingers hoping this will stay working. Thank you guys for the help!

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

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

Post by glenn20 » Thu Aug 19, 2021 8:06 am

dhust wrote:
Wed Aug 18, 2021 8:08 pm
Awesomeness! I think everything is working properly now.
Glad to hear it.
Before entering deep sleep or light sleep mode, applications must disable WiFi and BT (bluetooth)...
Not sure if w0.active(False) disables WiFi. Also, not sure how to disable BT.
w0.active(False) does turn off the wifi radio: it calls the ESP-IDF function esp_wifi_stop() (and w0.active(True) turns on the radio - use these to limit how long the radio is powered in battery sensitive operations). You only need to turn off BT if you have turned it on. Note - if anyone is using both the STA_IF and AP_IF interfaces, you need to turn them both off (even though they share the same radio). There will be some updated docs on this in the next release. I find that I need to document more and more of other parts of the ESP32 operation for ESPNow users (understandably) ;).

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

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

Post by dhust » Thu Aug 19, 2021 7:13 pm

Thank you.

I've been having a bit of an issue with receiving an ESP-Now message and then sending a text to my phone. Both work separately, but not together.

This works fine:

Code: Select all

wifi = network.WLAN(network.STA_IF) # needs to be STA_IF
wifi .active(True)

e = espnow.ESPNow()
e.init()
e.add_peer(mac)

while True:
    host, msg = e.irecv()
    print(msg)
But when I add this

Code: Select all

wifi.connect(ssid, password)
to the last line of the while loop the ESP-Now message prints False. I'm making this connection so that I can text myself. When I was looking around I saw this

Code: Select all

// Set the device as a Station and Soft Access Point simultaneously
WiFi.mode(WIFI_AP_STA);
figuring it would allow me to do both. Not sure if that's true, but I'm not seeing this as an option in MicroPython. I'm not sure how to approach communicating over the wifi for ESP-Now and for texting. Thoughts?

On an added note, when I read:
There are two WiFi interfaces, one for the station (when the ESP8266 connects to a router) and one for the access point (for other devices to connect to the ESP8266).
I'm thinking that I can use STA_IF for texting through the WiFi and then use AP_IF to get communications from another ESP32. It doesn't look like that's the case, unless I'm reading it wrong. Simply changing from network.AP_IF to network.STA_IF allows the message to be received.

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

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

Post by glenn20 » Thu Aug 19, 2021 9:22 pm

dhust wrote:
Thu Aug 19, 2021 7:13 pm
I've been having a bit of an issue with receiving an ESP-Now message and then sending a text to my phone. Both work separately, but not together.

But when I add this

Code: Select all

wifi.connect(ssid, password)
to the last line of the while loop the ESP-Now message prints False. I'm making this connection so that I can text myself. When I was looking around I saw this
wifi.connect() will always use the STA_IF interface to connect to the Access Point and will set the channel of the radio to the channel that the Access Point uses. It may well be that this is not channel 1 (the default channel for the ESP32/8266 radio) and now your device is listening for ESPNow messages on a different channel from the sender. The simplest thing is to set the ESP32/8266 devices to use the same channel as your access point using w0.config(channel=n). Alternatively, you can use e.add_peer() on the sender to set the channel of the receiver (but check the caveats in the docs). Note that add_peer(mac) will register your peer on the current channel (if you don't specify it as an argument) used by the wifi radio, so set the channel before calling add_peer().

There is some general guidance on mixing espnow and wifi on micropython in my espnow docs at:
https://micropython-glenn20.readthedocs ... w-and-wifi

Code: Select all

// Set the device as a Station and Soft Access Point simultaneously
WiFi.mode(WIFI_AP_STA);
figuring it would allow me to do both. Not sure if that's true, but I'm not seeing this as an option in MicroPython. I'm not sure how to approach communicating over the wifi for ESP-Now and for texting. Thoughts?
The micropython network module (ports/esp32/modnetwork.c automatically sets the correct wifi mode according to which interfaces have been enabled. In your case, you are only activating STA_IF interface, so the mode will be set to WIFI_STA automatically.
Last edited by glenn20 on Thu Aug 19, 2021 9:58 pm, edited 1 time in total.

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

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

Post by glenn20 » Thu Aug 19, 2021 9:30 pm

Deleted
Last edited by glenn20 on Thu Aug 19, 2021 9:39 pm, edited 1 time in total.

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

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

Post by glenn20 » Thu Aug 19, 2021 9:34 pm

Deleted.
Last edited by glenn20 on Thu Aug 19, 2021 9:57 pm, edited 1 time in total.

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

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

Post by glenn20 » Thu Aug 19, 2021 9:40 pm

Deleted (something went awry when I editted my post)

Post Reply