#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
const byte ROW_NUM = 4;
const byte COLUMN_NUM = 4;
char keys[ROW_NUM][COLUMN_NUM] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte pin_rows[ROW_NUM] = {9, 8, 7, 6};
byte pin_column[COLUMN_NUM] = {5, 4, 3, 2};
Keypad keypad = Keypad(makeKeymap(keys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM);
const int gridPin1 = 13;
const int gridPin2 = 12;
const int gridPin3 = 10;
const int buzzerPin = 11;
const int voltagePin = A0;
const int currentPin = A1;
// Declare global variables for voltage, current, and power
float voltage = 0.0;
float current = 0.0;
float power = 0.0;
String grid1Password = "1234";
String grid2Password = "5678";
String masterKeyPassword = "0000";
const int emergencyStopButtonPin = A2;
bool emergencyStopActive = false;
// Variables to store the previous state of grids
bool grid1PreviousState = LOW;
bool grid2PreviousState = LOW;
bool grid3PreviousState = LOW;
unsigned long overloadStartTime = 0;
const unsigned long overloadInterval = 200000; // 1 minute in milliseconds
unsigned long refreshStartTime = 0;
const unsigned long refreshInterval = 8000; // 4 seconds in milliseconds
// Variables for non-blocking delay
const unsigned long messageDuration = 2000; // 2 seconds for each message
unsigned long startTime;
unsigned long loadSharingStartTime = 0;
const unsigned long loadSharingInterval = 60000; // 1 minute in milliseconds
bool loadSharingInProgress = false;
bool loadSharingOn = false; // Initially set to false
int gridToggleState = 0;
// Function prototypes
void mainMenu();
void controlGrid();
void masterControl();
void changePassword();
void toggleGrid(int gridPin);
void beep();
void longBeep();
char getKey();
void goBack();
String getPassword();
void masterToggle(bool state);
void voltsCurrent();
void overload();
void loadSharing();
void controlSharing();
bool verifyCode(String code);
void emergencyStop();
void resetSystem();
void checkForKeyPress();
void setup() {
lcd.init();
lcd.backlight();
lcd.print("Line1: Hello");
lcd.setCursor(0, 1);
lcd.print("Line2: Arduino");
pinMode(gridPin1, OUTPUT);
pinMode(gridPin2, OUTPUT);
pinMode(gridPin3, OUTPUT);
pinMode(buzzerPin, OUTPUT);
pinMode(voltagePin, INPUT);
pinMode(currentPin, INPUT);
pinMode(emergencyStopButtonPin, INPUT_PULLUP);
digitalWrite(gridPin1, HIGH);
digitalWrite(gridPin2, HIGH);
digitalWrite(gridPin3, HIGH);
mainMenu();
}
// Add these global variables alongside other global declarations
unsigned long lastToggleTime = 0;
const unsigned long toggleInterval = 10000; // 10 seconds in milliseconds
void loop() {
char key = keypad.getKey();
// Check for Emergency Stop button press
if (digitalRead(emergencyStopButtonPin) == LOW && !emergencyStopActive) {
emergencyStop();
}
unsigned long currentTime = millis();
if (currentTime - refreshStartTime >= refreshInterval) {
mainMenu();
refreshStartTime = currentTime; // Reset the timer
}
if (key != NO_KEY) {
beep();
if (key == 'A') {
controlGrid();
} else if (key == 'B') {
masterControl();
} else if (key == 'C') {
changePassword();
} else if (key == 'D') {
controlSharing(); // Go directly to controlSharing() when 'D' is pressed
} else if (key == '*') {
mainMenu();
}
mainMenu();
}
if (loadSharingOn && current > 2.0) {
if (currentTime - lastToggleTime >= toggleInterval) {
loadSharing(gridToggleState);
lastToggleTime = currentTime;
}
}
if (loadSharingOn) {
// Other conditions for load sharing (if any)
}
overload(); // Check for overload conditions
}
void incorrectSound() {
for (int i = 0; i < 3; i++) {
tone(buzzerPin, 1500, 100); // Play a higher-pitched tone
delay(150);
noTone(buzzerPin);
delay(150);
}
}
void invalidSound() {
for (int i = 0; i < 2; i++) {
tone(buzzerPin, 1000, 200); // Play a different tone
delay(250);
noTone(buzzerPin);
delay(250);
}
}
void successSound() {
tone(buzzerPin, 2000, 300); // Play a high-pitched tone for success
delay(350);
noTone(buzzerPin);
}
void controlSharing() {
lcd.clear();
lcd.print("Control Sharing");
beep(); // Add beep sound
lcd.setCursor(0, 1);
lcd.print("1: On");
lcd.setCursor(0, 2);
lcd.print("2: Off");
char selection = getKey();
if (selection == '1') {
lcd.clear();
lcd.print("Press 1 to continue");
beep(); // Add beep sound
char confirm = getKey();
if (confirm == '1') {
lcd.clear();
lcd.print("Enter 4-Digit Code:");
beep(); // Add beep sound
String code = getPassword();
if (code.length() == 4) {
lcd.clear();
lcd.print("Load Sharing On");
beep(); // Add beep sound
loadSharingOn = true; // Set loadSharingOn to true
delay(1000);
} else {
lcd.clear();
lcd.print("Invalid Code");
successSound(); // Add beep sound
delay(1000);
mainMenu();
}
} else {
mainMenu();
}
} else if (selection == '2') {
lcd.clear();
lcd.print("Press 1 to continue");
beep(); // Add beep sound
char confirm = getKey();
if (confirm == '1') {
lcd.clear();
lcd.print("Enter 4-Digit Code:");
beep(); // Add beep sound
String code = getPassword();
if (code.length() == 4) {
lcd.clear();
lcd.print("Load Sharing Off");
beep(); // Add beep sound
loadSharingOn = false; // Set loadSharingOn to false
} else {
lcd.clear();
lcd.print("Invalid Code");
beep(); // Add beep sound
delay(1000);
mainMenu();
}
} else {
mainMenu();
}
}
beep(); // Add beep sound
mainMenu(); // Return to the main menu
}
void loadSharing(int ¤tToggleState) {
lcd.clear();
lcd.print("Load Sharing");
// Continue load sharing while loadSharingOn is true and current is more than 2 ampere
while (loadSharingOn && current > 2.0) {
// Check the status of all grids
bool grid1Status = digitalRead(gridPin1);
bool grid2Status = digitalRead(gridPin2);
bool grid3Status = digitalRead(gridPin3);
lcd.clear();
lcd.print("Load Sharing");
// Toggle the state of each high grid in sequence
lcd.setCursor(0, 1);
switch (currentToggleState) {
case 0:
lcd.print("Toggling Grid 1");
delay(1000);
digitalWrite(gridPin1, LOW);
digitalWrite(gridPin2, HIGH);
digitalWrite(gridPin3, HIGH);
break;
case 1:
lcd.print("Toggling Grid 2");
delay(1000);
digitalWrite(gridPin1, HIGH);
digitalWrite(gridPin2, LOW);
digitalWrite(gridPin3, HIGH);
break;
case 2:
lcd.print("Toggling Grid 3");
delay(1000);
digitalWrite(gridPin1, HIGH);
digitalWrite(gridPin2, HIGH);
digitalWrite(gridPin3, LOW);
break;
}
// Increment the toggle state
currentToggleState++;
// Reset the toggle state to 0 if it exceeds the maximum grid index
if (currentToggleState > 2) {
currentToggleState = 0;
}
// Delay for 10 seconds
// Check the status of all grids again after toggling
grid1Status = digitalRead(gridPin1);
grid2Status = digitalRead(gridPin2);
grid3Status = digitalRead(gridPin3);
mainMenu();
}
// Stop load sharing, and return to the main menu
lcd.clear();
lcd.print("Load Sharing Stopped");
delay(2000);
mainMenu();
}
void emergencyStop() {
lcd.clear();
lcd.print("Emergency Stop");
longBeep();
grid1PreviousState = digitalRead(gridPin1);
grid2PreviousState = digitalRead(gridPin2);
grid3PreviousState = digitalRead(gridPin3);
// Turn off all grids
digitalWrite(gridPin1, LOW);
digitalWrite(gridPin2, LOW);
digitalWrite(gridPin3, LOW);
lcd.setCursor(0, 1);
lcd.print("Press button to");
lcd.setCursor(0, 2);
lcd.print("remove Emergency");
// Regular beeping and flashing display backlight during Emergency Stop
unsigned long beepStartTime = millis();
unsigned long backlightStartTime = millis();
while (digitalRead(emergencyStopButtonPin) == HIGH) {
// Beep every 500 milliseconds
if (millis() - beepStartTime >= 700) {
beep();
beepStartTime = millis();
}
// Flash display backlight every second
if (millis() - backlightStartTime >= 500) {
lcd.setBacklight(LOW); // Turn off backlight
delay(500);
lcd.setBacklight(HIGH); // Turn on backlight
backlightStartTime = millis();
}
}
// Reset the system to normal conditions after Emergency Stop is removed
lcd.clear();
lcd.print("Removing Emergency");
delay(1000); // Add any additional delay or actions needed
resetSystem();
}
// Restore the previous state of grids
void resetSystem() {
// Add any actions needed to reset the system to normal conditions
// Restore the previous state of grids
digitalWrite(gridPin1, grid1PreviousState);
digitalWrite(gridPin2, grid2PreviousState);
digitalWrite(gridPin3, grid3PreviousState);
// Reset any other variables or states as needed
// Continue with the normal flow
mainMenu();
}
void checkForKeyPress() {
// Check for Emergency Stop button press
if (digitalRead(emergencyStopButtonPin) == LOW && !emergencyStopActive) {
emergencyStop();
return; // exit the function to ignore regular key checks
}
char key = keypad.getKey();
if (key != NO_KEY) {
beep();
if (key == 'A') {
controlGrid();
} else if (key == 'B') {
masterControl();
} else if (key == 'C') {
changePassword();
} else if (key == 'D') {
controlSharing();
} else if (key == '*') {
mainMenu();
}
}
}
void mainMenu() {
// Message 1
lcd.clear();
lcd.setCursor(5, 0);
lcd.print("TO CONTROL");
lcd.setCursor(0, 1);
lcd.print("A: To Grid Control");
lcd.setCursor(0, 2);
lcd.print("B: Master Control");
lcd.setCursor(0, 3);
lcd.print("C: To Change Pass.");
startTime = millis();
while (millis() - startTime < messageDuration) {
checkForKeyPress();
}
// Display voltage, current, and power information
lcd.clear();
voltsCurrent();
// Check for overload conditions
lcd.setCursor(9, 3);
if (current > 1.0) {
lcd.print("OVER LOAD");
} else {
lcd.print("Normal Load");
}
startTime = millis();
while (millis() - startTime < 3000) {
checkForKeyPress();
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Grid Status:");
lcd.setCursor(0, 1);
lcd.print("Grid 1: ");
lcd.print(digitalRead(gridPin1) == HIGH ? "ON" : "OFF");
lcd.setCursor(0, 2);
lcd.print("Grid 2: ");
lcd.print(digitalRead(gridPin2) == HIGH ? "ON" : "OFF");
lcd.setCursor(0, 3);
lcd.print("Grid 3: ");
lcd.print(digitalRead(gridPin3) == HIGH ? "ON" : "OFF");
startTime = millis();
while (millis() - startTime < messageDuration) {
checkForKeyPress();
}
// Message 2
lcd.clear();
lcd.setCursor(4, 0);
lcd.print("Design By");
lcd.setCursor(4, 1);
lcd.print("SONU YADAV");
lcd.setCursor(1, 2);
lcd.print("Reg.no-20103127031");
lcd.setCursor(3, 3);
lcd.print("Mob.8002370253");
startTime = millis();
while (millis() - startTime < 1000) {
checkForKeyPress();
}
// Remaining code...
}
// Rest of the functions remain unchanged
void voltsCurrent() {
// Read voltage from ZMPT101B
int voltageValue = analogRead(voltagePin);
voltage = voltageValue * (5.0 / 1023.0); // Assuming 5V reference voltage
// Read current from ACS712
int currentValue = analogRead(currentPin);
current = (currentValue - 512) * (5.0 / 512.0); // Assuming ACS712 sensitivity and 0A at 512
// Calculate power
power = voltage * current;
lcd.setCursor(0, 0);
lcd.print("Voltage");
lcd.setCursor(10, 0);
lcd.print(voltage, 2);
lcd.print("V");
lcd.setCursor(0, 1);
lcd.print("Current");
lcd.setCursor(10, 1);
lcd.print(current, 2);
lcd.print("A");
lcd.setCursor(0, 3);
lcd.print("P:");
lcd.print(power, 1);
lcd.print("W");
}
void overload() {
int currentValue = analogRead(currentPin);
float current = (currentValue - 512) * (5.0 / 512.0); // Assuming ACS712 sensitivity and 0A at 512
if (current > 1.0) { // Adjust the threshold as needed
unsigned long currentTime = millis();
if (currentTime - overloadStartTime >= overloadInterval) {
lcd.clear();
lcd.print("OVER LOAD");
longBeep();
delay(2000); // Display "OVER LOAD" for 2 seconds
overloadStartTime = currentTime; // Reset the timer
}
}
}
void controlGrid() {
lcd.clear();
lcd.print("Control Grid");
lcd.setCursor(0, 1);
lcd.print("1: Grid 1");
lcd.setCursor(0, 2);
lcd.print("2: Grid 2");
lcd.setCursor(0, 3);
lcd.print("*: Main Menu");
char gridSelection = getKey();
if (gridSelection == '1' || gridSelection == '2') {
lcd.clear();
lcd.print("Selected Grid: ");
lcd.print(gridSelection);
lcd.setCursor(0, 1);
lcd.print("Enter Password:");
String enteredPassword = getPassword();
if (gridSelection == '1' && enteredPassword == grid1Password) {
toggleGrid(gridPin1);
} else if (gridSelection == '2' && enteredPassword == grid2Password) {
toggleGrid(gridPin2);
} else {
lcd.clear();
lcd.print("Incorrect Password");
longBeep();
delay(1000);
goBack();
}
} else if (gridSelection == '*') {
goBack();
} else {
lcd.clear();
lcd.print("Invalid Selection");
longBeep();
delay(1000);
goBack();
}
}
void masterControl() {
lcd.clear();
lcd.print("MASTER CONTROL");
lcd.setCursor(0, 1);
lcd.print("1. To ON all Grid");
lcd.setCursor(0, 2);
lcd.print("2. To OFF all Grid");
lcd.setCursor(0, 3);
lcd.print("*: Main Menu");
char selection = getKey();
if (selection == '1' || selection == '2') {
lcd.clear();
lcd.print("ENTER MASTER KEY:");
String enteredMasterKey = getPassword();
if (enteredMasterKey == masterKeyPassword) {
lcd.clear();
lcd.print("Verified Master Key");
longBeep();
delay(1000);
lcd.clear();
if (selection == '1') {
lcd.print("Master Toggle ON");
masterToggle(true);
} else {
lcd.print("Master Toggle OFF");
masterToggle(false);
}
} else {
lcd.clear();
lcd.print("Incorrect Master Key");
longBeep();
delay(1000);
goBack();
}
} else if (selection == '*') {
goBack();
} else {
lcd.clear();
lcd.print("Invalid Selection");
longBeep();
delay(1000);
goBack();
}
}
void changePassword() {
lcd.clear();
lcd.print("Change Password");
lcd.setCursor(0, 1);
lcd.print("1: Grid 1");
lcd.setCursor(12, 1);
lcd.print("2: Grid 2");
lcd.setCursor(0, 2);
lcd.print("3: Master Key");
lcd.setCursor(0, 3);
lcd.print("4: Factory Reset");
char gridSelection = getKey();
if (gridSelection == '1' || gridSelection == '2') {
lcd.clear();
lcd.print("Selected Grid: ");
lcd.print(gridSelection);
lcd.setCursor(0, 1);
lcd.print("Enter Old Password:");
String oldPassword = getPassword();
String currentPassword = (gridSelection == '1') ? grid1Password : grid2Password;
if (oldPassword == currentPassword) {
lcd.clear();
lcd.print("Enter New Password:");
String newPassword = getPassword();
lcd.clear();
lcd.print("Confirm Password:");
String confirmPassword = getPassword();
if (newPassword == confirmPassword && newPassword.length() <= 4) {
if (gridSelection == '1') {
grid1Password = newPassword;
} else {
grid2Password = newPassword;
}
lcd.clear();
lcd.print("Password Changed");
longBeep();
delay(1000);
goBack();
} else {
lcd.clear();
lcd.print("Passwords do not match or exceed 4 digits");
longBeep();
delay(1000);
goBack();
}
} else {
lcd.clear();
lcd.print("Incorrect Old Password");
longBeep();
delay(1000);
goBack();
}
} else if (gridSelection == '3') {
lcd.clear();
lcd.print("Change Master Key");
lcd.setCursor(0, 1);
lcd.print("Enter Old Master Key:");
String oldMasterKey = getPassword();
if (oldMasterKey == masterKeyPassword) {
lcd.clear();
lcd.print("Enter New Master Key:");
String newMasterKey = getPassword();
lcd.clear();
lcd.print("Confirm Master Key:");
String confirmMasterKey = getPassword();
if (newMasterKey == confirmMasterKey && newMasterKey.length() <= 4) {
masterKeyPassword = newMasterKey;
lcd.clear();
lcd.print("Master Key Changed");
longBeep();
delay(1000);
goBack();
} else {
lcd.clear();
lcd.print("Master Keys do not match or exceed 4 digits");
longBeep();
delay(1000);
goBack();
}
} else {
lcd.clear();
lcd.print("Incorrect Old Master Key");
longBeep();
delay(1000);
goBack();
}
} else if (gridSelection == '4') {
lcd.clear();
lcd.print("Password Reset");
lcd.setCursor(0, 1);
lcd.print("Press 1 to continue");
char confirmation = getKey();
if (confirmation == '1') {
lcd.clear();
lcd.print("Enter Random 4-Digit Number:");
String resetCode = getPassword();
lcd.clear();
lcd.print("Processing...");
delay(2000);
if (resetCode.length() == 4) {
grid1Password = "1234";
grid2Password = "5678";
masterKeyPassword = "0000"; // Assuming grid 3 password variable exists
lcd.clear();
lcd.print("Successfully Reset");
longBeep();
delay(1000);
goBack();
} else {
lcd.clear();
lcd.print("Invalid Code");
longBeep();
delay(1000);
goBack();
}
} else {
lcd.clear();
lcd.print("Reset Canceled");
longBeep();
delay(1000);
goBack();
}
} else if (gridSelection == '*') {
goBack();
} else {
lcd.clear();
lcd.print("Invalid Selection");
longBeep();
delay(1000);
goBack();
}
}
void toggleGrid(int gridPin) {
lcd.clear();
lcd.print("Grid ");
if (gridPin == gridPin1) {
lcd.print("1 is ");
} else if (gridPin == gridPin2) {
lcd.print("2 is ");
}
if (digitalRead(gridPin) == LOW) {
digitalWrite(gridPin, HIGH);
lcd.print("On");
} else {
digitalWrite(gridPin, LOW);
lcd.print("Off");
}
longBeep();
delay(2000);
goBack();
}
void beep() {
tone(buzzerPin, 1000, 50);
delay(50);
noTone(buzzerPin);
}
void longBeep() {
tone(buzzerPin, 1000, 500);
delay(500);
noTone(buzzerPin);
}
char getKey() {
char key = NO_KEY;
unsigned long startTime = millis();
while (key == NO_KEY && millis() - startTime < 10000) {
key = keypad.getKey();
}
if (key == NO_KEY) {
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("Time Out");
longBeep();
delay(1000);
goBack();
}
return key;
}
void goBack() {
lcd.clear();
lcd.print("Going Back...");
delay(1000);
mainMenu();
}
String getPassword() {
String password = "";
char key;
lcd.setCursor(0, 2);
lcd.print("Input Key: ");
lcd.setCursor(0, 3);
lcd.print("*: Main Menu");
while ((key = getKey()) != '#' && key != '*') {
if (key == 'D') {
if (password.length() > 0) {
password = password.substring(0, password.length() - 1);
lcd.setCursor(12 + password.length(), 2);
lcd.print(" ");
beep();
}
} else if (key != NO_KEY && password.length() < 4) {
password += key;
lcd.setCursor(12 + password.length() - 1, 2);
lcd.print(key);
beep();
}
}
if (key == '*') {
goBack();
}
return password;
}
void masterToggle(bool state) {
digitalWrite(gridPin1, state ? HIGH : LOW);
digitalWrite(gridPin2, state ? HIGH : LOW);
digitalWrite(gridPin3, state ? HIGH : LOW);
delay(2000);
goBack();
}