- page one of this project
- Progress, but not there yet. Currently, it does the following.
- This is the master code, the slave code is separate.
- Queries up to three slave/sensor/sender units
- display the tank level readings on one set of 5 LEDs.
- A second set of 3 LEDs tells which tank is being read; 1, 2 or 3
- a request to calibrate the empty tank can be sent from the master.
- The MAC addresses of the slaves are collected. So far, only one MAC (of the master) has to be input into the code, the rest is automatic. I am working on getting the master MAC collected also.
- The system sends variables in both directions.
- The system uses the esp-now protocol,
- runs at 12 volts and should work on water, diesel, gasoline or black-water in a plastic tank (only tested with water so far).
- it uses aluminum tape as a sensor
- sensor/senders connected to the display via esp-now / Wi-Fi but no separate router is needed, the esp32 cards do it all
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
#include <esp_now.h>
#include <WiFi.h>
#define CHANNEL 1
byte paddingValue = 13;
int doCalibrate1 = 5;
byte chooseTank = 2;
String dw_M_SSID; // these vars are to capture the mac addresses of the slaves
String macCapture = "00";
String slaveOneMac = "00";
String slaveTwoMac = "00";
String slaveThreeMac = "00";
// Pins used 18, 19, 21, 22, 23 for level LEDs 26 for Calibrate switch 04 for calibrate indiscator
// // pins 32 33 inupt_pullup used for setting display to tank 1, 2, or 3 tank indicator LED 16, 17, (25)
int macLock1 = 1111; // 1111 is UNlocked 9999 is LOCKED
int macLock2 = 1111;
int macLock3 = 1111;
// REPLACE WITH THE MAC Address of your receiver - as this is the master it is using the broadcast-to-all 0xFF address
uint8_t broadcastAddress[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
//uint8_t broadcastAddress[] = { 0x30,0xC6,0xF7,0x05,0x9B,0x94 };
// MASTER - RECIVES DATA FROM THREE SLAVES AND SORTS THE DATA INTO THREE SERIAL OUTPUT DISPLAYS.
// This recives and labels them ONE TWO AND THREE
// IT IS DEPENDENT ON PUTTING THE RIGHT IDENTIFIER INTO the right var SUCH AS 949494 OR 707070 OR 787878
void InitESPNow() { // Init ESP Now with fallback
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 with indetifying mac
void configDeviceAP() {
String Prefix = "Master_dw:";
String Mac = WiFi.macAddress();
String SSID = Prefix + Mac;
String Password = "123456789";
bool result = WiFi.softAP(SSID.c_str(), Password.c_str(), CHANNEL, 0);
if (!result) {
Serial.println("AP Config failed.");
} else {
Serial.println("AP Config Success. Broadcasting with AP: " + String(SSID));
dw_M_SSID = String(SSID);
}
}
// Define variables to SEND to level sensor slaves
//int doCalibrate1;
//bool doCalibrate2;
//bool doCalibrate3;
//char dw_char[32];
// Define variables to store incoming readings
//int incomingDw_1;
//String incomingDw_s;
// Define variables to hold incoming incoming LED status readings
int incomingSlaveNumber;
int incomingSensorVarA1;
int incomingSensorVarA2;
int incomingSensorVarA3;
int incomingSensorVarA4;
int incomingSensorVarA5;
int incomingreSetCalFlagA;
int incomingSensorVarB1;
int incomingSensorVarB2;
int incomingSensorVarB3;
int incomingSensorVarB4;
int incomingSensorVarB5;
int incomingSensorVarC1;
int incomingSensorVarC2;
int incomingSensorVarC3;
int incomingSensorVarC4;
int incomingSensorVarC5;
String success; // Variable to store if sending data was successful
//Structure example to send data
//Must match the receiver structure
typedef struct struct_message {
int slaveNumber;
int sensor1;
int sensor2;
int sensor3;
int sensor4;
int sensor5;
char dw_char[32];
byte dw_pad;
int doCalibrate1;
int doCalibrate2;
int doCalibrate3;
} struct_message;
// Create a struct_message called BME280Readings to hold VARIABLES TO SEND TO SLAVES
struct_message outgoingMasterToSlave;
// Create a struct_message to hold incoming sensor readings
struct_message incomingFromSlaves;
// Callback when data is sent
void OnDataSent(const uint8_t* mac_addr, esp_now_send_status_t status) {
Serial.print("\r\nLast Packet Send Status:\t");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
if (status == 0) {
success = "Delivery Success :)";
String Mac = WiFi.macAddress();
Serial.println("AP Config Success. Broadcasting from MASTER with AP: " + String(Mac));
} else {
success = " OUTGOING DELIVER FAIL FAIL FAIL FAIL FAIL Delivery Fail :(";
}
/*
if (status == 0) {
success = "Delivery Success :)";
} else {
success = "Delivery Fail :(";
}
*/
}
// Callback when data is received
void OnDataRecv(const uint8_t* mac, const uint8_t* incomingData, int len) {
memcpy(&incomingFromSlaves, incomingData, sizeof(incomingFromSlaves));
char macStr[18];
snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
Serial.print("Bytes received: ");
Serial.println(len);
Serial.print("////////////// Last Packet Recv from: "); Serial.println(macStr);
Serial.print("Last Packet Recv Data: "); Serial.println(*incomingData);
Serial.print("Bytes received: ");
Serial.println(len);
macCapture = macStr;
if (incomingFromSlaves.slaveNumber == 949494 && chooseTank == 1) {
incomingSlaveNumber = incomingFromSlaves.slaveNumber;
incomingSensorVarA1 = incomingFromSlaves.sensor1;
incomingSensorVarA2 = incomingFromSlaves.sensor2;
incomingSensorVarA3 = incomingFromSlaves.sensor3;
incomingSensorVarA4 = incomingFromSlaves.sensor4;
incomingSensorVarA5 = incomingFromSlaves.sensor5;
updateDisplay1();
delay(20);
if (incomingSensorVarA1 == 1) {
digitalWrite(18, HIGH); }
if (incomingSensorVarA1 == 0) {
digitalWrite(18, LOW); }
if (incomingSensorVarA2 == 1) {
digitalWrite(19, HIGH); }
if (incomingSensorVarA2 == 0) {
digitalWrite(19, LOW);
}
if (incomingSensorVarA3 == 1) {
digitalWrite(21, HIGH); }
if (incomingSensorVarA3 == 0) {
digitalWrite(21, LOW);
}
if (incomingSensorVarA4 == 1) {
digitalWrite(22, HIGH); }
if (incomingSensorVarA4 == 0) {
digitalWrite(22, LOW);
}
if (incomingSensorVarA5 == 1) {
digitalWrite(23, HIGH); }
if (incomingSensorVarA5 == 0) {
digitalWrite(23, LOW);
}
}
if (incomingFromSlaves.slaveNumber == 707070 && chooseTank == 2) {
incomingSlaveNumber = incomingFromSlaves.slaveNumber;
incomingSensorVarB1 = incomingFromSlaves.sensor1;
incomingSensorVarB2 = incomingFromSlaves.sensor2;
incomingSensorVarB3 = incomingFromSlaves.sensor3;
incomingSensorVarB4 = incomingFromSlaves.sensor4;
incomingSensorVarB5 = incomingFromSlaves.sensor5;
updateDisplay2();
delay(200);
if (incomingSensorVarB1 == 1) {
digitalWrite(18, HIGH);
}
if (incomingSensorVarB1 == 0) {
digitalWrite(18, LOW);
}
if (incomingSensorVarB2 == 1) {
digitalWrite(19, HIGH);
}
if (incomingSensorVarB2 == 0) {
digitalWrite(19, LOW);
}
if (incomingSensorVarB3 == 1) {
digitalWrite(21, HIGH);
}
if (incomingSensorVarB3 == 0) {
digitalWrite(21, LOW);
}
if (incomingSensorVarB4 == 1) {
digitalWrite(22, HIGH);
}
if (incomingSensorVarB4 == 0) {
digitalWrite(22, LOW);
}
if (incomingSensorVarB5 == 1) {
digitalWrite(23, HIGH);
}
if (incomingSensorVarB5 == 0) {
digitalWrite(23, LOW);
}
//}
}
if (incomingFromSlaves.slaveNumber == 787878 && chooseTank ==3 ) {
incomingSlaveNumber = incomingFromSlaves.slaveNumber;
incomingSensorVarC1 = incomingFromSlaves.sensor1;
incomingSensorVarC2 = incomingFromSlaves.sensor2;
incomingSensorVarC3 = incomingFromSlaves.sensor3;
incomingSensorVarC4 = incomingFromSlaves.sensor4;
incomingSensorVarC5 = incomingFromSlaves.sensor5;
updateDisplay3();
delay(200);
if (incomingSensorVarC1 == 1) {
digitalWrite(18, HIGH);
}
if (incomingSensorVarC1 == 0) {
digitalWrite(18, LOW);
}
if (incomingSensorVarC2 == 1) {
digitalWrite(19, HIGH);
}
if (incomingSensorVarC2 == 0) {
digitalWrite(19, LOW);
}
if (incomingSensorVarC3 == 1) {
digitalWrite(21, HIGH);
}
if (incomingSensorVarC3 == 0) {
digitalWrite(21, LOW);
}
if (incomingSensorVarC4 == 1) {
digitalWrite(22, HIGH);
}
if (incomingSensorVarC4 == 0) {
digitalWrite(22, LOW);
}
if (incomingSensorVarC5 == 1) {
digitalWrite(23, HIGH);
}
if (incomingSensorVarC5 == 0) {
digitalWrite(23, LOW);
}
}
// }
}
unsigned long previousMillis = 0; // will store last time LED was updated
const long interval = 10000;
void setup() {
Serial.print(" I am here IN SETUP() ================================");
delay(200);
Serial.begin(115200);
pinMode(26, INPUT_PULLUP); // enable internal pull-up for calibration pushbutton
pinMode(32, INPUT_PULLUP); // for chooseTank switch
pinMode(33, INPUT_PULLUP); // for chooseTank switch
pinMode(4, OUTPUT); // this is for LED that indicates button has been pressed long enough
//digitalWrite(4, HIGH);
pinMode(18, OUTPUT);
pinMode(19, OUTPUT);
pinMode(21, OUTPUT);
pinMode(22, OUTPUT);
pinMode(23, OUTPUT);
WiFi.mode(WIFI_AP_STA); // configure device AP mode
configDeviceAP();
if (esp_now_init() != ESP_OK) { // Init ESP-NOW Set device as a Wi-Fi Station
Serial.println("Error initializing ESP-NOW");
return;
}
esp_now_register_send_cb(OnDataSent); // register for Send CB to get the status of Trasnmitted packet
esp_now_peer_info_t peerInfo; // Register peer
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
if (esp_now_add_peer(&peerInfo) != ESP_OK) { // Add peer
Serial.println("Failed to add peer");
return;
}
esp_now_register_recv_cb(OnDataRecv);// Register callback function that is called when data is received
}
void loop() { // *************************** start loop *******************************
Serial.println("// ********* this is the start of looop *****************************");
// chooseTank
if (digitalRead(32) == 0 && (digitalRead(33) == 0)) { chooseTank = 1; }
if (digitalRead(32) == 1 && (digitalRead(33) == 1)) { chooseTank = 2; }
if (digitalRead(32) == 0 && (digitalRead(33) == 1)) { chooseTank = 3; }
if (digitalRead(32) == 1 && (digitalRead(33) == 0)) { chooseTank = 3; }
Serial.print(" chooseTank value >>>> : ");
Serial.println(chooseTank);
// part of set mac of slave function
setMacOfSlave();
delay(5000); // to be able to read the message
// change to function below
delay(100); // this is here so screen can be read
readPushButton(); // see if "calibrate" button is pressed
valuesToSend(); // get the values to send
Serial.print("sending padding and doCalibrate >>>>>> : ");
Serial.print(outgoingMasterToSlave.dw_pad);
Serial.print(" <<<<<< >>> ");
Serial.print(outgoingMasterToSlave.doCalibrate1);
Serial.println(" <<<<<< ");
delay(1000); // to be able to read the message
sendMessageToSlaves(); // send the message to the slave with esp-now
//---------------------------123456789-123456789-123456789-1
// strcpy(outgoingMasterToSlave.dw_s, "FROM Master / LED display unit:"); // NO MORE THAN 31 CHARACTORS
} // ********************************** end loop **************************************************
void setMacOfSlave() {
if (slaveOneMac == "00") { slaveOneMac = macCapture; macLock1 = 9999; } delay(50); // set one
if (slaveTwoMac == "00" && macLock1 == 9999 && macCapture != slaveOneMac) { slaveTwoMac = macCapture; macLock2 = 9999; } delay(50); // set two
if (slaveTwoMac != "00" && macLock2 == 9999 && macLock1 == 9999 && macCapture != slaveOneMac && macCapture != slaveTwoMac) { slaveThreeMac = macCapture; macLock3 = 9999; } delay(50);
Serial.print(" Value of dw_ssid >>>> ");
Serial.println(dw_M_SSID);
Serial.println(" ");
Serial.print(" Value of xxx>>>> ");
Serial.println(macCapture);
Serial.println(incomingSlaveNumber);
Serial.print(" Value of one >>>> ");
Serial.println(slaveOneMac);
Serial.println(incomingSlaveNumber);
Serial.print(" Value of two>>>> ");
Serial.println(slaveTwoMac);
Serial.println(incomingSlaveNumber);
Serial.print(" Value of three>>>> ");
Serial.println(slaveThreeMac);
Serial.println(incomingSlaveNumber);
if (slaveOneMac != "00" && slaveTwoMac != "00" && slaveThreeMac != "00") {
Serial.println(" ");
Serial.println("********************** WE CAN SAVE THIS *******************************");
}
}
// Serial.println("//////****** &&& this is in a function &&&&&&&&&&&&&&&&&&&");
//}
void readPushButton() {
if (digitalRead(26) == 0) {
digitalWrite(4, HIGH); // blink an LED to show request has be registered
digitalWrite(4, HIGH); delay(500); digitalWrite(4, LOW); delay(300); digitalWrite(4, HIGH); delay(300);
digitalWrite(4, LOW); delay(300); digitalWrite(4, HIGH); delay(300); digitalWrite(4, LOW); delay(300);
digitalWrite(4, HIGH); delay(300); digitalWrite(4, LOW);
doCalibrate1 = 9999;
Serial.print(" inside readPushButton() function Value of doCalibrate1 >>>> ");
Serial.println(doCalibrate1);
delay(500); // to be able to read the message
Serial.print(" Value of doCalibrate1 >>>> ");
Serial.println(doCalibrate1);
delay(500); // to be able to read the message
}
// readPushButton(); // see if "calibrate" button is pressed
/* if (digitalRead(26) == 0) {
digitalWrite(4, HIGH); delay(500); digitalWrite(4, LOW); delay(500); digitalWrite(4, HIGH); delay(500); digitalWrite(4, LOW); delay(500); digitalWrite(4, HIGH);
}
// blink an LED to show request has be registered
digitalWrite(4, HIGH); delay(500); digitalWrite(4, LOW); delay(300); digitalWrite(4, HIGH); delay(300);
digitalWrite(4, LOW); delay(300); digitalWrite(4, HIGH); delay(300); digitalWrite(4, LOW); delay(300);
digitalWrite(4, HIGH); delay(300); digitalWrite(4, LOW);
// sendMessageToSlaves();
*/
} // end of read pushbutton
void valuesToSend() { // READING TO SEND TO SLAVE
outgoingMasterToSlave.dw_pad = paddingValue;
outgoingMasterToSlave.doCalibrate1 = doCalibrate1;
//incomingreSetCalFlagA;
}
// Send the message from Master to Slave via ESP-NOW
void sendMessageToSlaves() {
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t*)&outgoingMasterToSlave, sizeof(outgoingMasterToSlave));
if (result == ESP_OK) { // If the message was recived by the slave, do the following
Serial.println("*************** SENT MESSEGE TO SLAVE with success ******************************");
if (outgoingMasterToSlave.doCalibrate1 == 9999) { // if the "calibrate" is 0, change to 1
doCalibrate1 = 1111;
}
Serial.print(">>>>>>>>>>>>>>>> outgoingMasterToSlave.requestToCalibrateSensors = ");
Serial.println(outgoingMasterToSlave.doCalibrate1);
} else {
Serial.println("Error sending the data");
delay(1000); // allow time to read the message
}
delay(150); // allow time to read the message
}
void updateDisplay1() { // create function Display Readings in Serial Monitor
String Mac = WiFi.macAddress();
// Serial.print("MAC OF THE MASTER CARD ===================== : ");
// Serial.println(Mac);
Serial.println("======== THIS IS THE MASTER AND LED DISPLAY >>111 ONE 111<< ====== (14)");
Serial.print("incomingSensorVarA1: ");
Serial.println(incomingSensorVarA1);
Serial.print("incomingSensorVarA2: ");
Serial.println(incomingSensorVarA2);
Serial.print("incomingSensorVarA3: ");
Serial.println(incomingSensorVarA3);
Serial.print("incomingSensorVarA4 : ");
Serial.println(incomingSensorVarA4);
Serial.print("incomingSensorVarA5 : ");
Serial.println(incomingSensorVarA5);
Serial.print(" ////////// Start of loop -- doCalibrate1 = : "); Serial.println(doCalibrate1);
Serial.print(" digitalRead(26) ==== : "); Serial.println(digitalRead(26));
//Serial.print(" BUTTON STATUS IS >>>>> : "); Serial.println(pinValue);
// Serial.print(" outgoing From Master To Slave.reSetCalFlag IS >>> : ");
// Serial.println(outgoingMasterToSlave.requestToCalibrateSensors);
}
void updateDisplay2() { // create function to Display Readings in Serial Monitor
String Mac = WiFi.macAddress();
Serial.print("MAC OF THE MASTER CARD ===================== : ");
Serial.println(Mac);
Serial.println("== THIS IS THE MASTER AND LED DISPLAY >>TWO<< ");
Serial.print("incomingSensorVarB1: ");
Serial.println(incomingSensorVarB1);
Serial.print("incomingSensorVarB2: ");
Serial.println(incomingSensorVarB2);
Serial.print("incomingSensorVarB3: ");
Serial.println(incomingSensorVarB3);
Serial.print("incomingSensorVarB4 : ");
Serial.println(incomingSensorVarB4);
Serial.print("incomingSensorVarB5 : ");
Serial.println(incomingSensorVarB5);
}
void updateDisplay3() { // create function Display Readings in Serial Monitor
String Mac = WiFi.macAddress();
Serial.print("MAC OF THE MASTER CARD ===================== : ");
Serial.println(Mac);
Serial.println("== THIS IS THE MASTER AND LED DISPLAY >>333 THREE 333<< ");
Serial.print("incomingSensorVarC1: ");
Serial.println(incomingSensorVarC1);
Serial.print("incomingSensorVarC2: ");
Serial.println(incomingSensorVarC2);
Serial.print("incomingSensorVarC3: ");
Serial.println(incomingSensorVarC3);
Serial.print("incomingSensorVarC4 ");
Serial.println(incomingSensorVarC4);
Serial.print("incomingSensorVarC5: ");
Serial.println(incomingSensorVarC5);
}