Skip to content

Instantly share code, notes, and snippets.

@anecdata
Last active November 4, 2024 20:49
Show Gist options
  • Save anecdata/f46a1d07add5fc60cfbcf42dc7be6528 to your computer and use it in GitHub Desktop.
Save anecdata/f46a1d07add5fc60cfbcf42dc7be6528 to your computer and use it in GitHub Desktop.
CircuitPython example for Espressif ESP-NOW protocol
# SPDX-FileCopyrightText: 2023 anecdata
#
# SPDX-License-Identifier: MIT
import time
import traceback
import supervisor
import os
import rtc
import espnow
import espidf
import wifi
import socketpool
import adafruit_ntp
from sekrets import *
#### ESPNOW Receiver
TZ_DEFAULT = -5
SNDR_CH = 0 # channel 1 (unless connected to an AP or acting as an AP)
def struct_time_to_iso_time():
st = time.localtime()
tz = TZ_DEFAULT
return f"{st[0]:04d}-{st[1]:02d}-{st[2]:02d}T{st[3]:02d}:{st[4]:02d}:{st[5]:02d}{tz:+03}:00"
def connect():
try:
wifi.radio.connect(os.getenv("WIFI_SSID"), os.getenv("WIFI_PASSWORD"), bssid=AP_BSSID) # use AP on channel <> 1
time.sleep(1) # wait for ap_info
print(f"{struct_time_to_iso_time()} ipv4={wifi.radio.ipv4_address} channel={wifi.radio.ap_info.channel} rssi={wifi.radio.ap_info.rssi}")
except ConnectionError as ex:
traceback.print_exception(ex, ex, ex.__traceback__)
def ntp_to_rtc():
wifi.radio.enabled = True
connect()
try:
ntp = adafruit_ntp.NTP(pool, tz_offset=TZ_DEFAULT)
rtc.RTC().datetime = ntp.datetime
print(f"{struct_time_to_iso_time()} RTC time set with NTP time")
except Exception as e:
traceback.print_exception(e, e, e.__traceback__)
wifi.radio.enabled = False # lose the wifi channel
time.sleep(3) # wait for serial
print(f"{'='*25}")
pool = socketpool.SocketPool(wifi.radio)
ntp_to_rtc()
peers = [espnow.Peer(mac=SNDR_MAC, lmk=SNDR_LMK, encrypted=True, channel=SNDR_CH),]
while True:
with espnow.ESPNow() as e:
e.set_pmk(RCVR_PMK)
peers_report = ""
for peer in peers:
e.peers.append(peer)
peers_report += f"mac={peer.mac} lmk={peer.lmk} ch={peer.channel} if={peer.interface} enc={peer.encrypted}\n"
print(f"{'-'*25}\n{struct_time_to_iso_time()} Receiving...", end=" ")
while True:
if e:
try:
packet = e.read()
print(f"{packet}")
break
except ValueError as ex: # Invalid buffer
traceback.print_exception(ex, ex, ex.__traceback__)
supervisor.reload()
break
print(f"send=[{e.send_success} {e.send_failure}] read=[{e.read_success} {e.read_failure}] buf={e.buffer_size} phy={e.phy_rate} peers={peers_report}", end="")
@anecdata
Copy link
Author

anecdata commented Oct 31, 2024

@stanelie
Copy link

Thanks!

@stanelie
Copy link

stanelie commented Nov 4, 2024

How about setting the data rate for long range?
The doc says "espnow.ESPNow(buffer_size: = 526, phy_rate: int = 0), but I don't see what 0 means (1mbps? 56mbps?)
The values in the reference https://docs.espressif.com/projects/esp-idf/en/release-v4.4/esp32/api-reference/network/esp_wifi.html#_CPPv415wifi_phy_rate_t are not integer values, as expected by the Circuitpython library.

@anecdata
Copy link
Author

anecdata commented Nov 4, 2024

@stanelie it's an enumeration, so increasing integer values
https://github.com/espressif/esp-idf/blob/a9d0f22193acdf47a5a4db36832ae7068818962b/components/esp_wifi/include/esp_wifi_types.h#L594
the default is 0 (1Mbps), but you can change it

@stanelie
Copy link

stanelie commented Nov 4, 2024

Thanks. Is there a better place for my questions than this thread?

@stanelie
Copy link

stanelie commented Nov 4, 2024

I've tried all the phy_rate values between 0 and 32, and 16 and up do not work. So, I am unable to select the 31 or 32nd values (lora 250 and lora 500) that I want to enable long range. Where should I file a bug report about this issue?

@anecdata
Copy link
Author

anecdata commented Nov 4, 2024

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment