/***********************************************************
* Smart Plug for mobile Charger created by A.V.Pradeep
*
* Last modified version: V3.0
*
* Last updated Time: 24-02-2024 at 20:45
*
* For more details, visit:
* Downloads, docs, tutorials: https://www.blynk.io
* Sketch generator: https://examples.blynk.cc
* Blynk community: https://community.blynk.cc
* Notes: 1. Blynk is OK
* 2. Manual switching OK
************************************************************/
#pragma region Declarations
#define BLYNK_TEMPLATE_ID "TMPL3yyO18oEM"
#define BLYNK_TEMPLATE_NAME "SmartPlug"
#define BLYNK_AUTH_TOKEN "cB0iCFjElMo1aN_Wr_haVR_c-Foduzuo"
char auth[] = "cB0iCFjElMo1aN_Wr_haVR_c-Foduzuo";
char ssid[] = "Kichu_WiFi";
char pass[] = "86100069";
#include <WiFi.h>
//#include <ESP32Ping.h>
//#include <BlynkSimpleEsp8266.h>
#include <BlynkSimpleEsp32.h>
#include <ezButton.h>
#include <TM1637Display.h>
#define BLYNK_PRINT Serial
#define VPIN_BUTTON_3 V3
#define WiFi_LED 18
#define Blynk_LED 19
#define ChargerRelay 21
#define SHORT_PRESS_TIME 500 // 500 milliseconds
#define LONG_PRESS_TIME 1000 // 1000 milliseconds
unsigned long pressedTime = 0;
unsigned long releasedTime = 0;
unsigned long PrevMillis = 0;
bool Blink = true;
uint8_t data[] = {0x0, 0x0, 0x0, 0x0}; // variable for blinking the digits
bool isPressing = false;
bool isLongDetected = false;
int CurrentButton = 0; // last button pressed
int lastState = LOW; // the previous state from the input pin
int currentState; // the current reading from the input pin
int defaultTime = 45; // initial time if not saved previously
bool wifiFlag = false; //
int Mode = 0;
int CurrntPos = 4; // start from right most
int HoursTens = 0; // Hours left digit
int HoursOnes = 1; // hours rifght digit
int MinutesTens = 1; //minutes left digit
int MinutesOnes = 0; //minutes right digit
int Sec_Count = 0 ;
int Min_Count = 0 ;
int Hrs_Count = 0;
int AnimPos =0;
int ChargeMinutes = (HoursTens*10 + HoursOnes)*60 + (MinutesTens*10 + MinutesOnes);
const char* remote_host = "www.google.com";
BlynkTimer timer;
#define CLK 22 // The ESP32 pin GPIO22 connected to CLK
#define DIO 23 // The ESP32 pin GPIO23 connected to DIO
// create a display object of type TM1637Display
TM1637Display display = TM1637Display(CLK, DIO);
ezButton button1(25); // create ezButton object that attach to pin 6;
ezButton button2(26); // create ezButton object that attach to pin 7;
ezButton button3(27); // create ezButton object that attach to pin 8;
ezButton button4(14); // create ezButton object that attach to pin 8;
ezButton button5(13); // create ezButton object that attach to pin 6;
#pragma endregion Declarations
void myTimerEvent()
{
// You can send any value at any time.
// Please don't send more that 10 values per second.
Blynk.virtualWrite(V2, millis() / 3000);
Serial.println(" Blynk virtual pin updated!");
}
BLYNK_WRITE(VPIN_BUTTON_3)
{
digitalWrite(ChargerRelay, HIGH);
Serial.println("Switch ON command received!");
//Blynk.virtualWrite(VPIN_BUTTON_3, 0);
}
BLYNK_WRITE(V1)
{
int pinValue = param.asInt(); // assigning incoming value from pin V1 to a variable
Serial.print("DataReceived = ");
Serial.println(pinValue);
ChargeMinutes = pinValue;
_DisplayData();
// process received value
}
void _Animation() // animation of digits during awaiting data from blynk server
{
uint8_t TmpData[] = {0x0, 0x0, 0x0, 0x0};
AnimPos = AnimPos + 1;
if (AnimPos>3)
{
AnimPos = 0;
}
TmpData[AnimPos] =SEG_G | SEG_C | SEG_D | SEG_E | SEG_F;
//TmpData[AnimPos] =SEG_G ;
display.setSegments(TmpData);
delay(50);
}
void _DisplayData()
{
// display.showNumberDec(defaultTime, false); // Expect: 0045
if (Mode == 2)
{
HoursTens = (ChargeMinutes/60)/10;
HoursOnes = (ChargeMinutes/60)%10;
MinutesTens = (ChargeMinutes%60)/10;
MinutesOnes = (ChargeMinutes%60)%10;
}
data[0]= display.encodeDigit(HoursTens);
data[1]= display.encodeDigit(HoursOnes);
data[2]= display.encodeDigit(MinutesTens);
data[3]= display.encodeDigit(MinutesOnes);
display.setSegments(data);
}
void _UpdateSegments() // Update only selected digit or segments
{
uint8_t TmpData[] = {0x0, 0x0, 0x0, 0x0};
switch(CurrntPos)
{
case 1: //leftmost digit ie tens of hours
TmpData[0] = display.encodeDigit(HoursTens);
break;
case 2: // hours ones
TmpData[0] = display.encodeDigit(HoursOnes);
break;
case 3: // Tens of Minutes
TmpData[0] = display.encodeDigit(MinutesTens);
break;
case 4: // Ones of Minutes
TmpData[0] = display.encodeDigit(MinutesOnes);
break;
}
if (Blink)
{
TmpData[0] = 0x00;
}
display.setSegments(TmpData, 1, CurrntPos-1);
}
void _PosChange(int tmp) //
{
if (tmp == 1) // increment by one
{
CurrntPos = CurrntPos+1;
if (CurrntPos >4) // exceeded the maximum right position of 4
{
CurrntPos = 4; // limit the position
}
}
else
{
CurrntPos = CurrntPos-1;
if (CurrntPos <1) // exceeded the maximum left position of 1
{
CurrntPos = 1; // limit the position
}
}
Serial.print("Current Position: ");
Serial.println(CurrntPos);
_DisplayData();
}
void _DigitChange(int tmp) //
{
switch(CurrntPos)
{
case 1: //leftmost digit ie tens of hours
HoursTens = _ChangeValue(tmp, HoursTens);
break;
case 2: // hours ones
HoursOnes = _ChangeValue(tmp, HoursOnes);
break;
case 3: // Tens of Minutes
MinutesTens = _ChangeValue(tmp, MinutesTens);
break;
case 4: // Ones of Minutes
MinutesOnes = _ChangeValue(tmp, MinutesOnes);
break;
}
_DisplayData();
}
int _ChangeValue(int tmp, int digit)
{
if (tmp == 2 ) // decrease the vaue
{
digit = digit - 1;
if (digit < 0)
{
digit = 9;
}
}
else // tmp==1 ie; increment the value
{
digit = digit + tmp;
if (digit > 9)
{
digit = 0;
}
}
return digit;
}
void _StartCharging() // "Select" button is pressed during default mode
{
Mode= 1; // manual charging mode
ChargeMinutes = ((HoursTens*10 + HoursOnes)*60) + (MinutesTens*10) + MinutesOnes;
Serial.print("ChargeMinutes: ");
Serial.println( ChargeMinutes );
}
void _CheckTime() // "Select" button is pressed
{
Sec_Count = Sec_Count + 1;
if (Sec_Count == 10) // it should be 300 in actual practice
{
Sec_Count = 0;
Min_Count = Min_Count + 1;
ChargeMinutes = ChargeMinutes -1;
_DisplayData();
Serial.print("Ellapsed Minutes: ");
Serial.println(Min_Count);
}
if (ChargeMinutes == 0)
{
Mode = 5; // OFF mode
const uint8_t SEG_OFF[] = {
0x00, // blank
SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F, // O
SEG_A | SEG_E | SEG_F | SEG_G , // F
SEG_A | SEG_E | SEG_F | SEG_G // F
};
display.setSegments(SEG_OFF); // show "OFF" on display
}
//Serial.println( "\n ");
}
void _Pressing(int ButtNo)
{
CurrentButton = ButtNo;
pressedTime = millis();
isPressing = true;
isLongDetected = false;
}
void _Releasing(int ButtNo)
{
isPressing = false;
releasedTime = millis();
CurrentButton = ButtNo;
long pressDuration = releasedTime - pressedTime;
if ( pressDuration < SHORT_PRESS_TIME )
_Short_Pressed();
}
void _Short_Pressed()
{
//Serial.print("A short press is detected on Button:");
switch (CurrentButton)
{
case 1: // "Auto" button is pressed
if (Mode ==0) // default mode
{
Mode= 4; // Auto mode armed, NOT activated
}
else if (Mode ==1) // in Manual mode
{
_DigitChange(1); // increase the value
}
break;
case 2: // "Menu" button is pressed
if (Mode ==0)// default mode
{
Mode= 1; // Manual mode
}
else if (Mode ==1) // in Manual mode
{
_DigitChange(2); // decrease the value
}
break;
case 3:
//Serial.println(CurrentButton);
_PosChange(2); // update position- 1 to right shift, any other values to left shift
break;
case 4:
//Serial.println(CurrentButton);
_PosChange(1); // update position- 1 to right shift, any other values to left shift
break;
case 5:
_StartCharging(); // start charging
//Serial.println(CurrentButton);
break;
default:
//statements here
break;
}
}
void _Long_Pressed()
{
Serial.print("A looong press is detected on Button");
isLongDetected = true;
switch (CurrentButton)
{
case 1:
//Serial.println(CurrentButton);
break;
case 2:
//Serial.println(CurrentButton);
break;
case 3:
//Serial.println(CurrentButton);
break;
case 4:
//Serial.println(CurrentButton);
break;
case 5:
//Serial.println(CurrentButton);
break;
default:
// statements
break;
}
}
void _Check_WiFiStatus() // called every 3 seconds by SimpleTimer
{ while (WiFi.status() != WL_CONNECTED)
{
delay(100);
Serial.print(".");
}
Serial.println(" Connected!");
if (WiFi.status() == WL_CONNECTED)
{
{
digitalWrite(WiFi_LED, LOW); // turn off wifi status LED
Serial.println("wifi led switched off");
}
if (wifiFlag ==false) // turn on wifi status
{
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
Serial.println(wifiFlag);
wifiFlag = true;
}
}
else
digitalWrite(WiFi_LED, HIGH); // turn ON wifi status LED
}
void _Check_BlynkStatus()
{
bool isconnected = Blynk.connected();
if (isconnected == false)
{
wifiFlag = 1;
digitalWrite( Blynk_LED, HIGH);
Serial.println("Blynk Not Connected");
}
if (isconnected == true)
{
wifiFlag = 0;
digitalWrite( Blynk_LED, LOW);
// Serial.println("Blynk Connected");
}
}
void setup()
{
// Debug console
pinMode(WiFi_LED, OUTPUT);
pinMode(Blynk_LED, OUTPUT);
pinMode(ChargerRelay, OUTPUT);
digitalWrite(WiFi_LED, HIGH);
digitalWrite(Blynk_LED, HIGH);
Serial.begin(115200);
Serial.print("Connecting to WiFi");
WiFi.begin("Wokwi-GUEST", "", 6);
_Check_WiFiStatus();
_Check_BlynkStatus();
Blynk.config(auth);
button1.setDebounceTime(50); // set debounce time to 50 milliseconds
button2.setDebounceTime(50); // set debounce time to 50 milliseconds
button3.setDebounceTime(50); // set debounce time to 50 milliseconds
button4.setDebounceTime(50); // set debounce time to 50 milliseconds
button5.setDebounceTime(50); // set debounce time to 50 milliseconds
// Setup a function to be called every second
timer.setInterval(3000L, myTimerEvent);
// display.clear();
display.setBrightness(7); // set the brightness to 7 (0:dimmest, 7:brightest)
// displayed 15:30
//display.showNumberDecEx(45, 0b11100000, false, 4, 0);
// delay(100);
display.clear();
Serial.println("...\n");
Serial.println("Setup completed...\n");
Serial.println("...\n");
PrevMillis = millis();
_DisplayData();
// _Save_Time(); // one time use
}
void loop() // u/s
{
Blynk.run();
timer.run(); // Initiates BlynkTimer
button1.loop();
button2.loop();
button3.loop();
button4.loop();
button5.loop();
if (button1.isPressed())
{
_Pressing(1); // call _Pressing() function
}
else if (button2.isPressed())
{
_Pressing(2); // call _Pressing() function
}
else if (button3.isPressed())
{
_Pressing(3); // call _Pressing() function
}
else if (button4.isPressed())
{
_Pressing(4); // call _Pressing() function
}
else if (button5.isPressed())
{
_Pressing(5); // call _Pressing() function
}
if (button1.isReleased())
{
_Releasing(1); // call _Releasing() function
}
else if (button2.isReleased())
{
_Releasing(2); // call _Releasing() function
}
else if (button2.isReleased())
{
_Releasing(2); // call _Releasing() function
}
else if (button3.isReleased())
{
_Releasing(3); // call _Releasing() function
}
else if (button4.isReleased())
{
_Releasing(4); // call _Releasing() function
}
else if (button5.isReleased())
{
_Releasing(5); // call _Releasing() function
}
if (isPressing == true && isLongDetected == false) {
long pressDuration = millis() - pressedTime;
if ( pressDuration > LONG_PRESS_TIME )
_Long_Pressed();
}
if (millis() - PrevMillis >200)
{
PrevMillis = millis();
Blink = !Blink; // flip the blink from true to false and vice versa
if (Mode == 2) // in mode 2 Manual charging mode running
{
_CheckTime();
}
}
//_DisplayData(); // display the data on LED display
Serial.print( "Mode = " );
Serial.println( Mode );
delay(50);
if (Mode == 1)
{
_UpdateSegments();
}
else if (Mode == 4)
{
_Animation();
}
}