#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <RTClib.h> // RTC library to keep track of time
#define SCREEN_WIDTH 128 // OLED width, in pixels
#define SCREEN_HEIGHT 64 // OLED height, in pixels
Adafruit_SSD1306 oled(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); // create an OLED display object connected to I2C
RTC_DS1307 rtc; // create an RTC object
// Pin Declarations
int modePin = 26;
int gridPin = 35;
int solarPin = 34;
int selectionBtnPin = 25;
int potPin = 33;
int relay1 = 18; // MOTOR1
int relay2 = 17; // Bulb1
int relay3 = 16; // Bulb2
int relay4 = 4; // Bulb3
int relay5 = 23; // MOTOR2
int relay6 = 19; // Bulb4
int relay7 = 5; // Bulb5
int relay8 = 15; // Bulb6
int relay9 = 27; // Grid or Solar
// relay Load Value
int relay1_LoadVal = 70;
int relay2_LoadVal = 12;
int relay3_LoadVal = 23;
int relay4_LoadVal = 87;
int relay5_LoadVal = 23;
int relay6_LoadVal = 19;
int relay7_LoadVal = 5;
int relay8_LoadVal = 35;
int buzzerPin = 32; // Buzzer
int GridValue = 0;
int SolarValue = 0;
int selectionBtnVal = 0; // Current button state
int lastBtnVal = 0; // Last button state to detect state change
int selectedMode = 0; // Currently selected mode
int potValue = 0; // Current potentiometer value
// int modes[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // Array to store mode states (ON/OFF)
int modes[8] = {1,1,1,0, 1,1,1,0}; // Array to store mode states (ON/OFF)
// Preferences
int Prefrelay1 = 1;
int Prefrelay2 = 2;
int Prefrelay3 = 3;
int Prefrelay4 = 4;
int Prefrelay5 = 5;
int Prefrelay6 = 6;
int Prefrelay7 = 7;
int Prefrelay8 = 8;
// Day Slots and Price (Rs/Hr)
int slot1 = 12;
int slot2 = 11;
int slot3 = 50;
int slot4 = 16;
// Auto
int s1_LoadState[8] = {1,1,1,1, 1,1,1,1};
int s2_LoadState[8] = {1,1,1,1, 0,0,0,1};
int s3_LoadState[8] = {1,1,1,1, 0,1,0,1};
int s4_LoadState[8] = {1,1,1,1, 1,1,1,1};
String relayStatusBeepOld = "";
String relayStatusBeepNew = "";
int gridThreshold = 22; // Threshold for switching to solar (Gride Slot price)
int GridpowerThreshold = 100; // Threshold to check if power source is down (Watts)
int SolarpowerThreshold = 15; // Threshold to check if power source is down (Watts)
void setup() {
Serial.begin(115200);
// Initialize OLED display with I2C address 0x3C
if (!oled.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("Failed to start SSD1306 OLED"));
while (1);
}
// Initialize RTC
if (!rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
if (!rtc.isrunning()) {
Serial.println("RTC is NOT running!");
// Set the RTC to the current date & time
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
delay(100);
oled.clearDisplay();
oled.setTextSize(1);
oled.setTextColor(WHITE);
// Set relay pins as output
pinMode(relay1, OUTPUT);
pinMode(relay2, OUTPUT);
pinMode(relay3, OUTPUT);
pinMode(relay4, OUTPUT);
pinMode(relay5, OUTPUT);
pinMode(relay6, OUTPUT);
pinMode(relay7, OUTPUT);
pinMode(relay8, OUTPUT);
pinMode(relay9, OUTPUT);
pinMode(modePin, INPUT);
pinMode(buzzerPin, OUTPUT);
pinMode(selectionBtnPin, INPUT_PULLUP); // Set the button pin as input with pull-up
// Start with all relays off
digitalWrite(relay1, LOW);
digitalWrite(relay2, LOW);
digitalWrite(relay3, LOW);
digitalWrite(relay4, LOW);
digitalWrite(relay5, LOW);
digitalWrite(relay6, LOW);
digitalWrite(relay7, LOW);
digitalWrite(relay8, LOW);
digitalWrite(relay9, LOW);
digitalWrite(buzzerPin, LOW);
Serial.println("Hello, ESP32!");
delay(200);
}
void loop() {
// ========== Load State Selection Code ==========
// Manual
if (digitalRead(modePin) == HIGH){
Serial.println("Mode : Manual"); delay(100);
// Read the button state
selectionBtnVal = digitalRead(selectionBtnPin);
// If button state changes from HIGH to LOW (button press)
if (selectionBtnVal == LOW && lastBtnVal == HIGH) {
modes[selectedMode] = !modes[selectedMode]; // Toggle the selected mode
Serial.print("Mode ");
Serial.print(selectedMode + 1); // Mode number (1 to 8)
Serial.print(" is now ");
Serial.println(modes[selectedMode] ? "ON" : "OFF");
delay(2000); // Debounce delay
}
// Update the last button state
lastBtnVal = selectionBtnVal;
// Read the potentiometer value
potValue = analogRead(potPin);
// Map the potentiometer value to the mode number (0 to 7)
selectedMode = map(potValue, 0, 4095, 0, 7);
// Print the selected mode number
Serial.print("Selected Mode: ");
Serial.print(selectedMode + 1); // Mode number (1 to 8)
Serial.print(modes[selectedMode] ? " : ON" : " : OFF");
Serial.println("");
ManualactivatePowerSource();
delay(100); // Delay to reduce serial output rate
}
// Automatic Mode
else{
Serial.println("Mode : Automatic"); delay(100);
// Auto
// Read power values
GridValue = analogRead(gridPin);
GridValue = map(GridValue, 0, 4095, 0, 1100); // 0 to 4500 W
SolarValue = analogRead(solarPin);
SolarValue = map(SolarValue, 0, 4095, 0, 36); // 0 to 2500 W
// Get current time
DateTime now = rtc.now();
int currentHour = now.hour();
Serial.println("Hr: " + String(currentHour) + " GridV: " + String(GridValue) + "W SolarV: " + String(SolarValue) + "W");
// Determine slot price
// int currentSlotPrice = getSlotPrice(currentHour);
// int currentSlotPrice = slot1;
// int currentSlotPrice = slot2;
// int currentSlotPrice = slot3;
int currentSlotPrice = slot4;
// Clear display before updating
oled.clearDisplay();
displayOnOLED(0, 0, "IIoT Project");
displayOnOLED(10, 12, "Slot : " + String(currentSlotPrice) + " Rs/Hr");
// Check grid and solar status
if (GridValue < GridpowerThreshold && SolarValue < SolarpowerThreshold) {
Serial.println("Grid & Solar is DOWN");
activatePowerSource(false,false,false,false, false,false,false,false);
displayOnOLED(20, 24, "G - S -");
} else if (GridValue < GridpowerThreshold) {
Serial.println("Grid DOWN, Solar UP");
activatePowerSource(true,true,true,true, false,false,false,false);
displayOnOLED(20, 24, "G - S *");
} else if (SolarValue < SolarpowerThreshold) {
Serial.println("Grid UP, Solar DOWN");
activatePowerSource(true,true,true,true, true,true,true,true);
displayOnOLED(20, 24, "G * S -");
/*
int s1_LoadState[8] = {1,1,1,0, 1,1,1,0}; only grid
int s2_LoadState[8] = {1,1,1,0, 0,0,1,0}; only grid solar-1 (grpB: 2 ON grid)
int s3_LoadState[8] = {1,1,1,0, 1,1,1,0}; grpA : grid + grpB: solar
int s4_LoadState[8] = {1,1,1,0, 0,1,1,0}; grpA : grid + grpB: solar (grpB: 1 ON grid)
...
displayOnOLED(20, 24, "G - S *");
Serial.println("Relay: Solar ON (Grid Slot Price HIGH !!!)");
} else {
activatePowerSource(true,true,true,true, true,true,true,true);
displayOnOLED(20, 24, "G * S *");
Serial.println("Relay: Grid UP, Solar UP");
}
*/
} else {
// (slot vise load ON/OFF)
if (slot1 == currentSlotPrice) {
activatePowerSource(true,true,true,false, true,true,true,false);
displayOnOLED(20, 24, "G * S -");
Serial.println("Relay: Grid * Solar -");
} //only grid
else if (slot2 == currentSlotPrice){
activatePowerSource(true,true,true,false, true,false,true,false);
if (SolarValue < 20){ //range : 15 to 20
Serial.println("solar Power: LOW");
digitalWrite(relay9, LOW); // make Grid ON
}
else{
digitalWrite(relay9, HIGH); // make Solar ON
}
displayOnOLED(20, 24, "G * S *");
Serial.println("Relay: Grid * Solar *");
}//only grid solar-1 (grpB: 2 ON grid)
else if (slot3 == currentSlotPrice){
activatePowerSource(true,true,true,false, true,true,true,false);
displayOnOLED(20, 24, "G * S *");
Serial.println("Relay: Grid * Solar *");
} //grpA : grid + grpB: solar
else {
activatePowerSource(true,true,true,false, true,true,true,false);
if (SolarValue < 20){ //range : 15 to 20
Serial.println("solar Power: LOW");
digitalWrite(relay9, LOW); // make Grid ON
}
else{
digitalWrite(relay9, HIGH); // make Solar ON
}
displayOnOLED(20, 24, "G * S *");
Serial.println("Relay: Grid * Solar *");
} //grpA : grid + grpB: solar (grpB: 1 ON grid)
}
// ------------------------------------------------------
// Maximun Power Demand:
// ------------------------------------------------------
// Read the button state
selectionBtnVal = digitalRead(selectionBtnPin);
// If button state changes from HIGH to LOW (button press)
if (selectionBtnVal == LOW && lastBtnVal == HIGH) {
modes[selectedMode] = !modes[selectedMode]; // Toggle the selected mode
Serial.print("Mode ");
Serial.print(selectedMode + 1); // Mode number (1 to 8)
Serial.print(" is now ");
Serial.println(modes[selectedMode] ? "ON" : "OFF");
delay(2000); // Debounce delay
}
lastBtnVal = selectionBtnVal; // Update the last button state
potValue = analogRead(potPin);// Read the potentiometer value
// Map the potentiometer value to the mode number (0 to 7)
selectedMode = map(potValue, 0, 4095, 0, 7);
// Print the selected mode number
Serial.print("Selected Mode: "); Serial.print(selectedMode + 1); // Mode number (1 to 8)
Serial.print(modes[selectedMode] ? " : ON" : " : OFF"); Serial.println("");
digitalWrite(relay4, modes[3] ? HIGH : LOW);
digitalWrite(relay8, modes[7] ? HIGH : LOW);
int totalWatts = calculateTotalPower();
Serial.println("Total Watts: " + String(totalWatts));
if (totalWatts > 225){
if (digitalRead(relay4)){Serial.println("Load 4 : ON [Solar]");}
if (digitalRead(relay8)){Serial.println("Load 8 : ON [Solar]");}
}
else{
if (digitalRead(relay4)){Serial.println("Load 4 : ON");}
if (digitalRead(relay8)){Serial.println("Load 8 : ON");}
}
}
// ========== Existing IIoT Project Code ==========
Serial.println("-----------------------------------------------------------------------------");
// Display relay status on OLED
String relayStatus1 = "r1 " + getRelayStatusOled(relay1) + " r2 " + getRelayStatusOled(relay2);
String relayStatus2 = "r3 " + getRelayStatusOled(relay3) + " r4 " + getRelayStatusOled(relay4);
String relayStatus3 = "r5 " + getRelayStatusOled(relay5) + " r6 " + getRelayStatusOled(relay6);
String relayStatus4 = "r7 " + getRelayStatusOled(relay7) + " r8 " + getRelayStatusOled(relay8);
displayOnOLED(40, 0, relayStatus1 + " " + relayStatus2);
displayOnOLED(50, 0, relayStatus3 + " " + relayStatus4);
Serial.println(relayStatus1 + " " + relayStatus2 + " " + relayStatus3 + " " + relayStatus4);
delay(2000);
}
int getSlotPrice(int currentHour) {
if ((currentHour >= 0) && (currentHour < 6)) return slot1;
if ((currentHour >= 6) && (currentHour < 12)) return slot2;
if ((currentHour >= 12) && (currentHour < 18)) return slot3;
if ((currentHour >= 18) && (currentHour < 24)) return slot4;
return 0;
}
void ManualactivatePowerSource() {
if (modes[0] == 1){digitalWrite(relay1, HIGH);}else{digitalWrite(relay1, LOW);}
if (modes[1] == 1){digitalWrite(relay2, HIGH);}else{digitalWrite(relay2, LOW);}
if (modes[2] == 1){digitalWrite(relay3, HIGH);}else{digitalWrite(relay3, LOW);}
if (modes[3] == 1){digitalWrite(relay4, HIGH);}else{digitalWrite(relay4, LOW);}
if (modes[4] == 1){digitalWrite(relay5, HIGH);}else{digitalWrite(relay5, LOW);}
if (modes[5] == 1){digitalWrite(relay6, HIGH);}else{digitalWrite(relay6, LOW);}
if (modes[6] == 1){digitalWrite(relay7, HIGH);}else{digitalWrite(relay7, LOW);}
if (modes[7] == 1){digitalWrite(relay8, HIGH);}else{digitalWrite(relay8, LOW);}
// if (modes[0] == 1){digitalWrite(relay1, R1);}else{digitalWrite(relay1, LOW);}
// if (modes[1] == 1){digitalWrite(relay2, R2);}else{digitalWrite(relay2, LOW);}
// if (modes[2] == 1){digitalWrite(relay3, R3);}else{digitalWrite(relay3, LOW);}
// if (modes[3] == 1){digitalWrite(relay4, R4);}else{digitalWrite(relay4, LOW);}
// if (modes[4] == 1){digitalWrite(relay5, R5);}else{digitalWrite(relay5, LOW);}
// if (modes[5] == 1){digitalWrite(relay6, R6);}else{digitalWrite(relay6, LOW);}
// if (modes[6] == 1){digitalWrite(relay7, R7);}else{digitalWrite(relay7, LOW);}
// if (modes[7] == 1){digitalWrite(relay8, R8);}else{digitalWrite(relay8, LOW);}
// if (SolarValue > SolarpowerThreshold){
// if (modes[0] == 1){digitalWrite(relay1, HIGH);}
// if (modes[1] == 1){digitalWrite(relay2, HIGH);}
// if (modes[2] == 1){digitalWrite(relay3, HIGH);}
// if (modes[3] == 1){digitalWrite(relay4, HIGH);}
// if (modes[4] == 1){digitalWrite(relay5, HIGH);}
// if (modes[5] == 1){digitalWrite(relay6, HIGH);}
// if (modes[6] == 1){digitalWrite(relay7, HIGH);}
// if (modes[7] == 1){digitalWrite(relay8, HIGH);}
// }
// Display relay status on OLED
String relayStatus1 = "r1 " + getRelayStatusOled(relay1) + " r2 " + getRelayStatusOled(relay2);
String relayStatus2 = "r3 " + getRelayStatusOled(relay3) + " r4 " + getRelayStatusOled(relay4);
String relayStatus3 = "r5 " + getRelayStatusOled(relay5) + " r6 " + getRelayStatusOled(relay6);
String relayStatus4 = "r7 " + getRelayStatusOled(relay7) + " r8 " + getRelayStatusOled(relay8);
String relayStatusNew = relayStatus1 + relayStatus2 + relayStatus3 + relayStatus4;
if (relayStatusBeepOld != relayStatusNew) {
tone(buzzerPin, 1000, 500);
delay(1000);
relayStatusBeepOld = relayStatusNew;
}
}
// Function to activate power source based on input
void activatePowerSource(bool relay1State, bool relay2State, bool relay3State, bool relay4State, bool relay5State, bool relay6State, bool relay7State, bool relay8State) {
digitalWrite(relay1, relay1State ? HIGH : LOW);
digitalWrite(relay2, relay2State ? HIGH : LOW);
digitalWrite(relay3, relay3State ? HIGH : LOW);
digitalWrite(relay4, relay4State ? HIGH : LOW);
digitalWrite(relay5, relay5State ? HIGH : LOW);
digitalWrite(relay6, relay6State ? HIGH : LOW);
digitalWrite(relay7, relay7State ? HIGH : LOW);
digitalWrite(relay8, relay8State ? HIGH : LOW);
// Display relay status on OLED
String relayStatus1 = "r1 " + getRelayStatusOled(relay1) + " r2 " + getRelayStatusOled(relay2);
String relayStatus2 = "r3 " + getRelayStatusOled(relay3) + " r4 " + getRelayStatusOled(relay4);
String relayStatus3 = "r5 " + getRelayStatusOled(relay5) + " r6 " + getRelayStatusOled(relay6);
String relayStatus4 = "r7 " + getRelayStatusOled(relay7) + " r8 " + getRelayStatusOled(relay8);
String relayStatus5 = "r9 " + getRelayStatusOled(relay9);
String relayStatusNew = relayStatus1 + relayStatus2 + relayStatus3 + relayStatus4 + relayStatus5;
if (relayStatusBeepOld != relayStatusNew) {
tone(buzzerPin, 1000, 500);
delay(1000);
relayStatusBeepOld = relayStatusNew;
}
}
String getRelayStatusOled(int relayPin) {
return digitalRead(relayPin) ? "*" : "-";
}
void displayOnOLED(int row, int col, String text) {
oled.setCursor(col, row);
oled.println(text);
oled.display();
}
// Function to calculate the total power of turned-on relays
int calculateTotalPower() {
int totalPower = 0;
// Check each relay state and add corresponding load value if turned on
totalPower += digitalRead(relay1) == HIGH ? relay1_LoadVal : 0;
totalPower += digitalRead(relay2) == HIGH ? relay2_LoadVal : 0;
totalPower += digitalRead(relay3) == HIGH ? relay3_LoadVal : 0;
totalPower += digitalRead(relay4) == HIGH ? relay4_LoadVal : 0;
totalPower += digitalRead(relay5) == HIGH ? relay5_LoadVal : 0;
totalPower += digitalRead(relay6) == HIGH ? relay6_LoadVal : 0;
totalPower += digitalRead(relay7) == HIGH ? relay7_LoadVal : 0;
totalPower += digitalRead(relay8) == HIGH ? relay8_LoadVal : 0;
return totalPower;
}