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:30] – 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 21: | 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 36: | 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 52: | 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 62: | 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(" | ||
+ | Serial.println(status == ESP_NOW_SEND_SUCCESS ? " | ||
+ | } | ||
+ | |||
+ | // Une variable qui servira à stocker les réglages concernant le récepteur | ||
+ | esp_now_peer_info_t infosRecepteur; | ||
- | // callback when data is sent | ||
- | void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) { | ||
- | Serial.print(" | ||
- | Serial.println(status == ESP_NOW_SEND_SUCCESS ? " | ||
- | } | ||
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 131: | 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(" |
} | } | ||
- | delay(2000); | ||
- | } | ||
- | </ | ||
- | Quelques explications: | + | |
- | + | | |
- | D' | + | |
- | < | + | |
- | #include < | + | |
- | #include < | + | |
- | </code> | + | |
- | + | ||
- | Ensuite, nous stockons dans une variable l' | + | |
- | < | + | |
- | uint8_t broadcastAddress[] = {0x30, 0xAE, 0xA4, 0x07, 0x0D, 0x64}; | + | |
- | </code> | + | |
- | Pensez évidemment à remplacer l' | + | |
- | + | ||
- | Ensuite, il faut créer une structure qui contiendra | + | |
- | < | + | |
- | typedef struct struct_message { | + | |
- | char a[32]; | + | |
- | int b; | + | |
- | float c; | + | |
- | bool d; | + | |
- | } struct_message; | + | |
- | </ | + | |
- | + | ||
- | 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; | + | |
- | </ | + | |
- | + | ||
- | 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(" | + | |
- | | + | |
} | } | ||
</ | </ | ||
- | |||
- | Viens maintenant le moment de créer notre fonction *setup()*, où, après avoir initialisé la communication série avec *Serial.begin(115200)*, | ||
- | |||
- | < | ||
- | WiFi.mode(WIFI_STA); | ||
- | if (esp_now_init() != ESP_OK) { | ||
- | Serial.println(" | ||
- | return; | ||
- | } | ||
- | </ | ||
- | |||
- | 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(" | ||
- | return; | ||
- | } | ||
- | </ | ||
- | |||
- | 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) { | ||
- | Serial.println(" | ||
- | } | ||
- | else { | ||
- | Serial.println(" | ||
- | } | ||
- | </ | ||
- | |||
- | The loop() is executed every 2000 milliseconds (2 seconds). | ||
- | |||
- | delay(2000); | ||
===== Code du récepteur ===== | ===== Code du récepteur ===== | ||
- | Voici le programme à uploader dans l'ESP qui servira de récepteur. | + | Voici le code du récepteur, commenté: |
< | < | ||
- | /* | + | // Inclure les librairies |
- | Rui Santos | + | |
- | Complete project details at https:// | + | |
- | + | ||
- | 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. | + | |
- | */ | + | |
#include < | #include < | ||
#include < | #include < | ||
- | // Structure example to receive data | + | // La variable qui sera envoyée au récepteur (nous générerons une valeur aléatoire pour l' |
- | // Must match the sender structure | + | float maValeurRecue; |
- | typedef struct struct_message { | + | |
- | char a[32]; | + | |
- | int b; | + | |
- | | + | |
- | bool d; | + | |
- | } struct_message; | + | |
- | + | ||
- | // Create a struct_message called myData | + | |
- | struct_message myData; | + | |
- | // callback function that will be executed when data is received | + | // La fonction de rappel qui nous assurera de la bonne livraison du message |
- | void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) { | + | void quand_donnees_Recues(const uint8_t * mac, const uint8_t *data_reception, int taille) { |
- | memcpy(& | + | memcpy(& |
Serial.print(" | Serial.print(" | ||
- | Serial.println(len); | + | Serial.println(taille); |
- | Serial.print(" | + | Serial.print(" |
- | Serial.println(myData.a); | + | Serial.println(maValeurRecue); |
- | Serial.print(" | + | |
- | Serial.println(myData.b); | + | |
- | Serial.print(" | + | |
- | Serial.println(myData.c); | + | |
- | Serial.print(" | + | |
- | Serial.println(myData.d); | + | |
Serial.println(); | Serial.println(); | ||
} | } | ||
void setup() { | void setup() { | ||
- | // Initialize 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; | ||
} | } | ||
+ | |||
+ | // Si ESP-NOW a corectement démarré, il est temps d' | ||
+ | esp_now_register_recv_cb(quand_donnees_Recues); | ||
| | ||
- | // Once ESPNow is successfully Init, we will register for recv CB to | ||
- | // get recv packer info | ||
- | esp_now_register_recv_cb(OnDataRecv); | ||
} | } | ||
void loop() { | void loop() { | ||
+ | | ||
} | } | ||
- | </ | ||
- | |||
- | Le code se passe presque d' | ||
- | < | ||
- | memcpy(& | ||
</ | </ | ||
===== Tester et aller plus loin ===== | ===== Tester et aller plus loin ===== | ||
- | 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 | + | 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 |
- | Nous vous renvoyons aux exemples disponibles dans la bibliothèque Arduino, et à nouveaux aux articles de Random Nerd Tutorials | + | Nous vous renvoyons aux exemples disponibles dans la bibliothèque Arduino pour aller plus loin ! |