// App on phone has three buttons:
// Button 1: 11 for ON and 10 for OFF
// Button 2: 21 for ON and 20 for OFF
// Button 3: 31 for ON and 30 for OFF
//
//**********************************************************************//
#include <EEPROM.h>
#include "ESP32TimerInterrupt.h"
#include "BluetoothSerial.h"
// init Class:
//BluetoothSerial ESP_BT; // *use this when Actual Bluetooth device will connect
String Rec_string;
uint8_t Relay_value;
String TON_H_val1;
String TON_M_val1;
String TON_S_val1;
String TOFF_H_val1;
String TOFF_M_val1;
String TOFF_S_val1;
//*******************************Timer Variable********************//
hw_timer_t * timer1 = NULL;
hw_timer_t * timer2 = NULL;
hw_timer_t * timer3 = NULL;
portMUX_TYPE timerMux0 = portMUX_INITIALIZER_UNLOCKED;
portMUX_TYPE timerMux1 = portMUX_INITIALIZER_UNLOCKED;
portMUX_TYPE timerMux2 = portMUX_INITIALIZER_UNLOCKED;
/*****************************Global variable************************/
uint8_t Ton1_HH=0,Ton1_MM=0,Ton1_SS,Toff1_HH=0,Toff1_MM=0,Toff1_SS =0;
uint8_t Ton2_HH=0,Ton2_MM=0,Ton2_SS=0,Toff2_HH=0,Toff2_MM=0,Toff2_SS =0;
uint8_t Ton3_HH=0,Ton3_MM=0,Ton3_SS=0,Toff3_HH=0,Toff3_MM=0,Toff3_SS =0;
volatile int8_t time_H1=0,time_M1=0,time_S1=0;
volatile int8_t time_H2=0,time_M2=0,time_S2=0;
volatile int8_t time_H3=0,time_M3=0,time_S3=0;
bool Flag_on_off_Timer= 1; //0 -> Qucik Mode on/off 1-> Timer Mode
bool Previous_Flag1=1;
bool Previous_Flag2=1;
bool Previous_Flag3=1;
bool Timer1_Flag=0; // if 0 then TON, else TOFF
bool Timer2_Flag=0; // if 0 then TON, else TOFF
bool Timer3_Flag=0; // if 0 then TON, else TOFF
/******************************************************************/
#define EEPROM_SIZE 20
#define Flag_On_Off_Timer_Addr 0
#define Ton1_HH_Addr 1
#define Ton1_MM_Addr 2
#define Ton1_SS_Addr 3
#define Toff1_HH_Addr 4
#define Toff1_MM_Addr 5
#define Toff1_SS_Addr 6
#define Ton2_HH_Addr 8
#define Ton2_MM_Addr 8
#define Ton2_SS_Addr 9
#define Toff2_HH_Addr 10
#define Toff2_MM_Addr 11
#define Toff2_SS_Addr 12
#define Ton3_HH_Addr 13
#define Ton3_MM_Addr 14
#define Ton3_SS_Addr 15
#define Toff3_HH_Addr 16
#define Toff3_MM_Addr 17
#define Toff3_SS_Addr 18
#define TIMER1_INTERVAL_MS 1000
#define TIMER2_INTERVAL_MS 1000
#define TIMER3_INTERVAL_MS 1000
#define Relay1 23
#define Relay2 22
#define Relay3 21
void IRAM_ATTR onTimer1()
{
portENTER_CRITICAL_ISR(&timerMux0);
time_S1 = time_S1-1;
if(time_S1<0)
{time_S1=59; time_M1 = time_M1-1;}
if(time_M1<0)
{time_M1=59; time_H1 = time_H1-1;}
if(time_S1==59 && time_M1==59 && time_H1<0) //when TON Time completed
{time_S1=0;time_M1=0;time_H1=0;Timer1_Flag=!Timer1_Flag;}// setting flag for load the TOFF time
portEXIT_CRITICAL_ISR(&timerMux0);
}
void IRAM_ATTR onTimer2()
{
portENTER_CRITICAL_ISR(&timerMux1);
time_S2 = time_S2-1;
if(time_S2<0)
{time_S2=59; time_M2 = time_M2-1;}
if(time_M2<0)
{time_M2=59; time_H2 = time_H2-1;}
if(time_S2==59 && time_M2==59 && time_H2<0) //when TON Time completed
{time_S2=0;time_M2=0;time_H2=0;Timer2_Flag=!Timer2_Flag;} // setting flag for load the TOFF time
portEXIT_CRITICAL_ISR(&timerMux1);
}
void IRAM_ATTR onTimer3()
{
portENTER_CRITICAL_ISR(&timerMux2);
time_S3 = time_S3-1;
if(time_S3<0)
{time_S3=59; time_M3 = time_M3-1;}
if(time_M3<0)
{time_M3=59; time_H3 = time_H3-1;}
if(time_S3==59 && time_M3==59 && time_H3<0) //when TON Time completed
{time_S3=0;time_M3=0;time_H3=0;Timer3_Flag=!Timer3_Flag;}
portEXIT_CRITICAL_ISR(&timerMux2);
}
void EEPROM_Read_Timer_HH_MM_SS_1()
{
/*****************************Reading Ton1/Toff1 Time from EEPROM*********************/
Ton1_HH=EEPROM.read(Ton1_HH_Addr);
Ton1_MM=EEPROM.read(Ton1_MM_Addr);
Ton1_SS=EEPROM.read(Ton1_SS_Addr);
if( Ton1_HH>99 )
Ton1_HH = 0;
if(Ton1_MM>60)
Ton1_MM=0;
if(Ton1_SS>60)
Ton1_SS=0;
/*****************************Reading Ton1/Toff1 Time from EEPROM*********************/
Toff1_HH=EEPROM.read(Toff1_HH_Addr);
Toff1_MM=EEPROM.read(Toff1_MM_Addr);
Toff1_SS=EEPROM.read(Toff1_SS_Addr);
if( Toff1_HH>99 )
Toff1_HH = 0;
if(Toff1_MM>60)
Toff1_MM=0;
if(Toff1_SS>60 )
Toff1_SS=0;
}
void EEPROM_Read_Timer_HH_MM_SS_2()
{
/*****************************Reading Ton2/Toff2 Time from EEPROM*********************/
Ton2_HH=EEPROM.read(Ton2_HH_Addr);
Ton2_MM=EEPROM.read(Ton2_MM_Addr);
Ton2_SS=EEPROM.read(Ton2_SS_Addr);
if( Ton2_HH>99 )
Ton2_HH = 0;
if(Ton2_MM>60)
Ton2_MM=0;
if(Ton2_SS>60 )
Ton2_SS=0;
/*****************************Reading Ton2/Toff2 Time from EEPROM*********************/
Toff2_HH=EEPROM.read(Toff2_HH_Addr);
Toff2_MM=EEPROM.read(Toff2_MM_Addr);
Toff2_SS=EEPROM.read(Toff2_SS_Addr);
if( Toff2_HH>99 )
Toff2_HH = 0;
if(Toff2_MM>60)
Toff2_MM=0;
if(Toff2_SS>60 )
Toff2_SS=0;
}
void EEPROM_Read_Timer_HH_MM_SS_3()
{
/*****************************Reading Ton3/Toff3 Time from EEPROM*********************/
Ton2_HH=EEPROM.read(Ton2_HH_Addr);
Ton2_MM=EEPROM.read(Ton2_MM_Addr);
Ton2_SS=EEPROM.read(Ton2_SS_Addr);
/*****************************Reading Ton3/Toff3 Time from EEPROM*********************/
Toff3_HH=EEPROM.read(Toff3_HH_Addr);
Toff3_MM=EEPROM.read(Toff3_MM_Addr);
Toff3_SS=EEPROM.read(Toff3_SS_Addr);
if( Toff3_HH>99 )
Toff3_HH = 0;
if(Toff3_MM>60)
Toff3_MM=0;
if(Toff3_SS>60 )
Toff3_SS=0;
}
void EEPROM_Save_Data(int Data, int Addr)
{
EEPROM.write(Addr, Data);
EEPROM.commit();
}
//***************Function to get the value between special Character***********//
String getValue(String data, char separator, int index)
{
int found = 0;
int strIndex[] = { 0, -1 };
int maxIndex = data.length() - 1;
for (int i = 0; i <= maxIndex && found <= index; i++) {
if (data.charAt(i) == separator || i == maxIndex) {
found++;
strIndex[0] = strIndex[1] + 1;
strIndex[1] = (i == maxIndex) ? i+1 : i;
}
}
return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}
//***********************************************************************
void setup() {
Serial.begin(115200);
//ESP_BT.begin("Relay_Control"); // *use this when Actual Bluetooth device will connect
EEPROM.begin(EEPROM_SIZE);
pinMode(Relay1, OUTPUT);
pinMode(Relay2, OUTPUT);
pinMode(Relay3, OUTPUT);
digitalWrite(Relay1,LOW); //initial LOW
digitalWrite(Relay2,LOW); //initial LOW
digitalWrite(Relay3,LOW); //initial LOW
// Flag_on_off_Timer=EEPROM.read(Flag_On_Off_Timer_Addr);
//if(Flag_on_off_Timer!=0 ||Flag_on_off_Timer!=1 ) // if EEPROM Read wrong vale then set to default, this condition will open on Hardware.
// Flag_on_off_Timer=0 ;
//*****************************Init Timers********************//
// EEPROM_Read_Timer_HH_MM_SS_1();
// EEPROM_Read_Timer_HH_MM_SS_2();
// EEPROM_Read_Timer_HH_MM_SS_3();
// Serial.println("start timer 1");
timer2 = timerBegin(1, 80, true); // timer 1, MWDT clock period = 12.5 ns * TIMGn_Tx_WDT_CLK_PRESCALE -> 12.5 ns * 80 -> 1000 ns = 1 us, countUp
timerAttachInterrupt(timer2, &onTimer2, true); // edge (not level) triggered
timerAlarmWrite(timer2, TIMER2_INTERVAL_MS*1000, true); // 1000000 * 1 us = 1 s, autoreload true
//Serial.println("start timer 0");
timer1 = timerBegin(0, 80, true); // timer 0, MWDT clock period = 12.5 ns * TIMGn_Tx_WDT_CLK_PRESCALE -> 12.5 ns * 80 -> 1000 ns = 1 us, countUp
timerAttachInterrupt(timer1, &onTimer1, true); // edge (not level) triggered
timerAlarmWrite(timer1, TIMER1_INTERVAL_MS*1000, true); // 1000000 * 1 us = 1 s, autoreload true
// Serial.println("start timer 2");
timer3 = timerBegin(2, 80, true); // timer 2, MWDT clock period = 12.5 ns * TIMGn_Tx_WDT_CLK_PRESCALE -> 12.5 ns * 80 -> 1000 ns = 1 us, countUp
timerAttachInterrupt(timer3, &onTimer3, true); // edge (not level) triggered
timerAlarmWrite(timer3, TIMER3_INTERVAL_MS*1000, true); // 1000000 * 1 us = 1 s, autoreload true
timerAlarmEnable(timer1); // enable
timerAlarmEnable(timer2); // enable
timerAlarmEnable(timer3); // enable
}
void loop()
{
if (Serial.available()>0) //ESP_BT.available() // *use this when Actual Bluetooth device will connect
{
String Rec_string = Serial.readStringUntil('\n'); //Read what we receive //ESP_BT.readStringUntil// *use this when Actual Bluetooth device will connect
Serial.print("Received String:");
Serial.println(Rec_string); // Received string
// at least enable the timer alarms
if((Rec_string.length()>3) && Rec_string.endsWith("*")) // Received (21*5*4*3*2*1*0*) When timer mode is enable
{
String Relay_status = getValue(Rec_string, '*', 0);//String before first *
//Convert String to int
Relay_value = Relay_status.toInt();
Serial.println(Relay_value);
Flag_on_off_Timer = 1; //timer mode enable
EEPROM_Save_Data(Flag_on_off_Timer,Flag_On_Off_Timer_Addr); //saving timer mode value
switch(Relay_value)
{
case 11: //when 1 Relay timer data is received
TON_H_val1= getValue(Rec_string, '*', 1); //String before second *
Ton1_HH = TON_H_val1.toInt();
EEPROM_Save_Data(Ton1_HH,Ton1_HH_Addr); //Saving data on EEPROM
Serial.print("Ton1_HH:");
Serial.println(Ton1_HH);
TON_M_val1= getValue(Rec_string, '*', 2); //String before second *
Ton1_MM = TON_M_val1.toInt();
EEPROM_Save_Data(Ton1_MM,Ton1_MM_Addr);
Serial.print("Ton1_MM:");
Serial.println(Ton1_MM);
TON_S_val1= getValue(Rec_string, '*', 3); //String before second *
Ton1_SS = TON_S_val1.toInt();
EEPROM_Save_Data(Ton1_SS,Ton1_SS_Addr);
Serial.print("Ton1_SS:");
Serial.println(Ton1_SS);
TOFF_H_val1= getValue(Rec_string, '*', 4); //String before second *
Toff1_HH = TOFF_H_val1.toInt();
EEPROM_Save_Data(Toff1_HH,Toff1_HH_Addr);
Serial.print("Toff1_HH:");
Serial.println(Toff1_HH);
TOFF_M_val1= getValue(Rec_string, '*', 5); //String before second *
Toff1_MM = TOFF_M_val1.toInt();
EEPROM_Save_Data(Toff1_MM,Toff1_MM_Addr);
Serial.print("Toff1_MM:");
Serial.println(Toff1_MM);
TOFF_S_val1= getValue(Rec_string, '*', 6); //String before second *
Toff1_SS = TOFF_S_val1.toInt();
EEPROM_Save_Data(Toff1_SS,Toff1_SS_Addr);
Serial.print("Toff1_SS:");
Serial.println(Toff1_SS);
//Reset the Timer
Previous_Flag1=1;
Timer1_Flag=0; // if 0 then TON, else TOFF
break;
case 21: //when 2 Relay timer data is received
TON_H_val1= getValue(Rec_string, '*', 1); //String before second *
Ton2_HH = TON_H_val1.toInt();
EEPROM_Save_Data(Ton2_HH,Ton2_HH_Addr);
Serial.print("Ton2_HH:");
Serial.println(Ton2_HH);
TON_M_val1= getValue(Rec_string, '*', 2); //String before second *
Ton2_MM = TON_M_val1.toInt();
EEPROM_Save_Data(Ton2_MM,Ton2_MM_Addr);
Serial.print("Ton2_MM:");
Serial.println(Ton2_MM);
TON_S_val1= getValue(Rec_string, '*', 3); //String before second *
Ton2_SS = TON_S_val1.toInt();
EEPROM_Save_Data(Ton2_SS,Ton2_SS_Addr);
Serial.print("Ton2_SS:");
Serial.println(Ton2_SS);
TOFF_H_val1= getValue(Rec_string, '*', 4); //String before second *
Toff2_HH = TOFF_H_val1.toInt();
EEPROM_Save_Data(Toff2_HH,Toff2_HH_Addr);
Serial.print("Toff2_HH:");
Serial.println(Toff2_HH);
TOFF_M_val1= getValue(Rec_string, '*', 5); //String before second *
Toff2_MM = TOFF_M_val1.toInt();
EEPROM_Save_Data(Toff2_MM,Toff2_MM_Addr);
Serial.print("Toff2_MM:");
Serial.println(Toff2_MM);
TOFF_S_val1= getValue(Rec_string, '*', 6); //String before second *
Toff2_SS = TOFF_S_val1.toInt();
EEPROM_Save_Data(Toff2_SS,Toff2_SS_Addr);
Serial.print("Toff2_SS:");
Serial.println(Toff2_SS);
//Reset the Timer
Previous_Flag2=1;
Timer2_Flag=0; // if 0 then TON, else TOFF
break;
case 31: //when 3 Relay timer data is received
TON_H_val1= getValue(Rec_string, '*', 1); //String before second *
Ton3_HH = TON_H_val1.toInt();
EEPROM_Save_Data(Ton3_HH,Ton3_HH_Addr);
Serial.print("Ton3_HH:");
Serial.println(Ton3_HH);
TON_M_val1= getValue(Rec_string, '*', 2); //String before second *
Ton3_MM = TON_M_val1.toInt();
EEPROM_Save_Data(Ton3_MM,Ton3_MM_Addr);
Serial.print("Ton3_MM:");
Serial.println(Ton3_MM);
TON_S_val1= getValue(Rec_string, '*', 3); //String before second *
Ton3_SS = TON_S_val1.toInt();
EEPROM_Save_Data(Ton3_SS,Ton3_SS_Addr);
Serial.print("Ton3_SS:");
Serial.println(Ton3_SS);
TOFF_H_val1= getValue(Rec_string, '*', 4); //String before second *
Toff3_HH = TOFF_H_val1.toInt();
EEPROM_Save_Data(Toff3_HH,Toff3_HH_Addr);
Serial.print("Toff3_HH:");
Serial.println(Toff3_HH);
TOFF_M_val1= getValue(Rec_string, '*', 5); //String before second *
Toff3_MM = TOFF_M_val1.toInt();
EEPROM_Save_Data(Toff3_MM,Toff3_MM_Addr);
Serial.print("Toff3_MM:");
Serial.println(Toff3_MM);
TOFF_S_val1= getValue(Rec_string, '*', 6); //String before second *
Toff3_SS = TOFF_S_val1.toInt();
EEPROM_Save_Data(Toff3_SS,Toff3_SS_Addr);
Serial.print("Toff3_SS:");
Serial.println(Toff3_SS);
//Reset the Timer
Previous_Flag3=1;
Timer3_Flag=0; // if 0 then TON, else TOFF
break;
}
// ESP.restart(); /*ESP restart function call when New data stored in EEPROM*/
}
else if((Rec_string.length()==3) && Rec_string.endsWith("*")) // Received (21*,20* etc) when timer mode disable, Direct ON/OFF
{
String Relay_status = getValue(Rec_string, '*', 0);
Flag_on_off_Timer = 0; //timer mode disable
EEPROM_Save_Data(Flag_on_off_Timer,Flag_On_Off_Timer_Addr);//saving timer mode value
//Convert String to int
Relay_value = Relay_status.toInt();
Serial.println(Relay_value);
int button = floor(Relay_value / 10);
int value = Relay_value % 10;
switch (button)
{
case 1:
Serial.print("Relay1:"); Serial.println(value);
digitalWrite(Relay1, value);
break;
case 2:
Serial.print("Relay2:"); Serial.println(value);
digitalWrite(Relay2, value);
break;
case 3:
Serial.print("Relay3:"); Serial.println(value);
digitalWrite(Relay3, value);
break;
}
}
else
return;
}
if(Flag_on_off_Timer) //when Timer Mode enable
{
if(Previous_Flag1!=Timer1_Flag)
{
if((!Timer1_Flag)&&((Ton1_HH>0)||(Ton1_MM>0)||(Ton1_SS>0))) // When TON1_HH_MM_SS >0 Then only true & Timer flag chnaged
{
time_H1=Ton1_HH; //Load the TON value into Timer variable
time_M1=Ton1_MM; //Load the TON value into Timer variable
time_S1=Ton1_SS; //Load the TON value into Timer variable
digitalWrite(Relay1, HIGH);
}
else if((Timer1_Flag)&&((Toff1_HH>0)||(Toff1_MM>0)||(Toff1_SS>0))) // TOFF1 Timer
{
time_H1=Toff1_HH; //Load the TOFF value into Timer variable
time_M1=Toff1_MM; //Load the TOFF value into Timer variable
time_S1=Toff1_SS; //Load the TOFF value into Timer variable
digitalWrite(Relay1, LOW);
}
Previous_Flag1=Timer1_Flag;
}
if(Previous_Flag2!=Timer2_Flag) //when Timer flag chnaged,Means TON or OFF completed
{
if((!Timer2_Flag)&&((Ton2_HH>0)||(Ton2_MM>0)||(Ton2_SS>0))) //Load the TON value into Timer variable
{
time_H2=Ton2_HH;
time_M2=Ton2_MM;
time_S2=Ton2_SS;
digitalWrite(Relay2, HIGH);
Serial.println("Inside Timer2_Flag if");
}
else if((Timer2_Flag)&&((Toff2_HH>0)||(Toff2_MM>0)||(Toff2_SS>0))) //Load the TOFF value into Timer variable
{
time_H2=Toff2_HH;
time_M2=Toff2_MM;
time_S2=Toff2_SS;
digitalWrite(Relay2, LOW);
Serial.println("Inside Timer2_Flag else");
}
Previous_Flag2=Timer2_Flag;
}
if(Previous_Flag3!=Timer3_Flag) //when Timer flag chnaged,Means TON or OFF completed
{
if((!Timer3_Flag)&&((Ton3_HH>0)||(Ton3_MM>0)||(Ton3_SS>0))) //Load the TON value into Timer variable
{
time_H3=Ton3_HH;
time_M3=Ton3_MM;
time_S3=Ton3_SS;
digitalWrite(Relay3, HIGH);
Serial.println("Inside Timer3_Flag if");
}
else if((Timer3_Flag)&&((Toff3_HH>0)||(Toff3_MM>0)||(Toff3_SS>0))) //Load the TOFF value into Timer variable //Load the TOFF value into Timer variable
{
time_H3=Toff3_HH;
time_M3=Toff3_MM;
time_S3=Toff3_SS;
digitalWrite(Relay3, LOW);
Serial.println("Inside Timer3_Flag else");
}
Previous_Flag3=Timer3_Flag;
}
}
else
{
// Direct ON/OFF Mode
return;
// Serial.println("Inside Flag_on_off_Timer else condition");
}
//if(time_S1!=time_S1 || time_M1!=time_M1 || time_H1!=time_H1)
{ Serial.print("Timer1:");
Serial.print(time_H1);
Serial.print(":");
Serial.print(time_M1);
Serial.print(":");
Serial.println(time_S1);
Serial.print("Timer2:");
Serial.print(time_H2);
Serial.print(":");
Serial.print(time_M2);
Serial.print(":");
Serial.println(time_S2);
Serial.print("Timer3:");
Serial.print(time_H3);
Serial.print(":");
Serial.print(time_M3);
Serial.print(":");
Serial.println(time_S3);
//Serial.println(Timer1_Flag);
}
delay(1000);
}