first push
This commit is contained in:
commit
76bc7f4122
7
data/bootstrap.min.css
vendored
Normal file
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
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
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
BIN
data/opencure_logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 382 KiB |
323
opncure.ino
Normal file
323
opncure.ino
Normal 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user