
In questo post vedremo due brevi programmi per testare sul campo la rete ESP-NOW, di cui abbiamo già scritto in questo articolo introduttivo del nostro blog.
Vedremo come usare due ESP32-CAM per creare una rete "mesh" con portata di 40~50 metri sfruttando l'antenna incorporata di circa 10 cm. La ESP32-CAM è un microcontroller interessantissimo che unisce alla velocità dell'ESP32 "classico" — di cui abbiamo parlato anche nella guida su come scrivere un server web con ESP32 — una webcam 1600x1200 px, il tutto ad un prezzo assai allettante.
È disponibile su Amazon a meno di dieci euro.
Un progetto minimale
Nel dettaglio vedremo due brevi programmi per inviare e ricevere una sequenza numerica senza Wi-Fi tradizionale ma sfruttando le qualità radio "native" della scheda. Questo approccio è particolarmente interessante quando si progettano nodi IoT compatti, come quelli descritti nella nostra scheda multifunzione per ESP32 .
Si tratta di un vantaggio importante perché permette di far funzionare tutta la rete presso nuovi utenti senza impostare manualmente login e password. In ambienti industriali, tuttavia, è fondamentale considerare anche interferenze e disturbi elettrici, come spiegato nell'analisi su ESP32, I2C ed EMI in ambito industriale .
Il protocollo di comunicazione di Espressif sostituisce il normale Wi-Fi ma ne conserva molti dettagli tecnici. I nostri programmi useranno infatti:
#include "WiFi.h"per settare lo scope del Wi-Fi classico ed ereditarne variabili e strutture dati. Se vuoi confrontare questa architettura con la generazione precedente, puoi leggere anche il nostro approfondimento sulla scheda ESP8266 di Espressif .
Per creare la rete faremo uso di un mini programma per trovare l'indirizzo MAC della scheda ESP ricevente. Il protocollo ESP-NOW prevede infatti di specificare il MAC di ogni scheda abilitata alla ricezione.
if (esp_now_add_peer(&peerInfo) != ESP_OK){
Serial.println("Non riesco ad aggiungere il dispositivo");
return;
}
Il codice main.ino per trovare l'indirizzo MAC
Il programma è brevissimo e utilizza la funzione WiFi.macAddress().
Dopo l'upload nell'IDE Arduino è sufficiente annotare il valore mostrato
nel Serial Monitor.
Con PlatformIO è possibile compilare con make upload
e usare minicom per visualizzare l'output.
Questo tipo di configurazione è tipica dei primi passi per chi sta iniziando con la robotica e vuole comprendere le basi delle comunicazioni embedded.
#include "WiFi.h"
void setup(){
Serial.begin(115200);
WiFi.mode(WIFI_MODE_STA);
Serial.print("indirizzo MAC=");
Serial.println(WiFi.macAddress());
}
void loop(){
}
File platformio.ini per ESP32-CAM
; PlatformIO Project Configuration File
[env:esp32cam]
platform = espressif32
board = esp32cam
framework = arduino
monitor_speed=115200
lib_ldf_mode=deep
build_flags =
-I../lib/esp32-camera
lib_deps =

Nella immagine sopra puoi vedere l'indirizzo MAC E0:5A:1B:6C:E4:B0 che useremo nel programma di trasmissione.
Programma per inviare dati con ESP32-CAM
In questo programma useremo l'indirizzo MAC scoperto in precedenza per selezionare il dispositivo ricevente. Questo schema di comunicazione è utile in sistemi distribuiti come robot mobili o piattaforme autonome alimentate a batteria, tema che abbiamo approfondito nel progetto robot guidato da AI – gestione batterie .
#include <esp_now.h>
#include <WiFi.h>
uint8_t broadcastAddress[] = {0xE0, 0x5A, 0x1B, 0x6C, 0xE4, 0xB0};
typedef struct struct_messaggio {
int contatore;
} struct_messaggio;
struct_messaggio Dati;
esp_now_peer_info_t peerInfo;
int ix;
void suInvioDati(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print("\r\nStatus invio:\t");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Consegna positiva" : "Errore di consegna");
}
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
if (esp_now_init() != ESP_OK) {
Serial.println("Errore di inizializzazione per ESP-NOW");
return;
}
esp_now_register_send_cb(suInvioDati);
ix = 0;
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
if (esp_now_add_peer(&peerInfo) != ESP_OK){
Serial.println("Non riesco ad aggiungere il dispositivo");
return;
}
}
void loop() {
Dati.contatore = ix;
ix++;
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &Dati, sizeof(Dati));
if (result == ESP_OK) {
Serial.println("Messaggio inviato con successo");
} else {
Serial.println("Errore di invio");
}
delay(2000);
}
Programma per ricevere i dati
Il ricevente deve usare la stessa struttura dati del trasmettitore. Anche se semplice, la struct deve corrispondere esattamente.
typedef struct struct_messaggio {
int b;
} struct_messaggio;
Questa architettura può essere estesa a sistemi domotici, ad esempio nel controllo di carichi tramite MOSFET, come spiegato nella nostra guida ai MOSFET nella domotica IoT .
#include <esp_now.h>
#include <WiFi.h>
typedef struct struct_messaggio {
int b;
} struct_messaggio;
struct_messaggio Dati;
void suDatiRicevuti(const uint8_t * mac, const uint8_t *incomingData, int len) {
memcpy(&Dati, incomingData, sizeof(Dati));
Serial.print("Conteggio dei bytes ricevuti: ");
Serial.println(len);
Serial.print("Int: ");
Serial.println(Dati.b);
Serial.println();
}
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
if (esp_now_init() != ESP_OK) {
Serial.println("Errore nella inizializzazione della rete ESP-NOW");
return;
}
esp_now_register_recv_cb(suDatiRicevuti);
}
void loop() {
}

Conclusione
Con soli tre programmi estremamente semplici abbiamo impostato la struttura di funzionamento della rete mesh. Questa tecnologia rappresenta uno dei tasselli fondamentali nello sviluppo delle nuove architetture distribuite, tema che abbiamo analizzato anche parlando dei prossimi sviluppi della robotica in ambito commerciale .
Se stai progettando qualcosa che non può bloccarsi, guarda il Sentinel Node . Memoria pSLC. Watchdog hardware esterno. RTC dedicato. Progettato per uptime reale.