#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <WiFi.h>
#include <WebServer.h>
#include "ButtonHandler.h"
#define RELAY1 16
#define RELAY2 17
#define RELAY3 18
#define VOLTAGE_PIN 34
#define BTN_UP 25
#define BTN_DOWN 26
#define BTN_SELECT 27
#define BTN_RESET 14
#define WIFI_SSID "Wokwi-GUEST"
#define WIFI_PASS ""
LiquidCrystal_I2C lcd(0x27, 20, 4);
WebServer server(80);
ButtonUp Up(BTN_UP);
ButtonDown Down(BTN_DOWN);
ButtonSelect Select(BTN_SELECT);
ButtonCancel Cancel(BTN_RESET);
bool relay1_state = false;
bool relay2_state = false;
bool relay3_state = false;
void handleRoot()
{
server.sendHeader("Content-Type", "text/html");
server.send(200, "text/html", R"rawliteral(
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Battery Discharge Control</title>
<style>
body { font-family: Arial, sans-serif; text-align: center; margin-top: 50px; }
h2 { color: #007bff; }
p { font-size: 18px; }
.container { max-width: 400px; margin: auto; border: 1px solid #ddd; padding: 20px; border-radius: 10px; box-shadow: 2px 2px 10px rgba(0,0,0,0.1); }
.controls { display: flex; justify-content: center; align-items: center; margin: 5px; }
button { font-size: 18px; margin: 5px; padding: 5px 10px; }
</style>
<script>
function updateData() {
fetch("/status")
.then(response => response.json())
.then(data => {
document.getElementById("voltage").innerText = data.voltage.toFixed(2) + " V";
document.getElementById("r1").innerText = data.thresholds[0].toFixed(2) + " V";
document.getElementById("r2").innerText = data.thresholds[1].toFixed(2) + " V";
document.getElementById("r3").innerText = data.thresholds[2].toFixed(2) + " V";
document.getElementById("hysteresis").innerText = data.hysteresis.toFixed(2) + " V";
})
.catch(error => console.error("Error fetching data:", error));
}
function sendUpdate(param, change) {
fetch(`/update?param=${param}&change=${change}`)
.then(response => response.text())
.then(() => updateData())
.catch(error => console.error("Error updating data:", error));
}
setInterval(updateData, 1000);
</script>
</head>
<body>
<div class="container">
<h2>Battery Voltage: <span id="voltage">10.01 V</span></h2>
<p>R1 Threshold: <span id="r1">10.01 V</span></p>
<div class="controls">
<button onclick="sendUpdate('r1', -0.01)">-</button>
<button onclick="sendUpdate('r1', 0.01)">+</button>
</div>
<p>R2 Threshold: <span id="r2">10.01 V</span></p>
<div class="controls">
<button onclick="sendUpdate('r2', -0.01)">-</button>
<button onclick="sendUpdate('r2', 0.01)">+</button>
</div>
<p>R3 Threshold: <span id="r3">10.01 V</span></p>
<div class="controls">
<button onclick="sendUpdate('r3', -0.01)">-</button>
<button onclick="sendUpdate('r3', 0.01)">+</button>
</div>
<p>Hysteresis: <span id="hysteresis">10.01 V</span></p>
</div>
</body>
</html>
)rawliteral");
}
// Modify values
void handleStatus()
{
String json = "{";
json += "\"voltage\":" + String(voltage, 2) + ",";
json += "\"thresholds\":[" + String(thresholds[0], 2) + "," +
String(thresholds[1], 2) + "," +
String(thresholds[2], 2) + "],";
json += "\"hysteresis\":" + String(hysteresis, 2);
json += "}";
server.send(200, "application/json", json);
}
// Refresh values
void handleUpdate()
{
if (!server.hasArg("param") || !server.hasArg("change"))
{
server.send(400, "text/plain", "Bad Request");
return;
}
String param = server.arg("param");
float change = server.arg("change").toFloat();
if (param == "r1") thresholds[0] += change;
else if (param == "r2") thresholds[1] += change;
else if (param == "r3") thresholds[2] += change;
server.send(200, "text/plain", "OK");
}
void setup()
{
Serial.begin(115200);
lcd.init();
lcd.backlight();
pinMode(RELAY1, OUTPUT);
pinMode(RELAY2, OUTPUT);
pinMode(RELAY3, OUTPUT);
pinMode(BTN_UP, INPUT_PULLUP);
pinMode(BTN_DOWN, INPUT_PULLUP);
pinMode(BTN_SELECT, INPUT_PULLUP);
pinMode(BTN_RESET, INPUT_PULLUP);
WiFi.begin(WIFI_SSID, WIFI_PASS);
int i = 0;
while (WiFi.status() != WL_CONNECTED)
{
if(i == 10) break;
i++;
delay(1000);
Serial.println("Connecting to Wi-Fi...");
}
if(WiFi.status() == WL_CONNECTED)
{
Serial.println("Wi-Fi connection is established!");
}
else
{
Serial.println("Couldn't connect to Wi-Fi!");
}
server.on("/", handleRoot);
server.on("/status", handleStatus);
server.on("/update", handleUpdate);
server.begin();
}
void loop()
{
server.handleClient();
voltage = analogRead(VOLTAGE_PIN) * (3.3 / 4095.0) * 5.0;
if(voltage > thresholds[0] + hysteresis) relay1_state = true;
if(voltage < thresholds[0] - hysteresis) relay1_state = false;
digitalWrite(RELAY1, relay1_state ? HIGH : LOW);
if(voltage > thresholds[1] + hysteresis) relay2_state = true;
if(voltage < thresholds[1] - hysteresis) relay2_state = false;
digitalWrite(RELAY2, relay2_state ? HIGH : LOW);
if(voltage > thresholds[2] + hysteresis) relay3_state = true;
if(voltage < thresholds[2] - hysteresis) relay3_state = false;
digitalWrite(RELAY3, relay3_state ? HIGH : LOW);
if(!editing)
{
Up.Scroll();
Down.Scroll();
Select.Select();
}
else
{
Up.ModifyThreshold();
Down.ModifyThreshold();
Select.Save();
Cancel.Cancel();
}
lcd.setCursor(0, 0);
lcd.print("N:");
lcd.print(voltage);
lcd.print("V");
lcd.print(" G:");
lcd.print(hysteresis);
lcd.print("V");
lcd.setCursor(0, 1);
lcd.print((selectedIndex == 0 ? ">" : " ")); lcd.print("R1:");
if(editing && selectedIndex == 0 )
{
lcd.print(tempThreshold); lcd.print("<");
}
else
{
lcd.print(thresholds[0]); lcd.print(" ");
}
lcd.setCursor(0, 2);
lcd.print((selectedIndex == 1 ? ">" : " ")); lcd.print("R2:");
if(editing && selectedIndex == 1 )
{
lcd.print(tempThreshold); lcd.print("<");
}
else
{
lcd.print(thresholds[1]); lcd.print(" ");
}
lcd.setCursor(0, 3);
lcd.print((selectedIndex == 2 ? ">" : " ")); lcd.print("R3:");
if(editing && selectedIndex == 2)
{
lcd.print(tempThreshold); lcd.print("<");
}
else
{
lcd.print(thresholds[2]); lcd.print(" ");
}
}
[BATTERY]