MicroPython : ESP-NOW avec ESP32 (un à plusieurs)

MicroPython : ESP-NOW avec ESP32 (un à plusieurs)

Dans ce guide, vous apprendrez à utiliser ESP-NOW pour contrôler plusieurs cartes ESP32 à partir d’un seul contrôleur principal ESP32 (configuration un-à-plusieurs). Pensez-y comme à une télécommande qui envoie des commandes à plusieurs appareils. Nous allons vous montrer comment configurer une carte ESP32 pour contrôler sans fil trois autres cartes à l’aide du protocole de communication ESP-NOW, idéal pour la domotique, les réseaux de capteurs ou les projets impliquant plusieurs appareils IoT.

MicroPython ESP-NOW avec ESP32 contrôle plusieurs cartes, une à plusieurs

Vous utilisez l’IDE Arduino ? Suivez plutôt ce tutoriel : ESP-NOW avec ESP32 : envoyer des données à plusieurs cartes (une à plusieurs).

Conditions préalables – Micrologiciel MicroPython

Pour suivre ce tutoriel, vous devez installer le firmware MicroPython sur vos cartes ESP32 ou ESP8266. Vous avez également besoin d’un IDE pour écrire et télécharger le code sur votre tableau. Nous vous suggérons d’utiliser Thonny IDE :

Nouveau sur MicroPython ? Consultez notre eBook : Programmation MicroPython avec ESP32 et ESP8266 eBook (2e édition)

Présentation d’ESP-NOW

ESP-NOW est un protocole de communication sans fil développé par Espressif qui permet à plusieurs cartes ESP32 ou ESP8266 d’échanger de petites quantités de données sans utiliser le Wi-Fi ou le Bluetooth. ESP-NOW ne nécessite pas de connexion Wi-Fi complète (bien que le contrôleur Wi-Fi doive être activé), ce qui le rend idéal pour les applications à faible consommation et à faible latence telles que les réseaux de capteurs, les télécommandes ou l’échange de données entre cartes.

ESP-MAINTENANT - Logo ESP32

ESP-NOW utilise un modèle de communication sans connexion, ce qui signifie que les appareils peuvent envoyer et recevoir des données sans se connecter à un routeur ni configurer de point d’accès (contrairement à la communication HTTP entre les cartes). Il prend en charge la messagerie unicast (envoi de données à un appareil spécifique à l’aide de son adresse MAC) et de diffusion (envoi de données à tous les appareils à proximité à l’aide d’une adresse MAC de diffusion).

Vous êtes nouveau sur ESP-NOW ? Lisez notre guide de démarrage : MicroPython : ESP-NOW avec ESP32 (Mise en route).

Aperçu du projet

Ce didacticiel montre comment configurer une carte ESP32 en tant que contrôleur principal ESP-NOW qui envoie des commandes à plusieurs cartes ESP32.

Le contrôleur ESP32 envoie des données à plusieurs cartes via le protocole de communication ESP-NOW

Voici un aperçu du fonctionnement du projet :

  • Une carte ESP32 agira comme une carte contrôleur qui enverra des commandes à d’autres cartes ESP32.
  • Le contrôleur sera connecté à trois boutons poussoirs. Chaque bouton contrôle une LED d’une des cartes réceptrices.
  • La carte contrôleur ESP32 envoie des messages à une carte spécifique en se référant à son adresse MAC.
  • Lorsque vous appuyez sur le bouton-poussoir d’une carte particulière, l’état actuel de la LED bascule.
  • Les cartes réceptrices ESP32 écouteront les packages ESP-NOW. Lorsqu’ils recevront un message du contrôleur, ils contrôleront leur LED correspondante en conséquence.

Pièces requises

Pour suivre le projet de ce tutoriel, vous aurez besoin des pièces suivantes :

Vous pouvez utiliser les liens précédents ou vous rendre directement sur MakerAdvisor.com/tools pour trouver toutes les pièces pour vos projets au meilleur prix !

1769104807 675 MicroPython ESP NOW avec ESP32 un a plusieurs

ESP32 : Obtention de l’adresse MAC de la carte

Pour communiquer via ESP-NOW, vous devez connaître l’adresse MAC de vos cartes. Pour obtenir l’adresse MAC de votre carte, vous pouvez copier le code suivant dans Thonny IDE et l’exécuter sur votre carte.

# Rui Santos & Sara Santos - Raspberryme.com
# Complete project details at https://Raspberryme.com/micropython-esp-now-esp32/
 
import network

wlan = network.WLAN(network.STA_IF)
wlan.active(True)

# Get MAC address (returns bytes)
mac = wlan.config('mac')

# Convert to human-readable format
mac_address=":".join('%02x' % b for b in mac)

print("MAC Address:", mac_address)

Afficher le code brut

Après avoir exécuté le code, il doit imprimer l’adresse MAC de la carte sur le shell.

Thonny IDE - Obtenir l'adresse MAC de la carte ESP32 - MicroPython

Obtenez l’adresse MAC de toutes vos cartes.

Par exemple, dans mon cas, j’obtiens :

  • Carte émettrice : 24:0A:C4:31:38:5C
  • Carte réceptrice 1 : DC:B8:15:81:2B:64
  • Carte réceptrice 2 : 30:AE:A4:07:0D:64
  • Carte réceptrice 3 : 30:AE:A4:F6:7D:4C

Préparation de la carte émetteur ESP32

La carte émettrice sera connectée à trois boutons poussoirs. Chaque bouton-poussoir contrôlera une LED d’un ESP32 différent.

Contrôleur ESP32 ESP-NOW avec trois boutons-poussoirs

Câblage du circuit

Commencez par câbler trois boutons-poussoirs à la carte émettrice ESP32. Nous connecterons les boutons-poussoirs aux GPIO 21, 22 et 23. Vous pouvez utiliser n’importe quel autre GPIO approprié (n’oubliez pas de vérifier le brochage de la carte ESP32).

Nous utiliserons les résistances pull-down internes ESP32. Vous n’avez donc pas besoin d’ajouter des résistances au circuit.

ESP32 connecté à trois boutons-poussoirs - schéma de circuit

Contrôleur ESP32 ESP-NOW – Le code de l’expéditeur

Copiez le code suivant dans Thonny IDE.

# Rui Santos & Sara Santos - Raspberryme.com
# Complete project details at https://Raspberryme.com/micropython-esp-now-esp32-one-to-many/

import network
import aioespnow
import asyncio
from machine import Pin

# Initialize Wi-Fi in station mode
sta = network.WLAN(network.STA_IF)
sta.active(True)
sta.disconnect()

# Initialize AIOESPNow
e = aioespnow.AIOESPNow()
try:
    e.active(True)
except OSError as err:
    print("Failed to initialize AIOESPNow:", err)
    raise

# Define pins for pushbuttons
button1_pin = Pin(21, Pin.IN, Pin.PULL_UP)  # Button for Board 1
button2_pin = Pin(22, Pin.IN, Pin.PULL_UP)  # Button for Board 2
button3_pin = Pin(23, Pin.IN, Pin.PULL_UP)  # Button for Board 3

# Define MAC addresses for receiving boards
board1_mac = b'\xff\xff\xff\xff\xff\xff'  # MAC address for Board 1
board2_mac = b'\xff\xff\xff\xff\xff\xff'  # MAC address for Board 2
board3_mac = b'\xff\xff\xff\xff\xff\xff'  # MAC address for Board 3

# Build dictionary with pin and MAC variables
boards = {
    1: {"pin": button1_pin, "mac": board1_mac},
    2: {"pin": button2_pin, "mac": board2_mac},
    3: {"pin": button3_pin, "mac": board3_mac}
}

# Add peers
for board_num, info in boards.items():
    try:
        e.add_peer(info["mac"])
        print(f"Added Board {board_num} peer: {info['mac']}")
    except OSError as err:
        print(f"Failed to add Board {board_num} peer: {err}")
        raise

# Async function to monitor buttons and send toggle commands
async def monitor_buttons(e):
    # Track LED states (True = ON, False = OFF)
    led_states = {1: False, 2: False, 3: False}
    
    while True:
        for board_num, info in boards.items():
            button = info["pin"]
            if button.value() == 0:  # Button pressed (active low)
                led_states[board_num] = not led_states[board_num]  # Toggle LED
                command = "LED_ON" if led_states[board_num] else "LED_OFF"
                if await e.asend(info["mac"], command, sync=True):
                    print(f"Board {board_num}: {command}")
                else:
                    print(f"Board {board_num}: Failed to send")
                await asyncio.sleep(0.3)  # Debounce delay
        
        await asyncio.sleep(0.1)  # Short loop delay

# Main async function
async def main(e):
    await monitor_buttons(e)

# Run the async program
try:
    asyncio.run(main(e))
except KeyboardInterrupt:
    print("Stopping...")
    e.active(False)
    sta.active(False)

Afficher le code brut

Assurez-vous de modifier le code avec les adresses MAC des cartes de vos récepteurs.

Comment fonctionne le code ?

Jetons un coup d’œil rapide au fonctionnement du code. Vous pouvez également passer à la section suivante.

Importation de bibliothèques

Commencez par importer les bibliothèques requises. Nous utilisons la bibliothèque aioespnow pour ESP-NOW, qui est une version asynchrone de la bibliothèque espnow.

import network
import aioespnow
import asyncio
from machine import Pin

Si vous débutez dans la programmation asynchrone, nous vous recommandons de suivre ce guide pour mieux comprendre son fonctionnement : Programmation asynchrone MicroPython ESP32/ESP8266 – Exécuter plusieurs tâches.

Initialisez l’interface Wi-Fi et ESP-NOW

Pour utiliser ESP-NOW, vous devez d’abord initialiser l’interface Wi-Fi.

# Initialize Wi-Fi in station mode
sta = network.WLAN(network.STA_IF)
sta.active(True)
sta.disconnect()

Ensuite, vous pouvez initialiser le protocole de communication ESP-NOW

# Initialize AIOESPNow
e = aioespnow.AIOESPNow()
try:
    e.active(True)
except OSError as err:
    print("Failed to initialize AIOESPNow:", err)
    raise

Définir les boutons-poussoirs

Ensuite, définissez les broches des boutons-poussoirs. Si vous utilisez différents GPIO pour les boutons-poussoirs, modifiez-les en conséquence.

# Define pins for pushbuttons
button1_pin = Pin(21, Pin.IN, Pin.PULL_UP)  # Button for Board 1
button2_pin = Pin(22, Pin.IN, Pin.PULL_UP)  # Button for Board 2
button3_pin = Pin(23, Pin.IN, Pin.PULL_UP)  # Button for Board 3

Adresses MAC des cartes réceptrices

Ajoutez l’adresse MAC des cartes réceptrices dans les lignes suivantes. L’adresse MAC doit être au format octets. Par exemple:

  • 30:AE:A4:F6:7D:4C se transforme en b’\x30\xae\xa4\xf6\x7d\x4c’
# Define MAC addresses for receiving boards
board1_mac = b'\x30\xae\xa4\x07\x0d\x64'  # MAC address for Board 1
board2_mac = b'\x0c\xb8\x15\x81\x2b\x64'  # MAC address for Board 2
board3_mac = b'\x30\xae\xa4\xf6\x7d\x4c'  # MAC address for Board 3

Dictionnaire des planches

Nous créons un dictionnaire pour associer chaque numéro de carte à son bouton poussoir et à son adresse MAC.

# Build dictionary with pin and MAC variables
boards = {
    1: {"pin": button1_pin, "mac": board1_mac},
    2: {"pin": button2_pin, "mac": board2_mac},
    3: {"pin": button3_pin, "mac": board3_mac}
}

Ajouter des pairs

Ensuite, nous ajoutons les cartes réceptrices en tant que pairs.

# Add peers
for board_num, info in boards.items():
    try:
        e.add_peer(info["mac"])
        print(f"Added Board {board_num} peer: {info['mac']}")
    except OSError as err:
        print(f"Failed to add Board {board_num} peer: {err}")
        raise

Surveiller les boutons et envoyer des messages

La fonction monitor_buttons vérifiera l’état de chaque bouton-poussoir et enverra un message à la carte correspondante.

async def monitor_buttons(e):

Tout d’abord, nous créons un autre dictionnaire pour contenir l’état de la LED pour chaque carte.

led_states = {1: False, 2: False, 3: False}

Ensuite, on vérifie si un bouton poussoir a été enfoncé

for board_num, info in boards.items():
    button = info["pin"]
    if button.value() == 0:  # Button pressed (active low)
        led_states[board_num] = not led_states[board_num]  # Toggle LED
        command = "LED_ON" if led_states[board_num] else "LED_OFF"
        if await e.asend(info["mac"], command, sync=True):

Puisque nous utilisons les boutons dans un état actif-bas, lorsque la valeur du bouton-poussoir est 0, cela signifie qu’il a été enfoncé.

if button.value() == 0:  # Button pressed (active low)

Lorsque cela se produit, nous basculons l’état de la LED de la carte dont le bouton a été enfoncé (dans le dictionnaire led_states) et préparons la commande à envoyer via ESP-NOW.

if button.value() == 0:  # Button pressed (active low)
    led_states[board_num] = not led_states[board_num]  # Toggle LED
    command = "LED_ON" if led_states[board_num] else "LED_OFF"

Enfin, nous appelons la méthode asend() sur l’objet espnow e pour envoyer le message à la carte correspondante en faisant référence à son adresse MAC.

if await e.asend(info["mac"], command, sync=True):
      print(f"Board {board_num}: {command}")
else:
     print(f"Board {board_num}: Failed to send")
await asyncio.sleep(0.3)  # Debounce delay

Créer et exécuter la tâche asynchrone

Enfin, nous créons la fonction principale asynchrone et exécutons la tâche asynchrone.

# Main async function
async def main(e):
    await monitor_buttons(e)

# Run the async program
try:
    asyncio.run(main(e))
except KeyboardInterrupt:
    print("Stopping...")
    e.active(False)
    sta.active(False)

Téléchargement du code sur le tableau de l’expéditeur

Après avoir modifié le code avec l’adresse MAC de chaque carte réceptrice, vous pouvez le télécharger sur votre carte.

Dans Thonny IDE, avec une connexion établie avec votre carte, allez dans Fichier > Enregistrer sous > Appareil MicroPython.

Thonny IDE Enregistrer sur un périphérique MicroPython

Enregistrez le code sous le nom main.py, sinon cela ne fonctionnera pas. Lorsque vous nommez un fichier main.py, il s’exécutera automatiquement au redémarrage ou à la réinitialisation de l’ESP32.

Enregistrer main.py sur un périphérique micropython

Après avoir téléchargé le code sur votre carte, réinitialisez la carte en appuyant sur le bouton RST ou en débranchant et en rebranchant l’alimentation. Il commencera à exécuter le code.

Pour le moment, le code ne fonctionnera pas car nous n’avons pas encore préparé les cartes réceptrices.

Préparation des cartes réceptrices

Suivez cette procédure pour chacune de vos cartes réceptrices ESP32. Dans cet exemple, nous utilisons trois cartes réceptrices ESP32, mais vous ne pouvez en utiliser que deux (ou même une seule), voire plus de trois.

Trois cartes ESP32 avec code ESP-NOW pour recevoir des données

Câblage du circuit

Câblez une LED à chacune de vos cartes réceptrices. Nous connectons la LED au GPIO2, mais vous pouvez vous connecter à n’importe quel autre GPIO.

ESP32 avec une LED connectée au GPIO 2

Code du récepteur ESP-NOW

Copiez le code suivant dans Thonny IDE et téléchargez-le sur chacune de vos cartes réceptrices. Ce code écoutera les paquets ESP-NOW et allumera ou éteindra la LED en conséquence.

Important : n’oubliez pas de modifier le code avec l’adresse MAC de la carte émettrice.

# Rui Santos & Sara Santos - Raspberryme.com
# Complete project details at https://Raspberryme.com/micropython-esp-now-esp32-one-to-many/

import network
import aioespnow
import asyncio
from machine import Pin

# Initialize Wi-Fi in station mode
sta = network.WLAN(network.STA_IF)
sta.active(True)
sta.config(channel=1)  # Match sender's channel
sta.disconnect()

# Initialize AIOESPNow
e = aioespnow.AIOESPNow()
try:
    e.active(True)
except OSError as err:
    print("Failed to initialize AIOESPNow:", err)
    raise

# Sender's MAC address
sender_mac = b'\xff\xff\xff\xff\xff\xff'  # You need to replace with actual sender MAC address

# Add sender as peer for more reliability
try:
    e.add_peer(sender_mac)
    print(f"Added sender peer: {sender_mac}")
except OSError as err:
    print(f"Failed to add sender peer: {err}")
    raise

# Initialize LED
led = Pin(2, Pin.OUT)
led.value(0)

# Async function to receive messages and control LED
async def receive_messages(e):
    while True:
        try:
            async for mac, msg in e:
                message = msg.decode()
                print(f"Received from {mac.hex()}: {message}")
                if message == "LED_ON":
                    led.value(1)  # Turn LED on
                    print("LED turned ON")
                elif message == "LED_OFF":
                    led.value(0)  # Turn LED off
                    print("LED turned OFF")
        except OSError as err:
            print("Error:", err)
            await asyncio.sleep(5)

# Main async function
async def main(e):
    await receive_messages(e)

# Run the async program
try:
    asyncio.run(main(e))
except KeyboardInterrupt:
    print("Stopping receiver...")
    led.value(0)  # Turn off LED on exit
    e.active(False)
    sta.active(False)

Afficher le code brut

Comment fonctionne le code ?

Continuez à lire pour découvrir comment fonctionne le code ou passez à la section de démonstration.

Importation de bibliothèques

Commencez par importer les bibliothèques requises.

import network
import aioespnow
import asyncio
from machine import Pin

Initialisez l’interface Wi-Fi et ESP-NOW

Pour utiliser ESP-NOW, vous devez d’abord initialiser l’interface Wi-Fi.

# Initialize Wi-Fi in station mode
sta = network.WLAN(network.STA_IF)
sta.active(True)
sta.config(channel=1)  # Match sender's channel
sta.disconnect()

Ensuite, vous pouvez initialiser le protocole de communication ESP-NOW.

# Initialize AIOESPNow
e = aioespnow.AIOESPNow()
try:
    e.active(True)
except OSError as err:
    print("Failed to initialize AIOESPNow:", err)
    raise

Ajouter l’expéditeur en tant que pair

Ajoutez la carte de l’expéditeur en tant que pair. N’oubliez pas de remplacer par l’adresse MAC réelle de votre expéditeur.

# Sender's MAC address
sender_mac = b'\x24\x0A\xC4\x31\x38\x5C'  # Replace with actual sender MAC

# Add sender as peer for more reliability
try:
    e.add_peer(sender_mac)
    print(f"Added sender peer: {sender_mac}")
except OSError as err:
    print(f"Failed to add sender peer: {err}")
    raise

Initialiser la LED

Initialisez la LED comme sortie sur GPIO 2 et réglez son état initial sur LOW.

# Initialize LED
led = Pin(2, Pin.OUT)
led.value(0)

Recevez des messages ESP-NOW et contrôlez la LED

La fonction asynchrone recevoir_messages() écoutera les messages ESP-NOW.

async def receive_messages(e):
    while True:
        try:
            async for mac, msg in e:
                message = msg.decode()
                print(f"Received from {mac.hex()}: {message}")

Ensuite, il allumera ou éteindra la LED en fonction du message reçu.

if message == "LED_ON":
    led.value(1)  # Turn LED on
    print("LED turned ON")
elif message == "LED_OFF":
    led.value(0)  # Turn LED off
    print("LED turned OFF")

Créer et exécuter la tâche asynchrone

Enfin, nous créons la fonction principale asynchrone et exécutons la tâche asynchrone.

# Main async function
async def main(e):
    await receive_messages(e)

# Run the async program
try:
    asyncio.run(main(e))
except KeyboardInterrupt:
    print("Stopping receiver...")
    led.value(0)  # Turn off LED on exit
    e.active(False)
    sta.active(False)

Téléchargement du code sur les cartes réceptrices

Après avoir modifié le code avec l’adresse MAC de la carte émettrice, vous pouvez télécharger le code fourni sur chacune de vos cartes réceptrices.

Dans Thonny IDE, avec une connexion établie avec votre carte, allez dans Fichier > Enregistrer sous > Appareil MicroPython.

Thonny IDE Enregistrer sur un périphérique MicroPython

Enregistrez le code sous le nom main.py, sinon cela ne fonctionnera pas. Lorsque vous nommez un fichier main.py, il s’exécutera automatiquement au redémarrage ou à la réinitialisation de l’ESP32.

Enregistrer main.py sur un périphérique micropython

Après avoir téléchargé le code sur votre carte, réinitialisez la carte en appuyant sur le bouton RST ou en débranchant et en rebranchant l’alimentation. Il commencera à exécuter le code.

Démonstration

Appuyez sur les boutons poussoirs de la carte émettrice. Chaque bouton fera basculer l’état de la LED pour une carte spécifique. L’émetteur ESP32 fonctionne comme une télécommande pour envoyer des commandes individuelles à chaque carte.

Une carte ESP32 contrôle trois cartes ESP32 via ESP-NOW en appuyant sur un bouton-poussoir pour chaque carte

Vous pouvez jeter un œil à la vidéo suivante pour voir ce projet fonctionner.

Conclusion

Dans ce didacticiel, vous avez appris à envoyer des messages ESP-NOW d’un expéditeur ESP32 à plusieurs cartes. Ce n’est qu’un des nombreux exemples de la façon dont vous pouvez utiliser ESP-NOW dans vos projets IoT et d’automatisation.

Nous espérons que vous avez trouvé ce guide et ce projet utiles. Nous avons d’autres guides ESP-NOW qui pourraient vous plaire :

Si vous souhaitez en savoir plus sur la programmation de l’ESP32 à l’aide du micrologiciel MicroPython, consultez nos ressources :

Plongez dans l’histoire de Raspberry Pi avec cette vidéo :

Youtube video

  • ELEGOO 3PCS Carte de Développement ESP-32 Type-C, 2,4 GHz WiFi + Bluetooth
  • ELEGOO 2PCS ESP-32 Carte de Développement Type-C, 2,4 GHz WiFi + Bluetooth