first push

This commit is contained in:
Andrea Santaniello 2024-06-25 16:06:45 +02:00
commit 76bc7f4122
5 changed files with 339 additions and 0 deletions

7
data/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

7
data/bootstrap.min.js vendored Normal file

File diff suppressed because one or more lines are too long

2
data/jquery.min.js vendored Normal file

File diff suppressed because one or more lines are too long

BIN
data/opencure_logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 KiB

323
opncure.ino Normal file
View File

@ -0,0 +1,323 @@
#include <ESP8266WiFi.h>
#include <FS.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
#include <ESP8266WebServer.h>
#define DHT1_PIN 11
#define DHT2_PIN 12
#define RELAY_COOLING_PIN 13
#define RELAY_HEATING_PIN 14
#define DHT_TYPE DHT11
DHT dht1(DHT1_PIN, DHT_TYPE);
DHT dht2(DHT2_PIN, DHT_TYPE);
LiquidCrystal_I2C lcd(0x27, 20, 4);
ESP8266WebServer server(80);
const char* ssid = "OpenCure";
const char* password = "12345678";
enum Mode { OFF, TIME_MODE, HOLD_MODE, CURVE_MODE };
Mode currentMode = OFF;
float targetTemperature = 25.0;
unsigned long startTime = 0;
unsigned long duration = 0;
float surfaceTemp = 0.0;
float airTemp = 0.0;
float surfaceHum = 0.0;
float airHum = 0.0;
void setup() {
Serial.begin(115200);
pinMode(RELAY_COOLING_PIN, OUTPUT);
pinMode(RELAY_HEATING_PIN, OUTPUT);
digitalWrite(RELAY_COOLING_PIN, LOW);
digitalWrite(RELAY_HEATING_PIN, LOW);
dht1.begin();
dht2.begin();
lcd.begin(20,4);
lcd.backlight();
if (!SPIFFS.begin()) {
Serial.println("Failed to mount file system");
return;
}
WiFi.softAP(ssid, password);
server.on("/", handleRoot);
server.on("/bootstrap.min.css", []() {
serveFile("/bootstrap.min.css", "text/css");
});
server.on("/bootstrap.min.js", []() {
serveFile("/bootstrap.min.js", "application/javascript");
});
server.on("/jquery.min.js", []() {
serveFile("/jquery.min.js", "application/javascript");
});
server.on("/setTemperature", handleSetTemperature);
server.on("/setMode", handleSetMode);
server.begin();
Serial.println("HTTP server started");
lcd.setCursor(0, 0);
lcd.print("ESP8266 Peltier Fridge");
delay(2000);
}
void loop() {
server.handleClient();
updateSensors();
controlRelays();
updateLCD();
switch (currentMode) {
case TIME_MODE:
timeMode();
break;
case HOLD_MODE:
holdMode();
break;
case CURVE_MODE:
curveMode();
break;
case OFF:
disableRelays();
break;
}
}
void updateSensors() {
surfaceTemp = dht1.readTemperature();
surfaceHum = dht1.readHumidity();
airTemp = dht2.readTemperature();
airHum = dht2.readHumidity();
Serial.printf("Surface Temp: %.1f C, Air Temp: %.1f C\n", surfaceTemp, airTemp);
}
void enableCooling() {
digitalWrite(RELAY_HEATING_PIN, LOW);
delay(100);
digitalWrite(RELAY_COOLING_PIN, HIGH);
}
void enableHeating() {
digitalWrite(RELAY_COOLING_PIN, LOW);
delay(100);
digitalWrite(RELAY_HEATING_PIN, HIGH);
}
void disableRelays() {
digitalWrite(RELAY_COOLING_PIN, LOW);
digitalWrite(RELAY_HEATING_PIN, LOW);
}
void controlRelays() {
if (currentMode == OFF) {
disableRelays();
return;
}
if (targetTemperature < 25) {
if (airTemp > targetTemperature) {
enableCooling();
} else {
disableRelays();
}
} else if (targetTemperature > 25) {
if (airTemp < targetTemperature) {
enableHeating();
} else {
disableRelays();
}
} else {
disableRelays();
}
}
void updateLCD() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Target Temp: ");
lcd.print(targetTemperature, 1);
lcd.print(" C");
lcd.setCursor(0, 1);
lcd.print("Surface Temp: ");
lcd.print(surfaceTemp, 1);
lcd.print(" C");
lcd.setCursor(0, 2);
lcd.print("Air Temp: ");
lcd.print(airTemp, 1);
lcd.print(" C");
lcd.setCursor(0, 3);
lcd.print("Mode: ");
switch (currentMode) {
case TIME_MODE:
lcd.print("Time Mode");
break;
case HOLD_MODE:
lcd.print("Hold Mode");
break;
case CURVE_MODE:
lcd.print("Curve Mode");
lcd.setCursor(0, 3);
lcd.print("Elapsed: ");
lcd.print((millis() - startTime) / 1000, 1);
lcd.print(" s");
break;
case OFF:
default:
lcd.print("Off");
break;
}
}
void timeMode() {
if (millis() - startTime >= duration * 3600 * 1000) {
currentMode = OFF;
}
controlRelays();
}
void holdMode() {
controlRelays();
}
void curveMode() {
float elapsedTime = (millis() - startTime) / 1000.0;
float gaussValue = exp(-pow((elapsedTime - duration / 2.0), 2) / (2 * pow(duration / 6.0, 2)));
targetTemperature = targetTemperature * gaussValue;
if (elapsedTime >= duration) {
currentMode = OFF;
}
controlRelays();
}
void handleRoot() {
String html = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
<title>OpenCure</title>
<link rel="stylesheet" href="/bootstrap.min.css">
<script src="/jquery.min.js"></script>
<script src="/bootstrap.min.js"></script>
<script>
function setTemperature() {
var temp = document.getElementById('temperature').value;
$.get("/setTemperature?temp=" + temp, function(data) {
alert(data);
});
}
function setMode(mode) {
var duration = 0;
if (mode === 'time' || mode === 'curve') {
var hours = parseInt(document.getElementById('hours').value);
var minutes = parseInt(document.getElementById('minutes').value);
duration = (hours * 60 + minutes) * 60;
}
$.get("/setMode?mode=" + mode + "&duration=" + duration, function(data) {
alert(data);
});
}
</script>
</head>
<body>
<div class="container">
<h1>OpenCure</h1>
<div class="form-group">
<label for="temperature">Set Temperature (°C):</label>
<input type="number" class="form-control" id="temperature" placeholder="Enter temperature">
<button class="btn btn-primary mt-2" onclick="setTemperature()">Set Temperature</button>
</div>
<div class="form-group">
<label for="mode">Select Mode:</label>
<select class="form-control" id="mode" onchange="setMode(this.value)">
<option value="off">Off</option>
<option value="time">Time Mode</option>
<option value="hold">Hold Mode</option>
<option value="curve">Curve Mode</option>
</select>
</div>
<div class="form-group" id="time-settings" style="display: none;">
<label for="hours">Hours:</label>
<input type="number" class="form-control" id="hours" placeholder="Enter hours">
<label for="minutes">Minutes:</label>
<input type="number" class="form-control" id="minutes" placeholder="Enter minutes">
</div>
<script>
document.getElementById('mode').addEventListener('change', function () {
var mode = this.value;
if (mode === 'time' || mode === 'curve') {
document.getElementById('time-settings').style.display = 'block';
} else {
document.getElementById('time-settings').style.display = 'none';
}
});
</script>
</div>
</body>
</html>
)rawliteral";
server.send(200, "text/html", html);
}
void handleSetTemperature() {
if (server.hasArg("temp")) {
targetTemperature = server.arg("temp").toFloat();
server.send(200, "text/plain", "Temperature Set");
} else {
server.send(400, "text/plain", "Bad Request");
}
}
void handleSetMode() {
if (server.hasArg("mode")) {
String mode = server.arg("mode");
if (mode == "time") {
currentMode = TIME_MODE;
startTime = millis();
if (server.hasArg("duration")) {
duration = server.arg("duration").toInt();
}
} else if (mode == "hold") {
currentMode = HOLD_MODE;
} else if (mode == "curve") {
currentMode = CURVE_MODE;
startTime = millis();
if (server.hasArg("duration")) {
duration = server.arg("duration").toInt();
}
} else {
currentMode = OFF;
}
server.send(200, "text/plain", "Mode Set");
} else {
server.send(400, "text/plain", "Bad Request");
}
}
void serveFile(const char* path, const char* mimeType) {
File file = SPIFFS.open(path, "r");
if (file) {
server.streamFile(file, mimeType);
file.close();
} else {
server.send(404, "text/plain", "File Not Found");
}
}