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/08 17:20] – guillaume | howto:arduino-esp:esp-now [2021/10/12 09:51] – [Principe de communication] 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é | + | À Chaque étape listée ci-dessus va correspondre une fonction spécifique à l' |
+ | |||
+ | **esp_now_init()** Initialiser ESP-NOW. Il faut initialiser le wifi avant d' | ||
+ | **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_register_send_cb()** Enregistre une fonction de rappel qui sera déclenchée lorsque l'on envoie des données.\\ | ||
+ | **esp_now_register_rcv_cb()** Enregistre une fonction de rappel qui sera déclenchée lorsque l'on reçoit des données.\\ | ||
+ | |||
+ | ===== Code de l' | ||
+ | |||
+ | Ci-dessous, le code tel que proposé par Rui Santos, de Random Nerd Tutorials: | ||
+ | |||
+ | < | ||
+ | /* | ||
+ | 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 < | ||
+ | |||
+ | // REPLACE WITH YOUR RECEIVER MAC Address | ||
+ | uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; | ||
+ | |||
+ | // Structure example to send data | ||
+ | // Must match the receiver structure | ||
+ | typedef struct struct_message { | ||
+ | char a[32]; | ||
+ | int b; | ||
+ | float c; | ||
+ | bool d; | ||
+ | } struct_message; | ||
+ | |||
+ | // Create a struct_message called myData | ||
+ | struct_message myData; | ||
+ | |||
+ | // 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() { | ||
+ | // Init Serial Monitor | ||
+ | Serial.begin(115200); | ||
+ | |||
+ | // Set device as a Wi-Fi Station | ||
+ | WiFi.mode(WIFI_STA); | ||
+ | |||
+ | // Init ESP-NOW | ||
+ | if (esp_now_init() != ESP_OK) { | ||
+ | Serial.println(" | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | // Once ESPNow is successfully Init, we will register for Send CB to | ||
+ | // get the status of Trasnmitted packet | ||
+ | esp_now_register_send_cb(OnDataSent); | ||
+ | |||
+ | // 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; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | // Set values to send | ||
+ | strcpy(myData.a, | ||
+ | myData.b = random(1, | ||
+ | myData.c = 1.2; | ||
+ | myData.d = false; | ||
+ | |||
+ | // Send message via ESP-NOW | ||
+ | esp_err_t result = esp_now_send(broadcastAddress, | ||
+ | |||
+ | if (result == ESP_OK) { | ||
+ | Serial.println(" | ||
+ | } | ||
+ | else { | ||
+ | Serial.println(" | ||
+ | } | ||
+ | delay(2000); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Quelques explications: | ||
+ | |||
+ | D' | ||
+ | < | ||
+ | #include < | ||
+ | #include < | ||
+ | </ | ||
+ | |||
+ | Ensuite, nous stockons dans une variable l' | ||
+ | < | ||
+ | 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’appellera // | ||
+ | < | ||
+ | typedef struct struct_message { | ||
+ | char a[32]; | ||
+ | int b; | ||
+ | float c; | ||
+ | bool d; | ||
+ | } struct_message; | ||
+ | </ | ||
+ | |||
+ | On créé ensuite une variable de type // | ||
+ | < | ||
+ | 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(" | ||
+ | Serial.println(status == ESP_NOW_SEND_SUCCESS ? " | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Viens maintenant le moment de créer notre fonction // | ||
+ | |||
+ | < | ||
+ | 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 | ||
+ | |||
+ | 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. Cette manière de travailler permet d' | ||
+ | |||
+ | < | ||
+ | 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(" | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===== Code du récepteur ===== | ||
+ | |||
+ | Voici le programme à uploader dans l'ESP qui servira de récepteur. | ||
+ | |||
+ | < | ||
+ | /* | ||
+ | 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 < | ||
+ | |||
+ | // Structure example to receive data | ||
+ | // Must match the sender structure | ||
+ | typedef struct struct_message { | ||
+ | char a[32]; | ||
+ | int b; | ||
+ | float c; | ||
+ | bool d; | ||
+ | } struct_message; | ||
+ | |||
+ | // Create a struct_message called myData | ||
+ | struct_message myData; | ||
+ | |||
+ | // callback function that will be executed when data is received | ||
+ | void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, | ||
+ | memcpy(& | ||
+ | Serial.print(" | ||
+ | Serial.println(len); | ||
+ | Serial.print(" | ||
+ | Serial.println(myData.a); | ||
+ | Serial.print(" | ||
+ | Serial.println(myData.b); | ||
+ | Serial.print(" | ||
+ | Serial.println(myData.c); | ||
+ | Serial.print(" | ||
+ | Serial.println(myData.d); | ||
+ | Serial.println(); | ||
+ | } | ||
+ | |||
+ | void setup() { | ||
+ | // Initialize Serial Monitor | ||
+ | Serial.begin(115200); | ||
+ | |||
+ | // Set device as a Wi-Fi Station | ||
+ | WiFi.mode(WIFI_STA); | ||
+ | |||
+ | // Init ESP-NOW | ||
+ | if (esp_now_init() != ESP_OK) { | ||
+ | Serial.println(" | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | // Once ESPNow is successfully Init, we will register for recv CB to | ||
+ | // get recv packer info | ||
+ | esp_now_register_recv_cb(OnDataRecv); | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | |||
+ | Le code se passe presque d' | ||
+ | < | ||
+ | memcpy(& | ||
+ | </ | ||
+ | |||
+ | Autre évidence, mais qu'il est bon de rappeler, les membres de la structure doivent être communs entre l' | ||
+ | |||
+ | ===== 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 interpreté 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. | ||
- | **esp_now_init()** Initialise ESP-NOW. Il faut initialiser le wifi avant d' | ||
- | **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_register_send_cb()** Enregistre une fonction de rappel qui sera déclenchée lorsque l'on envoie des données. | ||
- | **esp_now_register_rcv_cb()** Enregistre une fonction de rappel qui sera déclenchée lorsque l'on reçoit des données. | ||