#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// Define the OLED display size
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
// Initialize the OLED display
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// Pins
const int mainsVoltageSensorPin = A0;
const int mainsCurrentSensorPin = A1;
const int outputVoltageSensorPin = A2;
const int outputCurrentSensorPin = A3;
const int batteryVoltageSensorPin = A6;
const int batteryCurrentSensorPin = A7;
// Mains voltage threshold
const float mainsVoltageThreshold = 180.0; // Set your desired threshold for mains ON/OFF
// Battery parameters
const float batteryMaxVoltage = 12.0; // Max battery voltage
const float batteryMinVoltage = 10.0; // Min battery voltage (empty battery)
const float batteryCapacityAh = 100.0; // Battery capacity in amp-hours (adjust as needed)
// Backup time tracking
bool backupInProgress = false;
unsigned long backupStartTime = 0;
float batteryCapacityWh; // Battery capacity in watt-hours
// Timing variables
unsigned long previousMillis = 0;
const long interval = 10000; // 3 seconds interval for screen change
// Screen selector
int screenNumber = 0;
void setup() {
// Initialize Serial Monitor for debugging
Serial.begin(9600);
// Initialize OLED Display
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
// Initialize backup start time and battery capacity
backupStartTime = millis();
batteryCapacityWh = batteryCapacityAh * batteryMaxVoltage; // Capacity in watt-hours
}
void loop() {
// Timing to change screen
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
// Change screen number
screenNumber++;
if (screenNumber > 6) {
screenNumber = 0;
}
}
// Read mains voltage from sensor
int mainsVoltageSensorValue = analogRead(mainsVoltageSensorPin);
float mainsVoltage = (mainsVoltageSensorValue / 1023.0) * 250; // Assuming max voltage is 250V
// Read mains current from sensor
int mainsCurrentSensorValue = analogRead(mainsCurrentSensorPin);
float mainsVoltageForCurrent = mainsCurrentSensorValue * (5.0 / 1023.0); // Convert analog value to voltage
float mainsCurrent = (mainsVoltageForCurrent - 2.5) / 0.185; // Convert voltage to current (use correct sensitivity)
// Calculate mains wattage
float mainsWattage = mainsVoltage * mainsCurrent;
// Read output voltage from sensor
int outputVoltageSensorValue = analogRead(outputVoltageSensorPin);
float outputVoltage = (outputVoltageSensorValue / 1023.0) * 250; // Assuming max voltage is 250V
// Read output current from sensor
int outputCurrentSensorValue = analogRead(outputCurrentSensorPin);
float outputVoltageForCurrent = outputCurrentSensorValue * (5.0 / 1023.0); // Convert analog value to voltage
float outputCurrent = (outputVoltageForCurrent - 2.5) / 0.185; // Convert voltage to current (use correct sensitivity)
// Calculate output wattage
float outputWattage = outputVoltage * outputCurrent;
// Read battery voltage from sensor
int batteryVoltageSensorValue = analogRead(batteryVoltageSensorPin);
float batteryVoltage = (batteryVoltageSensorValue / 1023.0) * batteryMaxVoltage; // Assuming max voltage is 12V
// Read battery current from sensor
int batteryCurrentSensorValue = analogRead(batteryCurrentSensorPin);
float batteryVoltageForCurrent = batteryCurrentSensorValue * (5.0 / 1023.0); // Convert analog value to voltage
float batteryCurrent = (batteryVoltageForCurrent - 2.5) / 0.185; // Convert voltage to current (use correct sensitivity)
// Calculate battery wattage
float batteryWattage = batteryVoltage * batteryCurrent;
// Calculate load percentage
float loadPercentage = (outputWattage / 1000.0) * 100.0; // Adjusted for your max load
// Calculate battery percentage
float batteryPercentage = ((batteryVoltage - batteryMinVoltage) / (batteryMaxVoltage - batteryMinVoltage)) * 100.0;
// Ensure battery percentage is within 0-100%
if (batteryPercentage > 100.0) batteryPercentage = 100.0;
if (batteryPercentage < 0.0) batteryPercentage = 0.0;
// Update backup time if mains is off
if (mainsVoltage < mainsVoltageThreshold) {
if (!backupInProgress) {
backupInProgress = true;
backupStartTime = millis();
}
} else {
backupInProgress = false;
}
// Calculate kWh
float mainsEnergy = (mainsWattage / 1000.0) * (interval / 3600000.0); // kWh
float outputEnergy = (outputWattage / 1000.0) * (interval / 3600000.0); // kWh
// Calculate remaining backup time
float batteryRemainingWh = (batteryPercentage / 100.0) * batteryCapacityWh; // Remaining watt-hours
float loadWattage = outputWattage; // Assuming output wattage is the load
float remainingHours = batteryRemainingWh / loadWattage; // Remaining hours
// Clear the display
display.clearDisplay();
// Screen 0: Mains Status
if (screenNumber == 0) {
if (mainsVoltage >= mainsVoltageThreshold) {
display.setCursor(0, 0);
display.print("Mains: ON");
} else {
display.setCursor(0, 0);
display.print("Mains: OFF");
}
display.setCursor(0, 10);
display.print("Voltage: ");
display.print(mainsVoltage);
display.print(" V");
display.setCursor(0, 20);
display.print("Current: ");
display.print(mainsCurrent);
display.print(" A");
display.setCursor(0, 30);
display.print("Wattage: ");
display.print(mainsWattage);
display.print(" W");
}
// Screen 1: Output Status
else if (screenNumber == 1) {
display.setCursor(0, 0);
display.print("Output Status");
display.setCursor(0, 10);
display.print("Voltage: ");
display.print(outputVoltage);
display.print(" V");
display.setCursor(0, 20);
display.print("Current: ");
display.print(outputCurrent);
display.print(" A");
display.setCursor(0, 30);
display.print("Wattage: ");
display.print(outputWattage);
display.print(" W");
}
// Screen 2: Battery Status
else if (screenNumber == 2) {
if (mainsVoltage >= mainsVoltageThreshold) {
display.setCursor(0, 0);
display.print("Battery: Charging");
} else {
display.setCursor(0, 0);
display.print("Battery: Draining");
}
display.setCursor(0, 10);
display.print("Voltage: ");
display.print(batteryVoltage);
display.print(" V");
display.setCursor(0, 20);
display.print("Current: ");
display.print(batteryCurrent);
display.print(" A");
display.setCursor(0, 30);
display.print("Wattage: ");
display.print(batteryWattage);
display.print(" W");
}
// Screen 3: Output Load Percentage
else if (screenNumber == 3) {
display.setCursor(0, 0);
display.print("Output Load:");
display.setCursor(0, 10);
display.print(loadPercentage);
display.print(" %");
}
// Screen 4: Battery Percentage with Animation
else if (screenNumber == 4) {
display.setCursor(0, 0);
display.print("Battery: ");
display.print((int)batteryPercentage);
display.print(" %");
// Draw battery shape
display.drawRect(80, 20, 40, 20, SSD1306_WHITE); // Battery outline
display.fillRect(121, 25, 3, 10, SSD1306_WHITE); // Battery terminal
// Fill battery according to percentage
int batteryFill = (int)(batteryPercentage / 100.0 * 38); // Battery fill width (max 38 pixels)
display.fillRect(81, 21, batteryFill, 18, SSD1306_WHITE); // Fill battery level
}
// Screen 5: Backup Time
else if (screenNumber == 5) {
float remainingHours = batteryRemainingWh / outputWattage; // Remaining hours
int remainingDays = remainingHours / 24;
int remainingHoursInt = (int)remainingHours % 24;
int remainingMinutes = (int)((remainingHours - (int)remainingHours) * 60);
display.setCursor(0, 0);
display.print("Backup Time");
display.setCursor(0, 10);
display.print("Days: ");
display.print(remainingDays);
display.setCursor(0, 20);
display.print("Hours: ");
display.print(remainingHoursInt);
display.setCursor(0, 30);
display.print("Minutes: ");
display.print(remainingMinutes);
}
// Screen 6: Energy Usage (kWh)
else if (screenNumber == 6) {
display.setCursor(0, 0);
display.print("Energy Usage:");
display.setCursor(0, 10);
display.print("Mains: ");
display.print(mainsEnergy, 2); // Display kWh with 2 decimal places
display.print(" kWh");
display.setCursor(0, 20);
display.print("Output: ");
display.print(outputEnergy, 2); // Display kWh with 2 decimal places
display.print(" kWh");
}
// Display the updated information
display.display();
}