Skip to content
This repository has been archived by the owner on Sep 16, 2024. It is now read-only.

Add espnow #483

Open
wants to merge 23 commits into
base: Dev
Choose a base branch
from
Open

Add espnow #483

wants to merge 23 commits into from

Conversation

rodgergr
Copy link

@rodgergr rodgergr commented Oct 5, 2020

Added espnow class to Pycom code based on earlier work done by Nick Moore and shawwwn for generic micropython.
Main changes involved adopting the Pycom approach to callbacks using mp_irq_queue_interrupt() in the ISR routine to route the data to an appropriate queue handler and converted to be a Class.
The proper object oriented (Class) version of espnow is in mods/ , but an earlier more primitive version has been left in the esp32 root directory for information only and should be removed before merging.
TODO: detection of wifi status at line 253 of espnow is not implemented yet and could be improved by someone with greater familiarity of the wifi code.

Copy link
Contributor

@geza-pycom geza-pycom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have started to check your change, many thanks for the contribution ! Please check my comments and questions.


STATIC mp_obj_t espnow_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {

mp_obj_espnow_t *self = m_new_obj(mp_obj_espnow_t);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better if this class would be "singleton", like e.g. CoAp module. As I understand instantiating again this class would result that esp_now is re-initialized which may ruin the already ongoing former instances.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK - I agree - perhaps like this??

// A static pointer to the espnow singleton
STATIC mp_obj_espnow_t *espnow_singleton = NULL;

STATIC mp_obj_t espnow_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {

    if (espnow_singleton != NULL) {
        return espnow_singleton;
    } 

    mp_obj_espnow_t *self = m_new_obj(mp_obj_espnow_t);
    self->base.type = type;
    self->number = 0;
    
    ESPNOW_EXCEPTIONS(esp_now_init());  
    ESPNOW_EXCEPTIONS(esp_now_register_recv_cb(recv_cb));
    ESPNOW_EXCEPTIONS(esp_now_register_send_cb(send_cb));

    espnow_singleton = self;

    return MP_OBJ_FROM_PTR(self);
}

l

if (encrypt) _get_bytes(key, ESP_NOW_KEY_LEN, peer.lmk);
if (re_add) {
// workaround for calling esp_now_mod_peer() to
// change encryption status will crash the system
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you know why does it cause crash ?

// this workaround enables ESP32 to send from whatever IF that is
// active
// if_id == wifi_mode - 1
#define IS_IF_AVAILABLE(mode, if_id) ({ (mode & (if_id+1)) != 0; })
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really see the purpose of these 2 macros, I think it would just enough to check whether the WLAN is initialized or not. Does it matter whether the mode is STA or AP ?

// The variable has been changed to not static to make it visble outside the wlan module.
// TODO - change to public call

//extern bool wifi_started;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please if not needed remove these lines.

if (addr == mp_const_none) {
// send to all
esp_now_peer_info_t peer;
esp_err_t e = esp_now_fetch_peer(true, &peer);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, wouldn't it be enough to call esp_now_send() with NULL as peer_addr? As far I understand in that case it sends out the packet to all available peers.

@geza-pycom
Copy link
Contributor

@rodgergr : thanks for the contribution, esp-now module will be part of a future release.

@rodgergr
Copy link
Author

rodgergr commented Jan 26, 2021 via email

@geza-pycom
Copy link
Contributor

@rodgergr : yes please append it here and then we can check it and decide what to do. By default I think it should be kept simple, what is the problem with the callbacks?

@rodgergr
Copy link
Author

@geza-pycom The following are the key changes with the enhanced version of ESPNow. The ability to use ESPNow inside of an asyncio environment would be most beneficial. Callbacks are still used internally, but no longer exposed.

Ring buffers in esp32/ringbuffer.[ch] for robust IO.
Allocate the ESPNow singleton dynamically (protect bufs from gc).

New methods:

  • recv() to read incoming messages (instead of callbacks).
  • irecv() for allocation-free read of incoming messages.
  • Stream IO support: read(), write() and poll through ioctl(). This
    can be used to support asyncio use of espnow.
  • Also added read1() and readinto1().
  • Add support for iteration on ESPNow object for alloc-free read.
  • config(): set tx and rx buf sizes and read timeout
  • stats(): Returns transfer stats: (tx_packets, tx_packet_responses, rx_packets, lost_rx_packets).
  • add_peer(mac[,lmk[,channel[,ifidx[,encrypt]]]]): Add peer info
  • get_peer(mac): Return peer info: (mac,lmk,channel,ifidx,encrypt)
  • mod_peer(mac, ...) to change peer info parameters.
  • get_peers(): to return all peer info tuples.

@rodgergr
Copy link
Author

@geza-pycom I have now merged in the latest changes from the micropython version by glenn20 and this substantially improves the performance and stability of espnow. I have not been able to squash the commits very well, but the key files can be found in esp32/mod and are espnow.c, ringbuffer.c and ringbuffer.h. I also added espnow error codes in esp32/mp_pycom_err.h. Initial tests show that the espnow methods successfully send and receive espnow packets as expected. Please advise next steps.

@livius2
Copy link

livius2 commented May 4, 2021

Hi
this pull request should have bigger priority. As for "ESP now" connectionless communication, no AP is required.
It is really simple to use, and it work on quite good ranges.
Thank you @rodgergr for this pull request.

@geza-pycom
Copy link
Contributor

Hello!
Espnow support has been added to a development release with version 1.20.3.b3, however the implementation has been changed compared to this PR (including changes on API level as well).
Code can be found here: https://github.com/pycom/pycom-micropython-sigfox/blob/master_idf_v4.1/esp32/mods/modespnow.c

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants