Esp32 tank sensor gauge, using Arduino framework, developed with visual
- 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 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
#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); }

Please share it. Thanks!
Originally published at https://prosperityconsulting.com on February 21, 2022.