Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentes Révision précédente Prochaine révision | Révision précédente Prochaine révisionLes deux révisions suivantes | ||
howto:arduino-esp:esp-now [2021/10/09 15:09] – guillaume | howto:arduino-esp:esp-now [2021/10/12 12:52] – guillaume | ||
---|---|---|---|
Ligne 2: | Ligne 2: | ||
ESP-NOW est un protocole d' | ESP-NOW est un protocole d' | ||
- | |||
- | Ce qui va suivre s' | ||
===== Le protocole ESP-NOW ===== | ===== Le protocole ESP-NOW ===== | ||
- | Tel qu'il est décrit sur le site d' | + | Tel qu'il est décrit sur le site d' |
- | Il est possible de réaliser un schéma | + | Il est possible de réaliser un schéma |
Il est possible de chiffrer les communications, | Il est possible de chiffrer les communications, | ||
- | Il n'est possible d' | + | Il n'est possible d' |
===== Connaître l' | ===== Connaître l' | ||
Ligne 19: | Ligne 17: | ||
Il est possible de changer de manière logicielle l' | Il est possible de changer de manière logicielle l' | ||
- | Uploader | + | Téléverser |
< | < | ||
Ligne 34: | Ligne 32: | ||
} | } | ||
</ | </ | ||
+ | |||
+ | Cette étape manuelle permettra d' | ||
===== Principe de communication ===== | ===== Principe de communication ===== | ||
- | Pour commencer, nous allons simplement envoyer des informations d'un ESP vers un autre. Par commodité, nous les appellerons " | + | Pour commencer, nous allons simplement envoyer des informations d'un ESP vers un autre. Par commodité, nous les appellerons |
**Côté émetteur: | **Côté émetteur: | ||
* Initialiser ESP-NOW. | * Initialiser ESP-NOW. | ||
- | * Enregistrer une fonction de rappel, qui sera exécutée quant un message est envoyé. Cela nous permettra de vérifier la bonne livraison | + | * Enregistrer une fonction de rappel, qui sera exécutée quant un message est envoyé. Cela nous permettra de vérifier la bonne transmission |
* On ajoute l' | * On ajoute l' | ||
* On envoie le message. | * On envoie le message. | ||
Ligne 50: | Ligne 50: | ||
* Dans cette fonction de rappel, on sauve le contenu du message dans une variable pour en faire quelque chose. | * Dans cette fonction de rappel, on sauve le contenu du message dans une variable pour en faire quelque chose. | ||
- | ===== Résumé des fonctions les plus utiles ===== | + | À Chaque étape listée ci-dessus va correspondre une fonction spécifique à l' |
- | **esp_now_init()** | + | **esp_now_init()** |
**esp_now_add_peer()** On appelle cette fonction pour appairer un ESP, on passe son adresse MAC en argument.\\ | **esp_now_add_peer()** On appelle cette fonction pour appairer un ESP, on passe son adresse MAC en argument.\\ | ||
**esp_now_send()** Envoie des données avec ESP-NOW.\\ | **esp_now_send()** Envoie des données avec ESP-NOW.\\ | ||
Ligne 60: | Ligne 60: | ||
===== Code de l' | ===== Code de l' | ||
- | Ci-dessous, le code tel que proposé par Rui Santos, de Random Nerd Tutorials: | + | Ci-dessous, le code commenté: |
< | < | ||
- | /* | + | // Reference technique: |
- | Rui Santos | + | |
- | Complete project details at https://RandomNerdTutorials.com/esp-now-esp32-arduino-ide/ | + | |
- | + | ||
- | Permission is hereby granted, free of charge, to any person obtaining a copy | + | |
- | of this software and associated documentation files. | + | |
- | + | ||
- | The above copyright notice and this permission notice shall be included in all | + | |
- | copies or substantial portions of the Software. | + | |
- | */ | + | |
+ | // Inclure les librairies | ||
#include < | #include < | ||
#include < | #include < | ||
- | // REPLACE WITH YOUR RECEIVER | + | // Stockage de l' |
- | uint8_t | + | uint8_t |
- | // Structure example to send data | + | // La variable qui sera envoyée au récepteur (nous générerons une valeur aléatoire pour l' |
- | // Must match the receiver structure | + | float maValeurEnvoyee; |
- | typedef struct struct_message { | + | |
- | char a[32]; | + | |
- | int b; | + | |
- | | + | |
- | bool d; | + | |
- | } struct_message; | + | |
- | // Create a struct_message called myData | + | // La fonction de rappel qui nous assurera de la bonne livraison du message |
- | struct_message myData; | + | void quand_donnees_Envoyees(const uint8_t *mac_addr, esp_now_send_status_t status) { |
- | + | Serial.print(" | |
- | // callback when data is sent | + | Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Succès" : "Échec"); |
- | void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) { | + | |
- | Serial.print(" | + | |
- | Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail"); | + | |
} | } | ||
+ | |||
+ | // Une variable qui servira à stocker les réglages concernant le récepteur | ||
+ | esp_now_peer_info_t infosRecepteur; | ||
+ | |||
void setup() { | void setup() { | ||
- | // Init Serial Monitor | + | // On initie la comm série à 115200 Bauds |
Serial.begin(115200); | Serial.begin(115200); | ||
- | // Set device as a Wi-Fi Station | + | // On démarre le Wifi en mode Station |
WiFi.mode(WIFI_STA); | WiFi.mode(WIFI_STA); | ||
- | // Init ESP-NOW | + | // Puis on initialise |
if (esp_now_init() != ESP_OK) { | if (esp_now_init() != ESP_OK) { | ||
- | Serial.println(" | + | Serial.println(" |
return; | return; | ||
} | } | ||
- | // Once ESPNow is successfully Init, we will register for Send CB to | + | // Si ESP-NOW a coorectement démarré, il est temps d' |
- | // get the status of Trasnmitted packet | + | esp_now_register_send_cb(quand_donnees_Envoyees); |
- | esp_now_register_send_cb(OnDataSent); | + | |
| | ||
- | // Register peer | + | // Tout est prêt pour l' |
- | esp_now_peer_info_t peerInfo; | + | memcpy(infosRecepteur.peer_addr, |
- | memcpy(peerInfo.peer_addr, | + | |
- | peerInfo.channel = 0; | + | |
- | peerInfo.encrypt = false; | + | |
| | ||
- | // Add peer | + | // On définit un canal (0 utilisera automatiquement le même canal que celui utilisé par le wifi) |
- | if (esp_now_add_peer(& | + | infosRecepteur.channel = 0; |
- | Serial.println(" | + | |
+ | // On ne chiffre pas les échanges | ||
+ | infosRecepteur.encrypt = false; | ||
+ | |||
+ | // Appairage | ||
+ | if (esp_now_add_peer(& | ||
+ | Serial.println(" | ||
return; | return; | ||
} | } | ||
Ligne 129: | Ligne 118: | ||
void loop() { | void loop() { | ||
- | // Set values to send | ||
- | strcpy(myData.a, | ||
- | myData.b = random(1, | ||
- | myData.c = 1.2; | ||
- | myData.d = false; | ||
| | ||
- | // Send message | + | // On définit la valeur de la variable à envoyer à l'aide d'un générateur aléatoire |
- | esp_err_t | + | maValeurEnvoyee = random(1, |
+ | |||
+ | // On envoie le message | ||
+ | esp_err_t | ||
- | if (result | + | if (resultat |
- | Serial.println(" | + | Serial.println(" |
} | } | ||
else { | else { | ||
- | Serial.println(" | + | Serial.println(" |
} | } | ||
- | | + | |
+ | // On effectue cette opération toutes les secondes | ||
+ | | ||
} | } | ||
</ | </ | ||
- | Quelques explications: | + | ===== Code du récepteur ===== |
+ | |||
+ | Voici le code du récepteur, commenté: | ||
- | D' | ||
< | < | ||
+ | // Inclure les librairies | ||
#include < | #include < | ||
#include < | #include < | ||
- | </ | ||
- | Ensuite, | + | // La variable qui sera envoyée au récepteur (nous générerons |
- | < | + | float maValeurRecue; |
- | uint8_t broadcastAddress[] = {0x30, 0xAE, 0xA4, 0x07, 0x0D, 0x64}; | + | |
- | </ | + | |
- | Pensez évidemment à remplacer l' | + | |
- | Ensuite, il faut créer une structure qui contiendra les données envoyées. Elle s' | + | // La fonction de rappel qui nous assurera |
- | < | + | void quand_donnees_Recues(const uint8_t * mac, const uint8_t *data_reception, |
- | typedef struct struct_message { | + | memcpy(& |
- | char a[32]; | + | Serial.print(" |
- | int b; | + | Serial.println(taille); |
- | float c; | + | Serial.print("valeur reçue: "); |
- | bool d; | + | Serial.println(maValeurRecue); |
- | } struct_message; | + | Serial.println(); |
- | </code> | + | |
- | + | ||
- | On créé ensuite une variable de type *struct_message* et que l'on appelera *myData*. Cette variable servira à stocker... des variables, celles à envoyer. | + | |
- | < | + | |
- | struct_message myData; | + | |
- | </code> | + | |
- | + | ||
- | Enfin, nous allons définir notre fonction de rappel, qui sera exécutée automatiquement lorsqu' | + | |
- | < | + | |
- | void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) { | + | |
- | Serial.print(" | + | |
- | Serial.println(status == ESP_NOW_SEND_SUCCESS ? " | + | |
} | } | ||
- | </code> | + | |
+ | void setup() { | ||
+ | | ||
+ | Serial.begin(115200); | ||
+ | |||
+ | // On démarre le Wifi en mode Station | ||
+ | WiFi.mode(WIFI_STA); | ||
- | Viens maintenant le moment de créer notre fonction *setup()*, où, après avoir initialisé la communication série avec *Serial.begin(115200)*, nous allons allumer le wifi de l'ESP, puis initialiser | + | // Puis on initialise ESP-NOW |
+ | if (esp_now_init() != ESP_OK) { | ||
+ | | ||
+ | return; | ||
+ | } | ||
- | < | + | // Si ESP-NOW a corectement démarré, il est temps d' |
- | WiFi.mode(WIFI_STA); | + | |
- | if (esp_now_init() != ESP_OK) { | + | |
- | | + | |
- | | + | |
} | } | ||
- | </ | + | |
- | + | void loop() { | |
- | On enregistre ensuite la fonction de rappel, créée précédemment: | + | |
- | + | ||
- | < | + | |
- | esp_now_register_send_cb(OnDataSent); | + | |
- | </ | + | |
- | + | ||
- | Nous devons ensuite appairer notre émetteur avec son récepteur, en définissant son adresse MAC: | + | |
- | < | + | |
- | //Register peer | + | |
- | esp_now_peer_info_t peerInfo; | + | |
- | memcpy(peerInfo.peer_addr, | + | |
- | peerInfo.channel = 0; | + | |
- | peerInfo.encrypt = false; | + | |
- | + | ||
- | //Add peer | + | |
- | if (esp_now_add_peer(& | + | |
- | Serial.println(" | + | |
- | | + | |
- | } | + | |
- | </ | + | |
- | + | ||
- | Enfin, la boucle *loop()* va envoyer un message toutes les deux secondes, contenant des valeurs arbitraires, | + | |
- | + | ||
- | D' | + | |
- | < | + | |
- | strcpy(myData.a, | + | |
- | myData.b = random(1, | + | |
- | myData.c = 1.2; | + | |
- | myData.d = false; | + | |
- | </ | + | |
- | + | ||
- | Pour mémoire, myData est une structure. Nous assignons donc nos valeurs, aux membres qui sont de différents types. Pour en savoir un peu plus sur l' | + | |
- | + | ||
- | < | + | |
- | esp_err_t result = esp_now_send(broadcastAddress, | + | |
- | </ | + | |
- | + | ||
- | On peut vérifier que le message a bien été envoyé: | + | |
- | + | ||
- | < | + | |
- | if (result == ESP_OK) { | + | |
- | | + | |
- | } | + | |
- | else { | + | |
- | Serial.println(" | + | |
} | } | ||
</ | </ | ||
- | The loop() is executed every 2000 milliseconds (2 seconds). | + | ===== Tester et aller plus loin ===== |
- | delay(2000); | + | Lorsque vous regarderez les console série des deux ESP, vous constaterez que les messages sont bien expédiés, bien reçus et leur contenu correctement interprété côté récepteur. Les différentes sources trouvées sur le net parlent d'une portée en extérieur supérieur à 200 mètres, avec les deux antennes pointant l'une vers l' |
+ | Nous vous renvoyons aux exemples disponibles dans la bibliothèque Arduino pour aller plus loin ! | ||