Hello All,
I have been trying to create a project to control my Water pump based on sensor inputs and user inputs.
Hardware used is ESP32
Blynk Library version: 1.3.2
Issue:
When I run the hardware for several hours, the ESP32 stops getting commands from the blynk server (Like to turn on the motor or to turn on the lights) whereas the ESP32 keeps sending the sensed value to the server and also its uptime counter is seen to be updating correctly on the blynk dashboard.
I tried to add reconnection code but no luck.
Following is the code that is running on the ESP.
Any help would be greatly appreciated
//#define BLYNK_TEMPLATE_ID "TMPxxxxxx"
//#define BLYNK_TEMPLATE_NAME "Device"
/*************************************************************
Water Control App Light with L&T Controller v1.0
*************************************************************/
#define BLYNK_TEMPLATE_ID "TMPxxxxxx"
#define BLYNK_TEMPLATE_NAME "Device"
/*Uncomment the next line to turn ON Debug serial messages*/
//#define DebugON
#define MotorControlRelay 15
#define LnTControllerRelay 5
#define LightControlRelay 19
/* Comment this out to disable prints and save space */
#ifdef DebugON
#define BLYNK_PRINT Serial
#endif
#define CLEAR 0x00
#define UPDATED 0x01
#define ON 0x01
#define OFF 0x00
#define RESET 0x02
#define RELAY_ON 0x00
#define RELAY_OFF 0x01
#define LNT_CONTROLLER_ON 0x00
#define LNT_CONTROLLER_OFF 0x02
#define MOTOR_MODE_AUTO 0x02
#define MOTOR_MODE_OFF 0x01
#define MOTOR_MODE_ON 0x00
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <HardwareSerial.h>
/*A02YYUW Waterproof Ultrasonic Distance Sensor (3~450cm, UART, IP67)*/
HardwareSerial SerialPort(2); // use UART2
#define TankHeight 212 // in cm
#define TankWidth 182 //in cm
#define TankLength 335 //in cm
#define SensorHeight 20 // Dead zone of sensor in cm
// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "xxxx";
char pass[] = "xxxx";
int prevDistance;
float UG_WaterLevel;
float UG_WaterLevel_Percentage;
int UG_WaterInLitre;
int LightSwitchState_u8 = 0x00;
int LnTSwitchState_u8 = 0x00;
int MotorSwitchState_u8 = 0x00;
int InvaliCount = 0x00;
byte isUpdate_LightSwitch = 0x00;
byte isUpdate_LnTSwitch = 0x00;
byte isUpdate_MotorSwitch = 0x00;
int ReCnctFlag; // Reconnection Flag
int ReCnctCount = 0; // Reconnection counter
BlynkTimer timer;
void setup()
{
Serial.begin(115200);
SerialPort.begin(9600, SERIAL_8N1, 16, 17);
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
Serial.println("Water Control App Light with L&T Controller v1.0");
timer.setInterval(1000L, CyclicFunc_1);
timer.setInterval(250L, CyclicFunc_2);
timer.setInterval(1000, CyclicFunc_3);
pinMode(LightControlRelay, OUTPUT);
pinMode(LnTControllerRelay, OUTPUT);
pinMode(MotorControlRelay, OUTPUT);
digitalWrite(LightControlRelay, HIGH);
digitalWrite(LnTControllerRelay, HIGH);
digitalWrite(MotorControlRelay, HIGH);
Serial.println("Setup Complete");
}
// This function is called every time the device is connected to the Blynk.Cloud
BLYNK_CONNECTED()
{
Serial.println("Device D0 connected to Server");
Blynk.syncVirtual(0);
Blynk.syncVirtual(1);
Blynk.syncVirtual(10);
}
/*This function will be called every 1 second cyclically*/
void CyclicFunc_1()
{
// You can send any value at any time.
// Please don't send more that 10 values per second.
Blynk.virtualWrite(V18, millis() / 1000);
}
/********************************************************************************************************************************/
void CyclicFunc_2()
{
/*Check if light switch state has been updated*/
if(UPDATED == isUpdate_LightSwitch)
{
/*Check if Switch was turned ON*/
if(ON == LightSwitchState_u8)
{
#ifdef DebugON
Serial.println("Light ON request Received");
#endif
digitalWrite(LightControlRelay, RELAY_ON);
}
else
{
#ifdef DebugON
Serial.println("Light OFF request Received");
#endif
digitalWrite(LightControlRelay, RELAY_OFF);
}
isUpdate_LightSwitch = CLEAR;
}
/********************************************************************************************************************************/
/*Check if L&T Controller switch state has been updated*/
if(UPDATED == isUpdate_LnTSwitch)
{
/*L&T controller is connected to NC terminal of relay, So keeping the relay off means Controller is ON*/
/*0x00 - Keep relay OFF means L&T controller is ON
0x01 - Safe state do nothing
0x02 - Reset the L&T Controller OR turn theL&T Controller OFF by turning ON the relay*/
if(LNT_CONTROLLER_ON == LnTSwitchState_u8)
{
#ifdef DebugON
/*Make Relay OFF as L&T Controller is connected to NC*/
Serial.println("L&T Controller ON request Received - Relay State OFF");
#endif
digitalWrite(LnTControllerRelay, RELAY_OFF);
}
else if (LNT_CONTROLLER_OFF == LnTSwitchState_u8)
{
#ifdef DebugON
/*Make Relay ON so L&T controller turns OFF*/
Serial.println("L&T Controller OFF request Received - Relay State ON");
#endif
digitalWrite(LnTControllerRelay, RELAY_ON);
}
else
{
/*Do Nothing*/
}
isUpdate_LnTSwitch = CLEAR;
}
/*Check if Motor Control switch state has been updated*/
if(UPDATED == isUpdate_MotorSwitch)
{
if(MOTOR_MODE_OFF == MotorSwitchState_u8)
{
#ifdef DebugON
Serial.println("Motor OFF request Received");
#endif
digitalWrite(MotorControlRelay, RELAY_OFF);
Blynk.virtualWrite(V3, OFF);
}
else if(MOTOR_MODE_ON == MotorSwitchState_u8)
{
#ifdef DebugON
Serial.println("Motor ON request Received");
#endif
digitalWrite(MotorControlRelay, RELAY_ON);
Blynk.virtualWrite(V3, ON);
}
else
{
/*Do Nothing*/
}
isUpdate_MotorSwitch = CLEAR;
}
}
/********************************************************************************************************************************/
/*This function will be called every 1 second cyclically*/
void CyclicFunc_3()
{
int distance;
byte startByte, h_data, l_data, sum = 0;
byte buf[3];
int cnt=0;
while((SerialPort.read()==0xff) && (cnt < 50))
{
for(int i=0;i<3;i++)
{
buf[i]=SerialPort.read();
}
cnt++;
startByte = 0xFF; //(byte)SerialPort.read();
}
#ifdef DebugON
Serial.println(cnt);
#endif
if(startByte == 0xFF)
{
h_data = buf[0];
l_data = buf[1];
sum = buf[2];
distance = (h_data<<8) + l_data;
/*Converting Distance to cm*/
distance = distance/10;
/*Check if checksum matches*/
if(((startByte + h_data + l_data)&0xFF) != sum)
{
/*Checksum mismatch*/
#ifdef DebugON
Serial.println("Invalid result");
Serial.println(startByte);
Serial.println(h_data);
Serial.println(l_data);
Serial.println(sum);
#endif
InvaliCount++;
#ifdef DebugON
Serial.print("Invalid count: ");
Serial.println(InvaliCount);
#endif
//if (InvaliCount == 30)
//{
// InvaliCount = 0x00;
//}
}
else
{
//InvaliCount = 0x00;
if(prevDistance != distance)
{
prevDistance = distance;
//Serial.print("Distance: ");
//Serial.print(distance);
//Serial.println(" mm");
#ifdef DebugON
Serial.print("Distance: ");
Serial.print(distance);
Serial.println(" cm");
#endif
/*Calculate water height from the sensed hieght
Sensed height is the empty part of the tank,
so it is substracted from total height of the tank,
and the sensor dead zone or the height of the sensor from actual full tank
is also substracted. Dead zone of A02YYUW is 3cm so sensor is places atleast 3cm above sensing height */
UG_WaterLevel = TankHeight - (distance - SensorHeight);
/* Calculate total water quantity % */
UG_WaterLevel_Percentage = ((UG_WaterLevel/TankHeight)*100);
/*Volume of a cube = L*W*H*/
UG_WaterInLitre = TankLength * TankWidth * UG_WaterLevel;
/*Convert cm3 to liter OR mm3 to liter
(multiply the given value of cubic centimeters cm3 by a factor of 0.001 OR divide by 1000)
(multiply the given value of cubic Millimeters mm3 by a factor of 0.000001)*/
UG_WaterInLitre = UG_WaterInLitre/1000;
#ifdef DebugON
Serial.println("Change detected");
#endif
Blynk.virtualWrite(V5, UG_WaterLevel_Percentage);
Blynk.virtualWrite(V15, UG_WaterInLitre);
#ifdef DebugON
Serial.print("UG_WaterLevel_Percentage: ");
Serial.println(UG_WaterLevel_Percentage);
Serial.print("UG_WaterLevel: ");
Serial.println(UG_WaterLevel);
Serial.print("UG_WaterInLitre: ");
Serial.println(UG_WaterInLitre);
#endif
}
else
{
/*No Change in water level*/
}
}
}
else
{
#ifdef DebugON
Serial.println("Missed");
#endif
}
}
/********************************************************************************************************************************/
void resetMCU()
{
ESP.restart();
for (;;) {}
}
/********************************************************************************************************************************/
BLYNK_WRITE(InternalPinDBG)
{
if (String(param.asStr()) == "reboot") {
Serial.println("Rebooting...");
// TODO: Perform any neccessary preparation here,
// i.e. turn off peripherals, write state to EEPROM, etc.
// NOTE: You may need to defer a reboot,
// if device is in process of some critical operation.
resetMCU();
}
}
/*This Function will be called when switch state is updated for Light Control*/
BLYNK_WRITE(V10)
{
LightSwitchState_u8 = param.asInt();
isUpdate_LightSwitch = UPDATED;
}
/*This Function will be called when switch state is updated for L&T Controller*/
BLYNK_WRITE(V1)
{
LnTSwitchState_u8 = param.asInt();
isUpdate_LnTSwitch = UPDATED;
}
/*This Function will be called when switch state is updated for L&T Controller*/
BLYNK_WRITE(V0)
{
MotorSwitchState_u8 = param.asInt();
isUpdate_MotorSwitch = UPDATED;
}
void loop()
{
timer.run();
if (Blynk.connected())
{
Blynk.run();
}
else if (ReCnctFlag == 0)
{
ReCnctFlag = 1; // Set reconnection Flag
Serial.println("Starting reconnection timer in 15 seconds...");
timer.setTimeout(15000L, []() { // Lambda Reconnection Timer Function
ReCnctFlag = 0; // Reset reconnection Flag
ReCnctCount++; // Increment reconnection Counter
Serial.print("Attempting reconnection #");
Serial.println(ReCnctCount);
Blynk.connect(); // Try to reconnect to the server
}); // END Timer Functio
}
}