esp32 tank sensor gauge using esp-now on a boat.
The project is to create a “touchless” tank level gauge. “Touchless in this case means a sensor does not need ot go inside the tank. While it is for my own boat, the idea is it will be easy to install and use and potentially a product could be made from it. It should work for water tanks, fuel tanks and even blackwater tanks as long as they are not metal tanks. The basic functionality is to have five “sensors”, aluminum tape that will show full, 3/4, 1/2, 1/4 and empty. Maybe on empty all the LEDs flash and a buzzer sounds. So far it works experimentally but not in the tank yet. It should be able to be readily expanded to 2, 3, 4 or more tanks for just the price of another ESP32 dev kit, under $5.
UPDATE February 2022 – Still a ways to go, but It will be made as a product that can test up to 3 tanks (maybe 5). The sensors will just be aluminum tape and each tank will have an esp32 which will only need 12 volts, no other wires. If it is hard to get 12 volts to it, then it could be run off of a 6 volt battery pack, could be rechargeable, if let’s say it is not easy to get 12 volts to the tank in the bow. The LED display and “control” unit will go in a convenient visible place and, again, will just need a “hot” and a “ground” wire carrying 12 volts. Or again, a battery back if it is difficult to provide boat power. All units will be polarity protected and will run on 6 or 12 volts. Boat power, 4 AA batteries or a LiOn pack.
A high percentage of this code probably came from someone else. I do not know how to write code, but I can sometimes paste things together that work. Even if the code shown here did not come from one of the sources below, I most likely learned how to make it work with help from them. My apologies to anyone I missed. Please make use of anything you see here, but do not count on good coding practice as I have just done what was needed to make it work. But it does work, unless otherwise noted. Thanks to everyone who has shared their knowledge and good luck to those who are learning. https://www.jarutex.com/index.php/2021/12/19/8868/ https://www.arduino.cc/ https://www.sparkfun.com/ https://randomnerdtutorials.com/ https://youtu.be/3BWSSpcn95A https://stackoverflow.com/ https://youtu.be/684KSAvYbw4 https://exploreembedded.com/ https://www.youtube.com/watch?v=JmvMvIphMnY&t https://prosperityconsulting.com
It is still a work in progress, but here is the code. While the code may not be elegant, it works! . I would like to work on the sensitivity and some “smoothing” but so far, I have not cracked the mysterious esp32 internal “touch” functions.
// SENDER AND CONTROL UNIT.
//mostly the code comes directly from the ESP32 documentation but with lots of study and insights from //the https://randomnerdtutorials.com/ website.
// this is the "sender" module but I am thinking of swapping them around. In other words putting the //"smarts" in the LED display unit and having the unit at the tank(s) just send raw data.
#include <esp_now.h>
#include <WiFi.h>
#include <Preferences.h> // library to set up write-to-flash function
Preferences preferences; // Assignment to set up write-to-flash function
//d12 T9 - d4 T0 - d15 T3 - d13 T4 - d12 T5 the TouchPin number and pin number (jsut for reference)
// situp variables for checking "LED" staus
bool l1 = 0;
bool l2 = 0;
bool l3 = 0;
bool l4 = 0;
bool l5 = 0;
int padding = 4; //CALBRATION FACTOR (times.001) threshold value. set to present sensor reading to allow for drift
int buttonStatus = 0; // initialize button
int currentSensorVal1; // the latest reading of the sensors
int currentSensorVal2;
int currentSensorVal3;
int currentSensorVal4;
int currentSensorVal5;
int threshHoldValue1; // INITIALIZE VARIABLE TO STORE drySensorValue plus a margin for error
int threshHoldValue2;
int threshHoldValue3;
int threshHoldValue4;
int threshHoldValue5;
// Global copy of slave
esp_now_peer_info_t slave;
#define CHANNEL 1 // must match this value on slave
#define PRINTSCANRESULTS 0
#define DELETEBEFOREPAIR 0
// Init ESP Now with fallback
void InitESPNow() {
WiFi.disconnect();
if (esp_now_init() == ESP_OK) {
Serial.println("ESPNow Init Success");
} else {
Serial.println("ESPNow Init Failed");
ESP.restart();
}
}
// Scan for slaves in AP mode
void ScanForSlave() {
int8_t scanResults = WiFi.scanNetworks();
// reset on each scan
bool slaveFound = 0;
memset(&slave, 0, sizeof(slave));
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", &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: ");
// check if the peer exists
bool exists = esp_now_is_peer_exist(slave.peer_addr);
if (exists) {
// Slave already paired.
Serial.println("Already Paired");
return true;
} else {
// Slave not paired, attempt pair
esp_err_t addStatus = esp_now_add_peer(&slave);
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() {
esp_err_t delStatus = esp_now_del_peer(slave.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;
// 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 wifi code end
void setup() {
Serial.begin(115200);
preferences.begin("calibration", false);// Line to make nonvolitile memory work NO ERROR REPORTED IF MISSING!
WiFi.mode(WIFI_STA); //Set device in STA mode to begin with
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);
pinMode(26, INPUT_PULLUP); // enable internal pull-up for calibration pushbutton
// enable led pins,
pinMode(21, OUTPUT);
pinMode(22, OUTPUT);
pinMode(23, OUTPUT);
pinMode(24, OUTPUT);
pinMode(25, OUTPUT);
}
void loop() {
readAndReport(); // functions that read the data compare to the saved data and decide HIGH OR LOW for LEdS
setUpConnections(); // wifi code from ESP32
// sendData(); //ESP32 sending funciton
}
// ==================================== end LOOP() ================================================
//---------------- ===============FUNCTIONS =========================================================
// send data FUNCTION (mostly writtee by ESP) ====================================
void sendData() {
// Must match the receiver structure NEW DW
typedef struct struct_message {
// char dw_a[32]= "a"; // int dw_b = 202;// float dw_c = 26.9; // String dw_d = "this test";
int dw_1 = l1;
int dw_2 = l2;
int dw_3 = l3;
int dw_4 = l4;
int dw_5 = l5;
// int dw_d = 1;
// bool dw_e = 1;
} struct_message;
// Create a struct_message called myData
struct_message myData;
// Serial.printf(" myData a is chr %s\n", myData.dw_a);
// Serial.printf(" myData b is int %u\n", myData.dw_b);
// Serial.printf(" myData c is float %f\n", myData.dw_c);
// Serial.printf(" myData d is string %s\n", myData.dw_d);
// Serial.printf(" myData e is bool %u\n", myData.dw_e);
// Serial.print(myData.dw_a);
// Serial.print(myData.dw_b);
// Serial.print(myData.dw_c);
// Serial.print(myData.dw_d);
// Serial.print(myData.dw_e);
//delay(300);
const uint8_t* peer_addr = slave.peer_addr;
Serial.print("Sending: "); Serial.println(data);
esp_err_t result = esp_now_send(peer_addr, (uint8_t*) &myData, sizeof(myData));
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) { // Invalid Argument
Serial.println("Invalid Argument");
} else if (result == ESP_ERR_ESPNOW_INTERNAL) { // Internal Error
Serial.println("Internal Error");
} else if (result == ESP_ERR_ESPNOW_NO_MEM) { // no mem
Serial.println("ESP_ERR_ESPNOW_NO_MEM");
} else if (result == ESP_ERR_ESPNOW_NOT_FOUND) { // peer not found
Serial.println("Peer not found.");
} else {
Serial.println("Not sure what happened");
}
}
void readAndReport() { // code by dw to get values, compare them and turn on LEDs as needed.
Serial.println("------------------- IN LOOP ");
int savedThreshHoldValue1; // intialize the variables used for calibration *************
int savedThreshHoldValue2;
int savedThreshHoldValue3;
int savedThreshHoldValue4;
int savedThreshHoldValue5;
// READ SENSOR THREASHOLD VALUES STORED AT LAST CALIBRATION. USED TO COMPARE TO CURRENT SENSOR READINGS
savedThreshHoldValue1 = preferences.getInt("sensor1", savedThreshHoldValue1);
savedThreshHoldValue2 = preferences.getInt("sensor2", savedThreshHoldValue2);
savedThreshHoldValue3 = preferences.getInt("sensor3", savedThreshHoldValue3);
savedThreshHoldValue4 = preferences.getInt("sensor4", savedThreshHoldValue4);
savedThreshHoldValue5 = preferences.getInt("sensor5", savedThreshHoldValue5);
Serial.print("====================saved value one ");
Serial.println(savedThreshHoldValue1);
delay(800);
currentSensorVal1 = touchRead(13); // read the sensors as the loop() iterates
delay(5);
currentSensorVal2 = touchRead(32); // watch for them to go below the stored threashold value
delay(5);
currentSensorVal3 = touchRead(15);
delay(5);
currentSensorVal4 = touchRead(12);
delay(5);
currentSensorVal5 = touchRead(33);
delay(5);
Serial.println("||||||||||||||||||||||||||||||||||||||||||||||||||||");
//Serial.println();
Serial.println(" SAVED CURRENT DIFFERENCE =================");
Serial.print("Value 1 > ");
Serial.print(savedThreshHoldValue1);
Serial.print("\t");
Serial.print(currentSensorVal1);
Serial.print("\t"); Serial.print("\t");
Serial.println(savedThreshHoldValue1 - currentSensorVal1);
Serial.print("Value 2 > ");
Serial.print(savedThreshHoldValue2);
Serial.print("\t");
Serial.print(currentSensorVal2);
Serial.print("\t"); Serial.print("\t");
Serial.println(savedThreshHoldValue2 - currentSensorVal2);
Serial.print("Value 3 > ");
Serial.print(savedThreshHoldValue3);
Serial.print("\t");
Serial.print(currentSensorVal3);
Serial.print("\t"); Serial.print("\t");
Serial.println(savedThreshHoldValue3 - currentSensorVal3);
Serial.print("Value 4 > ");
Serial.print(savedThreshHoldValue4);
Serial.print("\t");
Serial.print(currentSensorVal4);
Serial.print("\t"); Serial.print("\t");
Serial.println(savedThreshHoldValue4 - currentSensorVal4);
Serial.print("Value 5 > ");
Serial.print(savedThreshHoldValue5);
Serial.print("\t");
Serial.print(currentSensorVal5);
Serial.print("\t"); Serial.print("\t");
Serial.println(savedThreshHoldValue5 - currentSensorVal5);
/*
// Serial.print(" CURRENT value 3 > ");
Serial.println(currentSensorVal3);
// Serial.print(" SAVED Value 4 > ");
Serial.print(savedThreshHoldValue4);
Serial.print(" CURRENT value 4 > ");
Serial.println(currentSensorVal4);
Serial.print(" SAVED Value 5 > ");
Serial.print(savedThreshHoldValue5);
Serial.print(" CURRENT value 5 > ");
Serial.println(currentSensorVal5);
Serial.printf(" SAVED SAVED SAVED SAVED savedThreshHoldValue1 > %u\n", savedThreshHoldValue1);
Serial.printf(" SAVED SAVED SAVED SAVED savedThreshHoldValue1 > %u\n", savedThreshHoldValue2);
Serial.printf(" SAVED SAVED SAVED SAVED savedThreshHoldValue1 > %u\n", savedThreshHoldValue3);
Serial.printf(" SAVED SAVED SAVED SAVED savedThreshHoldValue1 > %u\n", savedThreshHoldValue4);
Serial.printf(" SAVED SAVED SAVED SAVED savedThreshHoldValue1 > %u\n", savedThreshHoldValue5);
Serial.println();
Serial.printf(" ################### CURRENTSensorVal1 >>>> %u\n", currentSensorVal1);
Serial.printf(" ################### CURRENTSensorVal2 >>>> %u\n", currentSensorVal2);
Serial.printf(" ################### CURRENTSensorVal3 >>>> %u\n", currentSensorVal3);
Serial.printf(" ################### CURRENTSensorVal4 >>>> %u\n", currentSensorVal4);
Serial.printf(" ################### CURRENTSensorVal5 >>>> %u\n", currentSensorVal5);
delay(500);
*/
int pinValue = digitalRead(26); // added to get button press up here
delay(10); // quick and dirty debounce filter
if (buttonStatus != pinValue) {
buttonStatus = pinValue;
Serial.println(buttonStatus);
}
if (buttonStatus == 0) {
// RUN FUNCTION
threshHoldValue1 = PushButtonToSetDrySensor1(); // WAS ORIGINAL run fuction to Capture 'dry' state then pad
}
// end -- added to get button press up here
Serial.print(" BUTTON STATUS IS >>>>> : ");
Serial.println(buttonStatus);
if (currentSensorVal1 <= savedThreshHoldValue1) {
Serial.println(" HIGH HIGH HIGH HIGH");
digitalWrite(21, HIGH);
l1 = 1;
} else {
Serial.println("LOW LOW LOW LOW LOW ");
digitalWrite(21, LOW);
l1 = 0;
}
if (currentSensorVal2 <= savedThreshHoldValue2) {
Serial.println(" HIGH HIGH HIGH HIGH");
digitalWrite(22, HIGH);
l2 = 1;
} else {
Serial.println("LOW LOW LOW LOW LOW ");
digitalWrite(22, LOW);
l2 = 0;
}
if (currentSensorVal3 <= savedThreshHoldValue3) {
Serial.println(" HIGH HIGH HIGH HIGH");
digitalWrite(23, HIGH);
l3 = 1;
} else {
Serial.println("LOW LOW LOW LOW LOW ");
digitalWrite(23, LOW);
l3 = 0;
}
if (currentSensorVal4 <= savedThreshHoldValue4) {
Serial.println(" HIGH HIGH HIGH HIGH");
digitalWrite(24, HIGH);
l4 = 1;
} else {
Serial.println("LOW LOW LOW LOW LOW ");
digitalWrite(24, LOW);
l4 = 0;
}
if (currentSensorVal5 <= savedThreshHoldValue5) {
Serial.println(" HIGH HIGH HIGH HIGH");
digitalWrite(25, HIGH);
l5 = 1;
} else {
Serial.println("LOW LOW LOW LOW LOW ");
digitalWrite(25, LOW);
l5 = 0;
}
Serial.print(" ########## The Current Sensor Value 1 >>>> ");
Serial.println(currentSensorVal1);
// delay(100);
}
// **************************************** FUNCTIONS *********************************************
// CALABRATION FUNCTION
int PushButtonToSetDrySensor1() { // PUSH BUTTON TO COLLECT CURRENT SENSOR VALUES AND SAVE TO NONVOLITIAL MEMORY
Serial.println("NOW INSIDE PushButtonToSetDrySensor1()");
delay(500);
threshHoldValue1 = currentSensorVal1 - padding; //sensor on analog in 0
threshHoldValue2 = currentSensorVal2 - padding;
threshHoldValue3 = currentSensorVal3 - padding;
threshHoldValue4 = currentSensorVal4 - padding;
threshHoldValue5 = currentSensorVal5 - padding;
Serial.println(" BUTTON IS PUSHED ================ ");
Serial.print(" VALUE OF threshHoldValue1 ====== ");
Serial.println(threshHoldValue1);
Serial.print(" VALUE OF threshHoldValueTWO == === ");
Serial.println(threshHoldValue2);
delay(500);
// save the threshHoldvalue in eeprom
dwEeprommRoutine(threshHoldValue1, threshHoldValue2, threshHoldValue3, threshHoldValue4, threshHoldValue5);
}
// FUNCTION ******************************* READ WRITE TO EEPROM FUCTION **************************
//void dwEeprommRoutine(int savedThreshHoldValue1, int savedThreshHoldValue2, int savedThreshHoldValue3, int savedThreshHoldValue4, int savedThreshHoldValue5)
void dwEeprommRoutine(int threshHoldValue1, int threshHoldValue2, int savedThreshHoldValue3, int savedThreshHoldValue4, int savedThreshHoldValue5)
{
Serial.println("IN EEPROM FUNCTION === IN EEPROM FUNCTION === ");
Serial.println("IN EEPROM FUNCTION === IN EEPROM FUNCTION === -");
Serial.println("IN EEPROM FUNCTION === IN EEPROM FUNCTION === --");
delay(500);
Serial.print(" threshHoldValue1 IN EEPROM +++++ ");
Serial.print(threshHoldValue1);
Serial.print(" threshHoldValue2 IN EEPROM +++++ ");
Serial.print(threshHoldValue2);
//delay(100);
//int maxx;
Serial.print(" this is threshHoldValue1 >>>>>>>#########>> ");
Serial.println(threshHoldValue1);
Serial.print(" this is threshHoldValueTWO >>>>>>>#########>> ");
Serial.println(threshHoldValue2);
Serial.print(" this is threshHoldValue3 >>>>>>>#########>> ");
Serial.println(threshHoldValue3);
Serial.print(" this is threshHoldValue4 >>>>>>>#########>> ");
Serial.println(threshHoldValue4);
Serial.print(" this is threshHoldValue5 >>>>>>>#########>> ");
Serial.println(threshHoldValue5);
delay(500);
int value = 1;
if (value == 1);
{// WRITE TO FLASH MEMOREY USING PREFERENCES FUCTION (REPLACED EEPROM FUNCTION)
preferences.putInt("sensor1", threshHoldValue1);
delay(50);
preferences.putInt("sensor2", threshHoldValue2);
delay(50);
preferences.putInt("sensor3", threshHoldValue3);
delay(50);
preferences.putInt("sensor4", threshHoldValue4);
delay(50);
preferences.putInt("sensor5", threshHoldValue5);
delay(50);
Serial.print("SAVED in Prefereces threshHoldValue1 >>> ");
Serial.println(threshHoldValue1);
Serial.print(" is SAVED threshHoldValue2 >>>####### ");
Serial.println(threshHoldValue2);
Serial.print(" is SAVED threshHoldValue3 >>>####### ");
Serial.println(threshHoldValue3);
Serial.print(" is SAVED threshHoldValue4 >>>####### ");
Serial.println(threshHoldValue4);
Serial.print(" is SAVED threshHoldValue5 >>>####### ");
Serial.println(threshHoldValue5);
//delay(3100);
}
}
// wifi code function from ESP32 code =================================================================
void setUpConnections() {
// bool setUpConnections() {
// 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();
// return isPaired;
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(1000);
}
// /*
//=============FUNCTION ======== calulate level and send to reciever ==========================
uint8_t SendPinData() {
//uint8_t data = 0;
if (l1 == 1 && l2 == 1) {data = 200; goto dwBreak;}
if (l1 == 0 && l2 == 1 && l3 == 1 ) { data = 180; goto dwBreak; }
if (l1 == 0 && l2 == 0 && l3 == 1 && l4 == 1 ) {data = 160; goto dwBreak; }
if (l1 == 0 && l2 == 0 && l3 == 0 && l4 == 1 && l5 == 1) { data = 140; goto dwBreak; }
if (l1 == 0 && l2 == 0 && l3 == 0 && l4 == 0 && l5 == 0) { data = 100;}
else { data = 50; }
dwBreak: // this is a LABLE . it seems it is created simply by using a colon ':'
Serial.printf(" DATA DATA DATA DATA DATA DATA ================ > %u\n", data);
return data;
}
// */
/** LED gauge display unit (the dumb one).
ESPNOW - Basic communication - Slave
Date: 26th September 2017
Author: Arvind Ravulavaru <https://github.com/arvindr21>
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 <esp_now.h>
#include <WiFi.h>
#define CHANNEL 1
// Init ESP Now with fallback
void InitESPNow() {
WiFi.disconnect();
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() {
const 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.print(" I am here ================================");
pinMode(21, OUTPUT);
pinMode(22, OUTPUT);
pinMode(23, OUTPUT);
pinMode(24, OUTPUT);
pinMode(25, OUTPUT);
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);
}
typedef struct struct_message {
// char dw_a[32];
// int dw_b;
// float dw_c;
// String d;
// int dw_d;
// bool dw_e;
// bool a;
// bool b;
// bool c;
//
// bool e;
int dw_1 = 1;
int dw_2 = 1;
int dw_3 = 1;
int dw_4 = 1;
int dw_5 = 1;
} struct_message;
struct_message myData;
// callback when data is recv from Master
//void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len) {
//void OnDataRecv(const uint8_t* mac_addr, const uint8_t* myData, int data_len) {
void OnDataRecv(const uint8_t* mac_addr, const uint8_t* incomingData, int len){
memcpy(&myData, incomingData, sizeof(myData));
Serial.print("Bytes received: ");
Serial.println(len);
// Serial.print("Char: ");
Serial.print("dw_1: ");
Serial.println(myData.dw_1);
Serial.print("dw_2: ");
Serial.println(myData.dw_2);
Serial.print("dw_3: ");
Serial.println(myData.dw_3);
Serial.print("dw_4 ");
Serial.println(myData.dw_4);
Serial.print("dw_5 ");
Serial.println(myData.dw_5);
if (myData.dw_1 == 1) { digitalWrite(21, HIGH);
Serial.print("dw_1: in if statement ");
Serial.println(myData.dw_1);
}
delay(500);
if (myData.dw_1 == 0) { digitalWrite(21, LOW);
Serial.print("dw_1: in if statment ");
Serial.println(myData.dw_1);
}
delay(500);
if (myData.dw_2 == 1) { digitalWrite(22, HIGH); }
if (myData.dw_3 == 1) { digitalWrite(23, HIGH); }
if (myData.dw_4 == 1) { digitalWrite(24, HIGH); }
if (myData.dw_5 == 1) { digitalWrite(25, HIGH); }
if (myData.dw_2 == 0) { digitalWrite(22, LOW); }
if (myData.dw_3 == 0) { digitalWrite(23, LOW); }
if (myData.dw_4 == 0) { digitalWrite(24, LOW); }
if (myData.dw_5 == 0) { digitalWrite(25, LOW); }
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.print("Last Packet Recv Data: "); Serial.println(myData);
Serial.println("");
Serial.println();
}
void loop() {
// Serial.print(" data without the * as whatever : "); Serial.println(data2);
// digitalWrite(21, HIGH);
// digitalWrite(21, LOW);
// delay(1000);
// digitalWrite(21, HIGH);
// delay(1000);
// Serial.print(" I am here ================================");
/*
if (*data = 200 ) {
digitalWrite(21, HIGH);
digitalWrite(22, HIGH);
digitalWrite(23, HIGH);
digitalWrite(24, HIGH);
digitalWrite(25, HIGH);
}
// Chill
*/
}