245 lines
8.3 KiB
Arduino
245 lines
8.3 KiB
Arduino
|
/**
|
||
|
ESPNOW - Basic communication - Master
|
||
|
Date: 26th September 2017
|
||
|
Author: Arvind Ravulavaru <https://github.com/arvindr21>
|
||
|
Purpose: ESPNow Communication between a Master ESP32 and multiple ESP32 Slaves
|
||
|
Description: This sketch consists of the code for the Master module.
|
||
|
Resources: (A bit outdated)
|
||
|
a. https://espressif.com/sites/default/files/documentation/esp-now_user_guide_en.pdf
|
||
|
b. http://www.esploradores.com/practica-6-conexion-esp-now/
|
||
|
|
||
|
<< This Device Master >>
|
||
|
|
||
|
Flow: Master
|
||
|
Step 1 : ESPNow Init on Master and set it in STA mode
|
||
|
Step 2 : Start scanning for Slave ESP32 (we have added a prefix of `slave` to the SSID of slave for an easy setup)
|
||
|
Step 3 : Once found, add Slave as peer
|
||
|
Step 4 : Register for send callback
|
||
|
Step 5 : Start Transmitting data from Master to Slave(s)
|
||
|
|
||
|
Flow: Slave
|
||
|
Step 1 : ESPNow Init on Slave
|
||
|
Step 2 : Update the SSID of Slave with a prefix of `slave`
|
||
|
Step 3 : Set Slave in AP mode
|
||
|
Step 4 : Register for receive callback and wait for data
|
||
|
Step 5 : Once data arrives, print it in the serial monitor
|
||
|
|
||
|
Note: Master and Slave have been defined to easily understand the setup.
|
||
|
Based on the ESPNOW API, there is no concept of Master and Slave.
|
||
|
Any devices can act as master or salve.
|
||
|
|
||
|
|
||
|
// Sample Serial log with 1 master & 2 slaves
|
||
|
Found 12 devices
|
||
|
1: Slave:24:0A:C4:81:CF:A4 [24:0A:C4:81:CF:A5] (-44)
|
||
|
3: Slave:30:AE:A4:02:6D:CC [30:AE:A4:02:6D:CD] (-55)
|
||
|
2 Slave(s) found, processing..
|
||
|
Processing: 24:A:C4:81:CF:A5 Status: Already Paired
|
||
|
Processing: 30:AE:A4:2:6D:CD Status: Already Paired
|
||
|
Sending: 9
|
||
|
Send Status: Success
|
||
|
Last Packet Sent to: 24:0a:c4:81:cf:a5
|
||
|
Last Packet Send Status: Delivery Success
|
||
|
Send Status: Success
|
||
|
Last Packet Sent to: 30:ae:a4:02:6d:cd
|
||
|
Last Packet Send Status: Delivery Success
|
||
|
|
||
|
*/
|
||
|
|
||
|
#include <esp_now.h>
|
||
|
#include <WiFi.h>
|
||
|
|
||
|
// Global copy of slave
|
||
|
#define NUMSLAVES 20
|
||
|
esp_now_peer_info_t slaves[NUMSLAVES] = {};
|
||
|
int SlaveCnt = 0;
|
||
|
|
||
|
#define CHANNEL 3
|
||
|
#define PRINTSCANRESULTS 0
|
||
|
|
||
|
// Init ESP Now with fallback
|
||
|
void InitESPNow() {
|
||
|
if (esp_now_init() == ESP_OK) {
|
||
|
Serial.println("ESPNow Init Success");
|
||
|
}
|
||
|
else {
|
||
|
Serial.println("ESPNow Init Failed");
|
||
|
// Retry InitESPNow, add a counte and then restart?
|
||
|
// InitESPNow();
|
||
|
// or Simply Restart
|
||
|
ESP.restart();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Scan for slaves in AP mode
|
||
|
void ScanForSlave() {
|
||
|
int8_t scanResults = WiFi.scanNetworks();
|
||
|
//reset slaves
|
||
|
memset(slaves, 0, sizeof(slaves));
|
||
|
SlaveCnt = 0;
|
||
|
Serial.println("");
|
||
|
if (scanResults == 0) {
|
||
|
Serial.println("No WiFi devices in AP Mode found");
|
||
|
} else {
|
||
|
Serial.print("Found "); Serial.print(scanResults); Serial.println(" devices ");
|
||
|
for (int i = 0; i < scanResults; ++i) {
|
||
|
// Print SSID and RSSI for each device found
|
||
|
String SSID = WiFi.SSID(i);
|
||
|
int32_t RSSI = WiFi.RSSI(i);
|
||
|
String BSSIDstr = WiFi.BSSIDstr(i);
|
||
|
|
||
|
if (PRINTSCANRESULTS) {
|
||
|
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("");
|
||
|
}
|
||
|
delay(10);
|
||
|
// Check if the current device starts with `Slave`
|
||
|
if (SSID.indexOf("Slave") == 0) {
|
||
|
// SSID of interest
|
||
|
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("");
|
||
|
// Get BSSID => Mac Address of the Slave
|
||
|
int mac[6];
|
||
|
|
||
|
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] ) ) {
|
||
|
for (int ii = 0; ii < 6; ++ii ) {
|
||
|
slaves[SlaveCnt].peer_addr[ii] = (uint8_t) mac[ii];
|
||
|
}
|
||
|
}
|
||
|
slaves[SlaveCnt].channel = CHANNEL; // pick a channel
|
||
|
slaves[SlaveCnt].encrypt = 0; // no encryption
|
||
|
SlaveCnt++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (SlaveCnt > 0) {
|
||
|
Serial.print(SlaveCnt); Serial.println(" Slave(s) found, processing..");
|
||
|
} else {
|
||
|
Serial.println("No Slave Found, trying again.");
|
||
|
}
|
||
|
|
||
|
// clean up ram
|
||
|
WiFi.scanDelete();
|
||
|
}
|
||
|
|
||
|
// Check if the slave is already paired with the master.
|
||
|
// If not, pair the slave with master
|
||
|
void manageSlave() {
|
||
|
if (SlaveCnt > 0) {
|
||
|
for (int i = 0; i < SlaveCnt; i++) {
|
||
|
const esp_now_peer_info_t *peer = &slaves[i];
|
||
|
const uint8_t *peer_addr = slaves[i].peer_addr;
|
||
|
Serial.print("Processing: ");
|
||
|
for (int ii = 0; ii < 6; ++ii ) {
|
||
|
Serial.print((uint8_t) slaves[i].peer_addr[ii], HEX);
|
||
|
if (ii != 5) Serial.print(":");
|
||
|
}
|
||
|
Serial.print(" Status: ");
|
||
|
// check if the peer exists
|
||
|
bool exists = esp_now_is_peer_exist(peer_addr);
|
||
|
if (exists) {
|
||
|
// Slave already paired.
|
||
|
Serial.println("Already Paired");
|
||
|
} else {
|
||
|
// Slave not paired, attempt pair
|
||
|
esp_err_t addStatus = esp_now_add_peer(peer);
|
||
|
if (addStatus == ESP_OK) {
|
||
|
// Pair success
|
||
|
Serial.println("Pair success");
|
||
|
} else if (addStatus == ESP_ERR_ESPNOW_NOT_INIT) {
|
||
|
// How did we get so far!!
|
||
|
Serial.println("ESPNOW Not Init");
|
||
|
} else if (addStatus == ESP_ERR_ESPNOW_ARG) {
|
||
|
Serial.println("Add Peer - Invalid Argument");
|
||
|
} else if (addStatus == ESP_ERR_ESPNOW_FULL) {
|
||
|
Serial.println("Peer list full");
|
||
|
} else if (addStatus == ESP_ERR_ESPNOW_NO_MEM) {
|
||
|
Serial.println("Out of memory");
|
||
|
} else if (addStatus == ESP_ERR_ESPNOW_EXIST) {
|
||
|
Serial.println("Peer Exists");
|
||
|
} else {
|
||
|
Serial.println("Not sure what happened");
|
||
|
}
|
||
|
delay(100);
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
// No slave found to process
|
||
|
Serial.println("No Slave found to process");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
uint8_t data = 0;
|
||
|
// send data
|
||
|
void sendData() {
|
||
|
data++;
|
||
|
for (int i = 0; i < SlaveCnt; i++) {
|
||
|
const uint8_t *peer_addr = slaves[i].peer_addr;
|
||
|
if (i == 0) { // print only for first slave
|
||
|
Serial.print("Sending: ");
|
||
|
Serial.println(data);
|
||
|
}
|
||
|
esp_err_t result = esp_now_send(peer_addr, &data, sizeof(data));
|
||
|
Serial.print("Send Status: ");
|
||
|
if (result == ESP_OK) {
|
||
|
Serial.println("Success");
|
||
|
} else if (result == ESP_ERR_ESPNOW_NOT_INIT) {
|
||
|
// How did we get so far!!
|
||
|
Serial.println("ESPNOW not Init.");
|
||
|
} else if (result == ESP_ERR_ESPNOW_ARG) {
|
||
|
Serial.println("Invalid Argument");
|
||
|
} else if (result == ESP_ERR_ESPNOW_INTERNAL) {
|
||
|
Serial.println("Internal Error");
|
||
|
} else if (result == ESP_ERR_ESPNOW_NO_MEM) {
|
||
|
Serial.println("ESP_ERR_ESPNOW_NO_MEM");
|
||
|
} else if (result == ESP_ERR_ESPNOW_NOT_FOUND) {
|
||
|
Serial.println("Peer not found.");
|
||
|
} else {
|
||
|
Serial.println("Not sure what happened");
|
||
|
}
|
||
|
delay(100);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// callback when data is sent from Master to Slave
|
||
|
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
|
||
|
char macStr[18];
|
||
|
snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
|
||
|
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
|
||
|
Serial.print("Last Packet Sent to: "); Serial.println(macStr);
|
||
|
Serial.print("Last Packet Send Status: "); Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
|
||
|
}
|
||
|
|
||
|
void setup() {
|
||
|
Serial.begin(115200);
|
||
|
//Set device in STA mode to begin with
|
||
|
WiFi.mode(WIFI_STA);
|
||
|
Serial.println("ESPNow/Multi-Slave/Master Example");
|
||
|
// This is the mac address of the Master in Station Mode
|
||
|
Serial.print("STA MAC: "); Serial.println(WiFi.macAddress());
|
||
|
// Init ESPNow with a fallback logic
|
||
|
InitESPNow();
|
||
|
// Once ESPNow is successfully Init, we will register for Send CB to
|
||
|
// get the status of Trasnmitted packet
|
||
|
esp_now_register_send_cb(OnDataSent);
|
||
|
}
|
||
|
|
||
|
void loop() {
|
||
|
// In the loop we scan for slave
|
||
|
ScanForSlave();
|
||
|
// If Slave is found, it would be populate in `slave` variable
|
||
|
// We will check if `slave` is defined and then we proceed further
|
||
|
if (SlaveCnt > 0) { // check if slave channel is defined
|
||
|
// `slave` is defined
|
||
|
// Add slave as peer if it has not been added already
|
||
|
manageSlave();
|
||
|
// pair success or already paired
|
||
|
// Send data to device
|
||
|
sendData();
|
||
|
} else {
|
||
|
// No slave found to process
|
||
|
}
|
||
|
|
||
|
// wait for 3seconds to run the logic again
|
||
|
delay(1000);
|
||
|
}
|