ESP-Now support for ESP32 (and ESP8266)

All ESP32 boards running MicroPython.
Target audience: MicroPython users with an ESP32 board.
mhepp63
Posts: 8
Joined: Wed Apr 28, 2021 2:17 pm

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

Post by mhepp63 » Thu Apr 29, 2021 11:03 am

glenn20 wrote:
Thu Apr 29, 2021 2:33 am
Thanks for posting this @mhepp63 - I have found some very "interesting" quirks when investigating this issue :roll:
Cool! I am happy to see that helped ;)
TL/DR: When using AP and STA together, the AP will always change channel to that of the STA (See "Attention" note 3 at https://docs.espressif.com/projects/esp ... i_config_t). That is, your AP is running on channel 4, not channel 11 as you expect. You can verify this with w0.scan() on your sender node.

w1.config('channel') will also report the incorrect channel - adding to the confusion (I have fixed that in forthcoming commit - see below).
This explains a lot. I will do some testings in this way. But I have one point - When sender uses STA_IF with e.add_peer(peer, None, 11, network.STA_IF) and receiver AP_IF (STA_IF is not used!), w1.config(channel=11) with e.add_peer(peer, None, 11, network.STA_IF) - message is not received, when remove w1.config(channel=11), it works:
  • Sender (broadcasting messages, better if receiver is changing):

    Code: Select all

    message='Hello dear peer'
    e = espnow.ESPNow()
    e.init()
    w0 = network.WLAN(network.STA_IF)
    w0.active(True)
    reciever = b'\xFF\xFF\xFF\xFF\xFF\xFF'
    e.add_peer(reciever, None, 11, network.STA_IF)
    e.send(reciever, message.encode())
    
  • Receiver:

    Code: Select all

    w1 = network.WLAN(network.AP_IF)
    w1.active(True)
    w1.config(hidden=True)
    # w1.config(channel=11)             <-- this breaks receiving messages
    
    peers = ["fc:f5:c4:56:09:68", "a0:20:a6:16:59:15", "5c:cf:7f:0e:6c:61", "84:0d:8e:3b:87:38"]
    for peer in peers:
        peer = bytes([int(x, 16) for x in peer.split(':')])
        e.add_peer(peer, None, 11, network.AP_IF)
    
    print('Receiving A...')
    while True:
        msg = e.irecv()
        if msg:
            print(msg)
            if msg[1] == b'end':
                break
    
  • Setting the pmk on it's own does nothing...
OK, I will read documentation again, I don't need encrypted messages for now... I probably forgot some details...
Interestingly, your "Sender" code did not work for me at all. (It does contain typos, so it seems to be an almost copy of the actual code you are running):
It is possible, this previous posted code is simplified and I probably forgot something. New posted code is working... For example, original code uses MAC in "normal" form and convert them to bytecode, various options are in dict for easier configuration of multiple senders etc, as you can see in receiver code...
  • On e.send(), I would get an ESP_ERR_ESPNOW_ARG exception and the Espressif stack would print:

    Code: Select all

    E (6613) ESPNOW: Peer channel is not equal to the home channel, send fail!
    It seems that at some point Espressif started enforcing this restriction in an update to the IDF (since I originally tested this behaviour last year with IDF3).
...
Hohoho! This is story like from some CIA file, thanks for your work. I was looking for your latest commit earlier today, I will build FW with them and try... Btw, I am building micropython with latest esp-idf, so this can cause some problems too (I use git repo and forgot switch to some stable release). If you are using 4.0.2, I will switch to this version.
Once again - thanks for uncovering this changed and very inconvenient behaviour!!!!
You are welcome ;)

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

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

Post by mhepp63 » Thu Apr 29, 2021 9:57 pm

Hi,

I have an update - yes, whole problem was in channels settings - old version did not supported channel change for STA_IF - that means all devices was sending on channel 1. It does not matter what is set in add_peer. And as your latest fix, I can change channel for STA_IF, so when I changed all channels to 4 (my wifi is on this channel) I am receiving messages and I have receiver connected to WiFi!

ESP32 is awesome piece of HW, but sometime is very confusing and you must read documentation very carefully...

Thank you very much for your work and help. If you want to, I can help you with some tests...

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 May 19, 2021 1:27 am

Hi glenn20,

Just tried out the latest images for both the ESP8266 (1M) and the ESP32. I have put together a simple monitoring link (water tank level monitoring) and started range testing. Between two ESP32-WROOM-32Ds with their built-in PCB antennas I can do 100mtrs plus. Even with a metal garage in the path I can still just get a connection.

I really like the way if you lose the link it keeps on trying to re-establish.

Has anyone done any range testing? I have some ESP-07s that I can put 10dB gain patch antennas on so looking forward to see what distance that will cover.

Thanks again for the work you have done with this.

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 May 19, 2021 3:34 am

Hi @davef,

Thanks for the successful application report. That's good news. Long range hasn't been my principal motivation, but I have seen it suggested that you could try enabling 802.11LR (long range) and that may help with range (network.wlan(if).config(protocol=network.MODE_LR)). Also - don't use broadcasts over long range due to re-transmission issues. I haven't tried any of that, so I have no idea if it will actually help with espnow. I do remember a report of up to 1.5km range with a low-gain external antenna. The max-tx-power config option may also be helpful.

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 » Thu May 20, 2021 4:54 am

Hi glenn20,

Thanks for the MODE_LR hint. Very little about it, but found this:
https://docs.espressif.com/projects/esp ... /wifi.html
Glad as I am using ESP32s, so having the 2 to 2.5 times range improvement just might let me use the on-board PCB antennas.

max-tx-power is digging in a bit too deep for me!

Tested the link using ESP8266s (ESP-01S boards) and 200mtrs obstructed path even with one unit lying on the ground. Looking hopeful for a 1km obstructed path using 10dB gain patch antennas.

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 May 22, 2021 12:43 am

When setting up a simple link I think it would be handy if the local (receiving) unit would keep listening forever. I imagine there is limit on the timeout parameter.

Any suggestion on how to invoke a machine.reset() or a "re-start the program" function before or when the timeout is exceeded, rather than just freezing-up?

Thanks

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 May 22, 2021 4:08 am

Thought I would try:
(network.wlan(if).config(protocol=network.MODE_LR))
as:

Code: Select all

w0 = network.WLAN(network.STA_IF)
w0.config(protocol=network.MODE_LR)
the odd thing is runs once then on a re-boot it complains.

Code: Select all

RuntimeError: Wifi Unknown Error 0x0102
According to the docs the parameter name protocol is not supported for the ESP32.

I think my problem is that I don't understand what:

Code: Select all

network.wlan(if).config
means.

Thanks

WoutS
Posts: 1
Joined: Sun Jul 11, 2021 7:08 pm

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

Post by WoutS » Sun Jul 11, 2021 7:26 pm

Hi,

I am trying to make a two way communication system with one master and multiple slaves using ESP-Now and micropython. From a master I send messages to muliple slaves and wait for a response to react to again. I don't know when the response is sent and from which slave it will come. To my current understanding the e.recv() code blocks the esp and thus is not able to send messages. Very simple example below which combines the sender and receiver code from https://micropython-glenn20.readthedocs ... spnow.html

I want this code to send messages periodically and be able to receive messages and print them.

Code: Select all

import network
from esp import espnow
from time import sleep

# A WLAN interface must be active to send()/recv()
w0 = network.WLAN(network.STA_IF)  # Or network.AP_IF
w0.active(True)

e = espnow.ESPNow()
e.init()
peer = b'\x94\xB9\x7E\xE5\xC3\xEC'
e.add_peer(peer)

light1 = 1

e.send(peer,"Starting...",False)       # Send to all peers
while True:
    light1 = not light1
    e.send(peer,str(light1),False)
    print("message sent")
    sleep(0.5)
    host, msg = e.recv()     # Available on ESP32 and ESP8266
    print("receive")
    if msg:             # msg == None if timeout in irecv()
        print(host, msg)
        if host==peer:
            print('msg from peer')

        
This code halts at

Code: Select all

host, msg = e.recv()
until the timout runs out. Is it possible to use a receive callback function like in the c++ ESP-now library as below?

Code: Select all

esp_now_register_recv_cb()
Or is there another way to wait for received messages in a non-blocking way?
Thanks!

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 11, 2021 9:39 pm

Have you tried just sending to one slave and do you get a message back?

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

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

Post by dhust » 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?

Post Reply