From 4c36e033812a4142ba417565926ff8f919a32646 Mon Sep 17 00:00:00 2001 From: Arvind Ravulavaru Date: Tue, 26 Sep 2017 15:14:54 +0530 Subject: [PATCH] Added ESPNow basic example (#667) * Added ESPNow basic example * fixed meta doc for slave * refactored folder structure --- .../examples/ESPNow/Basic/Master/Master.ino | 269 ++++++++++++++++++ .../examples/ESPNow/Basic/Slave/Slave.ino | 90 ++++++ 2 files changed, 359 insertions(+) create mode 100644 libraries/ESP32/examples/ESPNow/Basic/Master/Master.ino create mode 100644 libraries/ESP32/examples/ESPNow/Basic/Slave/Slave.ino diff --git a/libraries/ESP32/examples/ESPNow/Basic/Master/Master.ino b/libraries/ESP32/examples/ESPNow/Basic/Master/Master.ino new file mode 100644 index 00000000..01c9362a --- /dev/null +++ b/libraries/ESP32/examples/ESPNow/Basic/Master/Master.ino @@ -0,0 +1,269 @@ +/** + ESPNOW - Basic communication - Master + Date: 26th September 2017 + Author: Arvind Ravulavaru + Purpose: ESPNow Communication between a Master ESP32 and a Slave ESP32 + 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 + + 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. +*/ + +#include +#include + +// Global copy of slave +esp_now_peer_info_t slave; +#define CHANNEL 3 +#define PRINTSCANRESULTS 0 +#define DELETEBEFOREPAIR 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(); + bool slaveFound = 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(RSSI); + Serial.print(")"); + Serial.println(""); + } + delay(10); + // Check if the current device starts with `Slave` + if (SSID.indexOf("Slave") == 0) { + // SSID of interest + Serial.println("Found a Slave."); + 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 ) { + slave.peer_addr[ii] = (uint8_t) mac[ii]; + } + } + + slave.channel = CHANNEL; // pick a channel + slave.encrypt = 0; // no encryption + + slaveFound = 1; + // we are planning to have only one slave in this example; + // Hence, break after we find one, to be a bit efficient + break; + } + } + } + + if (slaveFound) { + Serial.println("Slave Found, processing.."); + } else { + Serial.println("Slave Not 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 +bool manageSlave() { + if (slave.channel == CHANNEL) { + if (DELETEBEFOREPAIR) { + deletePeer(); + } + + Serial.print("Slave Status: "); + const esp_now_peer_info_t *peer = &slave; + const uint8_t *peer_addr = slave.peer_addr; + // check if the peer exists + bool exists = esp_now_is_peer_exist(peer_addr); + if ( exists) { + // Slave already paired. + Serial.println("Already Paired"); + return true; + } else if (exists == ESP_ERR_ESPNOW_NOT_INIT) { + // How did we get so far!! + Serial.println("ESPNOW Not InitESP_ERR_ESPNOW_NOT_INIT"); + return false; + } else if (exists == ESP_ERR_ESPNOW_ARG) { + // Invalid Argument + Serial.println("Invalid Argument"); + return false; + } 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"); + return true; + } else if (addStatus == ESP_ERR_ESPNOW_NOT_INIT) { + // How did we get so far!! + Serial.println("ESPNOW Not Init"); + return false; + } else if (addStatus == ESP_ERR_ESPNOW_ARG) { + Serial.println("Invalid Argument"); + return false; + } else if (addStatus == ESP_ERR_ESPNOW_FULL) { + Serial.println("Peer list full"); + return false; + } else if (addStatus == ESP_ERR_ESPNOW_NO_MEM) { + Serial.println("Out of memory"); + return false; + } else if (addStatus == ESP_ERR_ESPNOW_EXIST) { + Serial.println("Peer Exists"); + return true; + } else { + Serial.println("Not sure what happened"); + return false; + } + } + } else { + // No slave found to process + Serial.println("No Slave found to process"); + return false; + } +} + +void deletePeer() { + const esp_now_peer_info_t *peer = &slave; + const uint8_t *peer_addr = slave.peer_addr; + esp_err_t delStatus = esp_now_del_peer(peer_addr); + Serial.print("Slave Delete Status: "); + if (delStatus == ESP_OK) { + // Delete success + Serial.println("Success"); + } else if (delStatus == ESP_ERR_ESPNOW_NOT_INIT) { + // How did we get so far!! + Serial.println("ESPNOW Not Init"); + } else if (delStatus == ESP_ERR_ESPNOW_ARG) { + Serial.println("Invalid Argument"); + } else if (delStatus == ESP_ERR_ESPNOW_NOT_FOUND) { + Serial.println("Peer not found."); + } else { + Serial.println("Not sure what happened"); + } +} + + + +uint8_t data = 0; +// send data +void sendData() { + data++; + const uint8_t *peer_addr = slave.peer_addr; + 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"); + } +} + +// 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/Basic/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 (slave.channel == CHANNEL) { // check if slave channel is defined + // `slave` is defined + // Add slave as peer if it has not been added already + bool isPaired = manageSlave(); + if (isPaired) { + // pair success or already paired + // Send data to device + sendData(); + } else { + // slave pair failed + Serial.println("Slave pair failed!"); + } + } + else { + // No slave found to process + } + + // wait for 3seconds to run the logic again + delay(3000); +} \ No newline at end of file diff --git a/libraries/ESP32/examples/ESPNow/Basic/Slave/Slave.ino b/libraries/ESP32/examples/ESPNow/Basic/Slave/Slave.ino new file mode 100644 index 00000000..21e963b8 --- /dev/null +++ b/libraries/ESP32/examples/ESPNow/Basic/Slave/Slave.ino @@ -0,0 +1,90 @@ +/** + ESPNOW - Basic communication - Slave + Date: 26th September 2017 + Author: Arvind Ravulavaru + Purpose: ESPNow Communication between a Master ESP32 and a Slave ESP32 + Description: This sketch consists of the code for the Slave 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 Slave >> + + 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 + + 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. +*/ + +#include +#include + +#define CHANNEL 1 + +// 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(); + } +} + +// config AP SSID +void configDeviceAP() { + char* SSID = "Slave_1"; + bool result = WiFi.softAP(SSID, "Slave_1_Password", CHANNEL, 0); + if (!result) { + Serial.println("AP Config failed."); + } else { + Serial.println("AP Config Success. Broadcasting with AP: " + String(SSID)); + } +} + +void setup() { + Serial.begin(115200); + Serial.println("ESPNow/Basic/Slave Example"); + //Set device in AP mode to begin with + WiFi.mode(WIFI_AP); + // configure device AP mode + configDeviceAP(); + // This is the mac address of the Slave in AP Mode + Serial.print("AP MAC: "); Serial.println(WiFi.softAPmacAddress()); + // Init ESPNow with a fallback logic + InitESPNow(); + // Once ESPNow is successfully Init, we will register for recv CB to + // get recv packer info. + esp_now_register_recv_cb(OnDataRecv); +} + +// callback when data is recv from Master +void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len) { + 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 Recv from: "); Serial.println(macStr); + Serial.print("Last Packet Recv Data: "); Serial.println(*data); + Serial.println(""); +} + +void loop() { + // Chill +} \ No newline at end of file