Skip to content

Commit a66b544

Browse files
arvindr21me-no-dev
authored andcommitted
Added ESPNow Multi-Slave example (#669)
* Added ESPNow basic example * fixed meta doc for slave * refactored folder structure * bug fixes * Added Single Master Multi-Slave * updated meta docs
1 parent 2b6d47a commit a66b544

File tree

3 files changed

+341
-10
lines changed

3 files changed

+341
-10
lines changed

Diff for: libraries/ESP32/examples/ESPNow/Basic/Master/Master.ino

+3-10
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,10 @@ void InitESPNow() {
5555
// Scan for slaves in AP mode
5656
void ScanForSlave() {
5757
int8_t scanResults = WiFi.scanNetworks();
58+
// reset on each scan
5859
bool slaveFound = 0;
60+
memset(&slave, 0, sizeof(slave));
61+
5962
Serial.println("");
6063
if (scanResults == 0) {
6164
Serial.println("No WiFi devices in AP Mode found");
@@ -128,14 +131,6 @@ bool manageSlave() {
128131
// Slave already paired.
129132
Serial.println("Already Paired");
130133
return true;
131-
} else if (exists == ESP_ERR_ESPNOW_NOT_INIT) {
132-
// How did we get so far!!
133-
Serial.println("ESPNOW Not InitESP_ERR_ESPNOW_NOT_INIT");
134-
return false;
135-
} else if (exists == ESP_ERR_ESPNOW_ARG) {
136-
// Invalid Argument
137-
Serial.println("Invalid Argument");
138-
return false;
139134
} else {
140135
// Slave not paired, attempt pair
141136
esp_err_t addStatus = esp_now_add_peer(peer);
@@ -191,8 +186,6 @@ void deletePeer() {
191186
}
192187
}
193188

194-
195-
196189
uint8_t data = 0;
197190
// send data
198191
void sendData() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
/**
2+
ESPNOW - Basic communication - Master
3+
Date: 26th September 2017
4+
Author: Arvind Ravulavaru <https://github.com/arvindr21>
5+
Purpose: ESPNow Communication between a Master ESP32 and multiple ESP32 Slaves
6+
Description: This sketch consists of the code for the Master module.
7+
Resources: (A bit outdated)
8+
a. https://espressif.com/sites/default/files/documentation/esp-now_user_guide_en.pdf
9+
b. http://www.esploradores.com/practica-6-conexion-esp-now/
10+
11+
<< This Device Master >>
12+
13+
Flow: Master
14+
Step 1 : ESPNow Init on Master and set it in STA mode
15+
Step 2 : Start scanning for Slave ESP32 (we have added a prefix of `slave` to the SSID of slave for an easy setup)
16+
Step 3 : Once found, add Slave as peer
17+
Step 4 : Register for send callback
18+
Step 5 : Start Transmitting data from Master to Slave(s)
19+
20+
Flow: Slave
21+
Step 1 : ESPNow Init on Slave
22+
Step 2 : Update the SSID of Slave with a prefix of `slave`
23+
Step 3 : Set Slave in AP mode
24+
Step 4 : Register for receive callback and wait for data
25+
Step 5 : Once data arrives, print it in the serial monitor
26+
27+
Note: Master and Slave have been defined to easily understand the setup.
28+
Based on the ESPNOW API, there is no concept of Master and Slave.
29+
Any devices can act as master or salve.
30+
31+
32+
// Sample Serial log with 1 master & 2 slaves
33+
Found 12 devices
34+
1: Slave:24:0A:C4:81:CF:A4 [24:0A:C4:81:CF:A5] (-44)
35+
3: Slave:30:AE:A4:02:6D:CC [30:AE:A4:02:6D:CD] (-55)
36+
2 Slave(s) found, processing..
37+
Processing: 24:A:C4:81:CF:A5 Status: Already Paired
38+
Processing: 30:AE:A4:2:6D:CD Status: Already Paired
39+
Sending: 9
40+
Send Status: Success
41+
Last Packet Sent to: 24:0a:c4:81:cf:a5
42+
Last Packet Send Status: Delivery Success
43+
Send Status: Success
44+
Last Packet Sent to: 30:ae:a4:02:6d:cd
45+
Last Packet Send Status: Delivery Success
46+
47+
*/
48+
49+
#include <esp_now.h>
50+
#include <WiFi.h>
51+
52+
// Global copy of slave
53+
#define NUMSLAVES 20
54+
esp_now_peer_info_t slaves[NUMSLAVES] = {};
55+
int SlaveCnt = 0;
56+
57+
#define CHANNEL 3
58+
#define PRINTSCANRESULTS 0
59+
60+
// Init ESP Now with fallback
61+
void InitESPNow() {
62+
if (esp_now_init() == ESP_OK) {
63+
Serial.println("ESPNow Init Success");
64+
}
65+
else {
66+
Serial.println("ESPNow Init Failed");
67+
// Retry InitESPNow, add a counte and then restart?
68+
// InitESPNow();
69+
// or Simply Restart
70+
ESP.restart();
71+
}
72+
}
73+
74+
// Scan for slaves in AP mode
75+
void ScanForSlave() {
76+
int8_t scanResults = WiFi.scanNetworks();
77+
//reset slaves
78+
memset(slaves, 0, sizeof(slaves));
79+
SlaveCnt = 0;
80+
Serial.println("");
81+
if (scanResults == 0) {
82+
Serial.println("No WiFi devices in AP Mode found");
83+
} else {
84+
Serial.print("Found "); Serial.print(scanResults); Serial.println(" devices ");
85+
for (int i = 0; i < scanResults; ++i) {
86+
// Print SSID and RSSI for each device found
87+
String SSID = WiFi.SSID(i);
88+
int32_t RSSI = WiFi.RSSI(i);
89+
String BSSIDstr = WiFi.BSSIDstr(i);
90+
91+
if (PRINTSCANRESULTS) {
92+
Serial.print(i + 1); Serial.print(": "); Serial.print(SSID); Serial.print(" ["); Serial.print(BSSIDstr); Serial.print("]"); Serial.print(" ("); Serial.print(RSSI); Serial.print(")"); Serial.println("");
93+
}
94+
delay(10);
95+
// Check if the current device starts with `Slave`
96+
if (SSID.indexOf("Slave") == 0) {
97+
// SSID of interest
98+
Serial.print(i + 1); Serial.print(": "); Serial.print(SSID); Serial.print(" ["); Serial.print(BSSIDstr); Serial.print("]"); Serial.print(" ("); Serial.print(RSSI); Serial.print(")"); Serial.println("");
99+
// Get BSSID => Mac Address of the Slave
100+
int mac[6];
101+
102+
if ( 6 == sscanf(BSSIDstr.c_str(), "%x:%x:%x:%x:%x:%x%c", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5] ) ) {
103+
for (int ii = 0; ii < 6; ++ii ) {
104+
slaves[SlaveCnt].peer_addr[ii] = (uint8_t) mac[ii];
105+
}
106+
}
107+
slaves[SlaveCnt].channel = CHANNEL; // pick a channel
108+
slaves[SlaveCnt].encrypt = 0; // no encryption
109+
SlaveCnt++;
110+
}
111+
}
112+
}
113+
114+
if (SlaveCnt > 0) {
115+
Serial.print(SlaveCnt); Serial.println(" Slave(s) found, processing..");
116+
} else {
117+
Serial.println("No Slave Found, trying again.");
118+
}
119+
120+
// clean up ram
121+
WiFi.scanDelete();
122+
}
123+
124+
// Check if the slave is already paired with the master.
125+
// If not, pair the slave with master
126+
void manageSlave() {
127+
if (SlaveCnt > 0) {
128+
for (int i = 0; i < SlaveCnt; i++) {
129+
const esp_now_peer_info_t *peer = &slaves[i];
130+
const uint8_t *peer_addr = slaves[i].peer_addr;
131+
Serial.print("Processing: ");
132+
for (int ii = 0; ii < 6; ++ii ) {
133+
Serial.print((uint8_t) slaves[i].peer_addr[ii], HEX);
134+
if (ii != 5) Serial.print(":");
135+
}
136+
Serial.print(" Status: ");
137+
// check if the peer exists
138+
bool exists = esp_now_is_peer_exist(peer_addr);
139+
if (exists) {
140+
// Slave already paired.
141+
Serial.println("Already Paired");
142+
} else {
143+
// Slave not paired, attempt pair
144+
esp_err_t addStatus = esp_now_add_peer(peer);
145+
if (addStatus == ESP_OK) {
146+
// Pair success
147+
Serial.println("Pair success");
148+
} else if (addStatus == ESP_ERR_ESPNOW_NOT_INIT) {
149+
// How did we get so far!!
150+
Serial.println("ESPNOW Not Init");
151+
} else if (addStatus == ESP_ERR_ESPNOW_ARG) {
152+
Serial.println("Add Peer - Invalid Argument");
153+
} else if (addStatus == ESP_ERR_ESPNOW_FULL) {
154+
Serial.println("Peer list full");
155+
} else if (addStatus == ESP_ERR_ESPNOW_NO_MEM) {
156+
Serial.println("Out of memory");
157+
} else if (addStatus == ESP_ERR_ESPNOW_EXIST) {
158+
Serial.println("Peer Exists");
159+
} else {
160+
Serial.println("Not sure what happened");
161+
}
162+
delay(100);
163+
}
164+
}
165+
} else {
166+
// No slave found to process
167+
Serial.println("No Slave found to process");
168+
}
169+
}
170+
171+
172+
uint8_t data = 0;
173+
// send data
174+
void sendData() {
175+
data++;
176+
for (int i = 0; i < SlaveCnt; i++) {
177+
const uint8_t *peer_addr = slaves[i].peer_addr;
178+
if (i == 0) { // print only for first slave
179+
Serial.print("Sending: ");
180+
Serial.println(data);
181+
}
182+
esp_err_t result = esp_now_send(peer_addr, &data, sizeof(data));
183+
Serial.print("Send Status: ");
184+
if (result == ESP_OK) {
185+
Serial.println("Success");
186+
} else if (result == ESP_ERR_ESPNOW_NOT_INIT) {
187+
// How did we get so far!!
188+
Serial.println("ESPNOW not Init.");
189+
} else if (result == ESP_ERR_ESPNOW_ARG) {
190+
Serial.println("Invalid Argument");
191+
} else if (result == ESP_ERR_ESPNOW_INTERNAL) {
192+
Serial.println("Internal Error");
193+
} else if (result == ESP_ERR_ESPNOW_NO_MEM) {
194+
Serial.println("ESP_ERR_ESPNOW_NO_MEM");
195+
} else if (result == ESP_ERR_ESPNOW_NOT_FOUND) {
196+
Serial.println("Peer not found.");
197+
} else {
198+
Serial.println("Not sure what happened");
199+
}
200+
delay(100);
201+
}
202+
}
203+
204+
// callback when data is sent from Master to Slave
205+
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
206+
char macStr[18];
207+
snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
208+
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
209+
Serial.print("Last Packet Sent to: "); Serial.println(macStr);
210+
Serial.print("Last Packet Send Status: "); Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
211+
}
212+
213+
void setup() {
214+
Serial.begin(115200);
215+
//Set device in STA mode to begin with
216+
WiFi.mode(WIFI_STA);
217+
Serial.println("ESPNow/Multi-Slave/Master Example");
218+
// This is the mac address of the Master in Station Mode
219+
Serial.print("STA MAC: "); Serial.println(WiFi.macAddress());
220+
// Init ESPNow with a fallback logic
221+
InitESPNow();
222+
// Once ESPNow is successfully Init, we will register for Send CB to
223+
// get the status of Trasnmitted packet
224+
esp_now_register_send_cb(OnDataSent);
225+
}
226+
227+
void loop() {
228+
// In the loop we scan for slave
229+
ScanForSlave();
230+
// If Slave is found, it would be populate in `slave` variable
231+
// We will check if `slave` is defined and then we proceed further
232+
if (SlaveCnt > 0) { // check if slave channel is defined
233+
// `slave` is defined
234+
// Add slave as peer if it has not been added already
235+
manageSlave();
236+
// pair success or already paired
237+
// Send data to device
238+
sendData();
239+
} else {
240+
// No slave found to process
241+
}
242+
243+
// wait for 3seconds to run the logic again
244+
delay(1000);
245+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/**
2+
ESPNOW - Basic communication - Slave
3+
Date: 26th September 2017
4+
Author: Arvind Ravulavaru <https://github.com/arvindr21>
5+
Purpose: ESPNow Communication between a Master ESP32 and multiple ESP32 Slaves
6+
Description: This sketch consists of the code for the Slave module.
7+
Resources: (A bit outdated)
8+
a. https://espressif.com/sites/default/files/documentation/esp-now_user_guide_en.pdf
9+
b. http://www.esploradores.com/practica-6-conexion-esp-now/
10+
11+
<< This Device Slave >>
12+
13+
Flow: Master
14+
Step 1 : ESPNow Init on Master and set it in STA mode
15+
Step 2 : Start scanning for Slave ESP32 (we have added a prefix of `slave` to the SSID of slave for an easy setup)
16+
Step 3 : Once found, add Slave as peer
17+
Step 4 : Register for send callback
18+
Step 5 : Start Transmitting data from Master to Slave(s)
19+
20+
Flow: Slave
21+
Step 1 : ESPNow Init on Slave
22+
Step 2 : Update the SSID of Slave with a prefix of `slave`
23+
Step 3 : Set Slave in AP mode
24+
Step 4 : Register for receive callback and wait for data
25+
Step 5 : Once data arrives, print it in the serial monitor
26+
27+
Note: Master and Slave have been defined to easily understand the setup.
28+
Based on the ESPNOW API, there is no concept of Master and Slave.
29+
Any devices can act as master or salve.
30+
*/
31+
32+
#include <esp_now.h>
33+
#include <WiFi.h>
34+
35+
#define CHANNEL 1
36+
37+
// Init ESP Now with fallback
38+
void InitESPNow() {
39+
if (esp_now_init() == ESP_OK) {
40+
Serial.println("ESPNow Init Success");
41+
}
42+
else {
43+
Serial.println("ESPNow Init Failed");
44+
// Retry InitESPNow, add a counte and then restart?
45+
// InitESPNow();
46+
// or Simply Restart
47+
ESP.restart();
48+
}
49+
}
50+
51+
// config AP SSID
52+
void configDeviceAP() {
53+
String Prefix = "Slave:";
54+
String Mac = WiFi.macAddress();
55+
String SSID = Prefix + Mac;
56+
String Password = "123456789";
57+
bool result = WiFi.softAP(SSID.c_str(), Password.c_str(), CHANNEL, 0);
58+
if (!result) {
59+
Serial.println("AP Config failed.");
60+
} else {
61+
Serial.println("AP Config Success. Broadcasting with AP: " + String(SSID));
62+
}
63+
}
64+
65+
void setup() {
66+
Serial.begin(115200);
67+
Serial.println("ESPNow/Basic/Slave Example");
68+
//Set device in AP mode to begin with
69+
WiFi.mode(WIFI_AP);
70+
// configure device AP mode
71+
configDeviceAP();
72+
// This is the mac address of the Slave in AP Mode
73+
Serial.print("AP MAC: "); Serial.println(WiFi.softAPmacAddress());
74+
// Init ESPNow with a fallback logic
75+
InitESPNow();
76+
// Once ESPNow is successfully Init, we will register for recv CB to
77+
// get recv packer info.
78+
esp_now_register_recv_cb(OnDataRecv);
79+
}
80+
81+
// callback when data is recv from Master
82+
void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len) {
83+
char macStr[18];
84+
snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
85+
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
86+
Serial.print("Last Packet Recv from: "); Serial.println(macStr);
87+
Serial.print("Last Packet Recv Data: "); Serial.println(*data);
88+
Serial.println("");
89+
}
90+
91+
void loop() {
92+
// Chill
93+
}

0 commit comments

Comments
 (0)