El protocolo esp-now es muy sencillo de utilizar y utiliza la señal wifi, sin embargo tiene algunas limitaciones como por ejemplo en número de bytes que podemos hacer en cada envío, ya que es de solo 250 bytes.
Para enviar o recibir información utilizando el protocolo «esp-now» se necesita la dirección «MAC» del dispositivo del cual recibes la información, y también debes especificar la dirección «MAC» del dispositivo al que quieres enviar la información.
Muestro abajo el código con el cual podrás ver en pantalla, desde el «monitor serie», la dirección «MAC» del dispositivo que ejecuta el código.
Código para conocer la dirección MAC desde monitor serie:
#include <Arduino.h>
#include "WiFi.h"
void setup(){
Serial.begin(9600);
WiFi.mode(WIFI_STA);
Serial.println(WiFi.macAddress());
}
void loop(){
Serial.println(WiFi.macAddress());
delay(5000);
}
El código desde el cual un modulo 1 ESP32 envía un dato a otro modulo ESP y al mismo tiempo recibe un dato del mismo módulo se muestra a continuación.
Lo primero que necesitamos es incluir las librerías que necesitamos, para este proyecto necesitaremos la librería «esp-now», que es el protocolo para enviar y recibir datos desde un módulo ESP32 a otro. Y la librería «wifi», que la utilizaremos para operar el sistema de comunicación wifi de los ESP32.
#include <esp_now.h>
#include <WiFi.h>
Lo siguiente y para poder almacenar la dirección MAC hemos utilizado un array llamado «broadcastAddress», en este caso esta definido como dato «uint8_t» que es un entero de 8 bits sin signo negativo.
// REPLACE WITH YOUR RECEIVER MAC Address
uint8_t broadcastAddress[] = {0x34, 0x86, 0x5D, 0xFD, 0x00, 0x00};
En el siguiente código definimos la estructura que tendrán los datos que queremos tanto enviar como recibir. Utilizamos «struct» para asignar al siguiente nombre un tipo de dato «estructura», y lo declaramos como tipo «typedef» para que quede guardado con ese nombre, en este caso se queda guardado como estructura el nombre que definimos, de esta manera no necesitaremos volver a escribir «struct» cada vez que nos refiramos al nombre definido las sucesivas veces.
Un dato tipo «struct» puede tener una o mas variables, en nuestro ejemplo tendra una única variable «int a» declarada la letra «a» como numero entero.
Después declaramos dos variables llamadas myDataRec y myDataSen que contendrán cada una de ellas las variables del tipo de dato «struct» definido.
// Structure example to send data
// Must match the receiver structure
typedef struct struct_message {
int a;
} struct_message;
// Create a struct_message called myData
struct_message myDataRec;
struct_message myDataSen;
El siguiente código nombraremos «peerInfo» como tipo de dato estructurado llamado «esp_now_peer_info_t» (descrito en la página oficial de espressif), esta estructura consta de 3 variables, la primera será donde introduciremos la dirección MAC del módulo donde queremos enviar los datos, la segunda variable se utiliza para nombrar una clave para recibir los datos y en la tercera indicaremos el canal con el que queremos transmitir los datos via wifi, en caso de utilizar el canal por defecto pondremos un cero.
La función que utiliza esta estructura de dato «peerInfo» es «esp_now_add_peer» y en este caso nos devuelve un «ESP_OK» si se ha encontrado el módulo con la MAC indicada.
esp_now_peer_info_t peerInfo;
.
.
.
// Register peer
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
// Add peer
if (esp_now_add_peer(&peerInfo) != ESP_OK){
Serial.println("Failed to add peer");
return;
}
La siguiente parte crearemos una función para enviar los datos al otro módulo ESP32, la función se llama «OnDataSent» con dos parámetros, el primer parámetro es la dirección MAC y el segundo parámetro nombra el dato de tipo «enum» llamado «esp_now_send_status_t» definido en espressif. Este dato nos da como respuesta si el envío se ha realizado con éxito o ha habido algún fallo.
// callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print("\r\nLast Packet Send Status:\t");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}
La siguiente función la utilizaremos para recibir los datos del módulo ESP32 que los envía. La función se llama «OnDataRec», el primer parámetro guarda la dirección MAC en formato array del módulo que esta enviando el mensaje.
// callback function that will be executed when data is received
void OnDataRecv(const uint8_t *mac, const uint8_t *incomingData, int len) {
memcpy(&myDataRec, incomingData, sizeof(myDataRec));
Serial.print("Bytes received: ");
Serial.println(len);
Serial.print("Int: ");
Serial.println(myDataRec.a);
Serial.println();
}
En el siguiente código ya estamos dentro del setup(), dentro de la sintaxis de Arduino la función setup() la utilizamos para declarar variables, estructuras o datos que solo deben ejecutarse una vez en cada inicio del programa.
En nuestro caso dentro del setup() la primera instrucción que tenemos es Serial.begin, la utilizamos para indicar la velocidad en baudios con la que transmite la información el monitor serial.
// Init Serial Monitor
Serial.begin(9600);
La siguiente instrucción indicaremos en que modo dentro de la tecnología wifi va a trabajar nuestro modulo, pudiendo elegir entre modo «static» (enviar o recibir información via wifi), modo «Acces Point» (conexión a internet) o ambos. En este caso lo configuramos en modo «static».
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
Ahora escribiremos la función esp_now_init() que nos devuelve un valor indicando si el protocolo esp-now se ha iniciado correctamente.
// Init ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
Cuando hacemos un envio de datos debemos registrar la llamada al envío de datos utilizando, esp_now_register_send_cb :
// Once ESPNow is successfully Init, we will register for Send CB to
// get the status of Trasnmitted packet
esp_now_register_send_cb(OnDataSent);
Igual que arriba si recimos datos debemos registrar la llamada, en este caso utilizaremos esp_now_register_recv_cb :
// Once ESPNow is successfully Init, we will register for recv CB to
// get recv packer info
esp_now_register_recv_cb(OnDataRecv);
El siguiente extracto de código nos situamos dentro de la función void loop(), que dentro de la sintaxis del código de arduino se ejecuta constantemente como un bucle cerrado. Dentro de void loop() suele estar el programa en cuestión con las tareas que queremos que haga el modulo modulo ESP32, en nuestro caso.
En nuestra función loop() la primera instrucción en la asignación de un numero a la variable «a» definida dentro de la estructura «myDataSen»:
// Set values to send
myDataSen.a = 1;
Para enviar el mensaje utilizamos la función esp_now_send(), esta función envía los datos que hemos especificado, y devuelve ESP_OK en el caso de que no hallan habido errores.
// Send message via ESP-NOW
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myDataSen, sizeof(myDataSen));
if (result == ESP_OK) {
Serial.println("Sent with success");
}
else {
Serial.println("Error sending the data");
}
Código completo del Módulo 1:
#include <esp_now.h>
#include <WiFi.h>
// REPLACE WITH YOUR RECEIVER MAC Address
uint8_t broadcastAddress[] = {0x34, 0x86, 0x5D, 0x00, 0x00, 0x00};
// Structure example to send data
// Must match the receiver structure
typedef struct struct_message {
int a;
} struct_message;
// Create a struct_message called myData
struct_message myDataRec;
struct_message myDataSen;
esp_now_peer_info_t peerInfo;
// callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print("\r\nLast Packet Send Status:\t");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}
// callback function that will be executed when data is received
void OnDataRecv(const uint8_t *mac, const uint8_t *incomingData, int len) {
memcpy(&myDataRec, incomingData, sizeof(myDataRec));
Serial.print("Bytes received: ");
Serial.println(len);
Serial.print("Int: ");
Serial.println(myDataRec.a);
Serial.println();
}
void setup() {
// Init Serial Monitor
Serial.begin(9600);
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
// Init ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
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
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
// Add peer
if (esp_now_add_peer(&peerInfo) != ESP_OK){
Serial.println("Failed to add peer");
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() {
// Set values to send
myDataSen.a = 1;
// Send message via ESP-NOW
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myDataSen, sizeof(myDataSen));
if (result == ESP_OK) {
Serial.println("Sent with success");
}
else {
Serial.println("Error sending the data");
}
delay(2000);
}
En nuestro ejemplo el módulo 2 trabaja exactamente igual que el módulo 1, a continuación se muestra el código completo del módulo 2:
#include <esp_now.h>
#include <WiFi.h>
// REPLACE WITH YOUR RECEIVER MAC Address
uint8_t broadcastAddress[] = {0xc0, 0x49, 0xef, 0xce, 0x00, 0x00};
// Structure example to receive data
// Must match the sender structure
typedef struct struct_message {
int a;
} struct_message;
// Create a struct_message called myData
struct_message myDataRec;
struct_message myDataSen;
esp_now_peer_info_t peerInfo;
// callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print("\r\nLast Packet Send Status:\t");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}
// callback function that will be executed when data is received
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
memcpy(&myDataRec, incomingData, sizeof(myDataRec));
Serial.print("Bytes received: ");
Serial.println(len);
Serial.print("Int: ");
Serial.println(myDataRec.a);
Serial.println();
}
void setup() {
// Initialize Serial Monitor
Serial.begin(9600);
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
// Init ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
// Once ESPNow is successfully Init, we will register for recv CB to
// get recv packer info
esp_now_register_recv_cb(OnDataRecv);
// 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
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
// Add peer
if (esp_now_add_peer(&peerInfo) != ESP_OK){
Serial.println("Failed to add peer");
return;
}
}
void loop() {
// Set values to send
myDataSen.a = 2;
// Send message via ESP-NOW
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myDataSen, sizeof(myDataSen));
if (result == ESP_OK) {
Serial.println("Sent with success");
}
else {
Serial.println("Error sending the data");
}
delay(2000);
}
Deja una respuesta Cancelar la respuesta