mirror of
https://github.com/vincentvdwal/crust-craft.git
synced 2026-08-18 17:26:39 +02:00
add under and over shoot corrections
This commit is contained in:
@@ -141,4 +141,5 @@ ESP32Async/ESPAsyncWebServer | https://github.com/ESP32Async/ESPAsyncWebServer |
|
|||||||
|
|
||||||
### Display
|
### Display
|
||||||
|
|
||||||
In the long run a capacative LCD screen might be used in addition to the WebSocket connection
|
- Add capacative LCD screen to be used in addition to the WebSocket connection for direct control on the oven
|
||||||
|
- Maybe add sensor to indicate if the lid has been opened
|
||||||
+2
-2
@@ -15,7 +15,7 @@
|
|||||||
<div class="card-grid">
|
<div class="card-grid">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<p class="card-title">
|
<p class="card-title">
|
||||||
Temperature</p>
|
Sensor Temperature</p>
|
||||||
<p class="reading"><span id="temperature"></span> °C</p>
|
<p class="reading"><span id="temperature"></span> °C</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="card relais" id="relais_switch">
|
<div class="card relais" id="relais_switch">
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
<div class="oven" id="oven">
|
<div class="oven" id="oven">
|
||||||
<div class="oven-wrapper">
|
<div class="oven-wrapper">
|
||||||
<div class="oven-img-wrapper">
|
<div class="oven-img-wrapper">
|
||||||
<img src="/oven.png">
|
<img src="/oven_small.png">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+59
-14
@@ -31,10 +31,12 @@ int thermoCLK = 5;
|
|||||||
MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);
|
MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);
|
||||||
|
|
||||||
int targetTemp = 300;
|
int targetTemp = 300;
|
||||||
int overShoot = 10;
|
float setOverShoot = 15;
|
||||||
int underShoot = 5;
|
float setUnderShoot = 10;
|
||||||
|
float derivedOverShoot = targetTemp;
|
||||||
|
float derivedUnderShoot = targetTemp;
|
||||||
unsigned long lastSwitch = 0;
|
unsigned long lastSwitch = 0;
|
||||||
unsigned long switchDelay = 60000;
|
unsigned long switchDelay = 30000; // 30s
|
||||||
bool autoSwitch = true;
|
bool autoSwitch = true;
|
||||||
|
|
||||||
// Get Sensor Readings and return JSON object
|
// Get Sensor Readings and return JSON object
|
||||||
@@ -49,6 +51,9 @@ String getSensorReadings()
|
|||||||
{
|
{
|
||||||
readings["relais"] = 0;
|
readings["relais"] = 0;
|
||||||
}
|
}
|
||||||
|
readings["target_temp"] = targetTemp;
|
||||||
|
readings["derived_overshoot"] = derivedOverShoot;
|
||||||
|
readings["derived_undershoot"] = derivedUnderShoot;
|
||||||
serializeJson(readings, jsonString);
|
serializeJson(readings, jsonString);
|
||||||
return jsonString;
|
return jsonString;
|
||||||
}
|
}
|
||||||
@@ -108,11 +113,12 @@ void handleWebSocketMessage(void *arg, uint8_t *data, size_t len)
|
|||||||
digitalWrite(relay, HIGH);
|
digitalWrite(relay, HIGH);
|
||||||
lastSwitch = millis();
|
lastSwitch = millis();
|
||||||
}
|
}
|
||||||
|
resetDerivedValues();
|
||||||
}
|
}
|
||||||
if (message.startsWith("setTargetTemp"))
|
if (message.startsWith("setTargetTemp"))
|
||||||
{
|
{
|
||||||
String target = message.substring(15, 18);
|
String target = message.substring(15, 18);
|
||||||
targetTemp = target.toInt();
|
targetTemp = target.toFloat();
|
||||||
Serial.printf("\nTarget temp set to ");
|
Serial.printf("\nTarget temp set to ");
|
||||||
Serial.print(targetTemp);
|
Serial.print(targetTemp);
|
||||||
Serial.printf("°C");
|
Serial.printf("°C");
|
||||||
@@ -145,6 +151,54 @@ void initWebSocket()
|
|||||||
server.addHandler(&ws);
|
server.addHandler(&ws);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void regulateRelais()
|
||||||
|
{
|
||||||
|
if (autoSwitch)
|
||||||
|
{
|
||||||
|
if ((millis() - lastSwitch) > switchDelay)
|
||||||
|
{
|
||||||
|
float temperature = thermocouple.readCelsius();
|
||||||
|
float sinceLastSwitch = millis() - lastSwitch;
|
||||||
|
float fiveMinutesInMillis = 5 * 60 * 1000;
|
||||||
|
float shootFactor = sinceLastSwitch / fiveMinutesInMillis;
|
||||||
|
|
||||||
|
float overshoot = setOverShoot * shootFactor; // derive over 5 mins -> 1 min eq. 3°C, 5mins eq. 15°C
|
||||||
|
float dirivedOvershoot = min(overshoot, setOverShoot);
|
||||||
|
|
||||||
|
float undershoot = setUnderShoot * shootFactor; // derive over 5 min -> 1 min eq. 3°C, 5mins eq. 15°C
|
||||||
|
float dirivedUndershoot = min(undershoot, setUnderShoot);
|
||||||
|
|
||||||
|
float overShootCorrectedTarget = derivedOverShoot = targetTemp - dirivedOvershoot;
|
||||||
|
float underShootCorrectedTarget = derivedUnderShoot = targetTemp + dirivedUndershoot;
|
||||||
|
|
||||||
|
if (temperature > overShootCorrectedTarget) // > 285°C
|
||||||
|
{
|
||||||
|
if (digitalRead(relay) == HIGH)
|
||||||
|
{
|
||||||
|
digitalWrite(relay, LOW);
|
||||||
|
lastSwitch = millis();
|
||||||
|
resetDerivedValues();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (temperature < underShootCorrectedTarget) // < 310°C
|
||||||
|
{
|
||||||
|
if (digitalRead(relay) == LOW)
|
||||||
|
{
|
||||||
|
digitalWrite(relay, HIGH);
|
||||||
|
lastSwitch = millis();
|
||||||
|
resetDerivedValues();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetDerivedValues()
|
||||||
|
{
|
||||||
|
derivedOverShoot = targetTemp;
|
||||||
|
derivedUnderShoot = targetTemp;
|
||||||
|
}
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
Serial.begin(9600);
|
Serial.begin(9600);
|
||||||
@@ -172,16 +226,7 @@ void loop()
|
|||||||
{
|
{
|
||||||
String sensorReadings = getSensorReadings();
|
String sensorReadings = getSensorReadings();
|
||||||
notifyClients(sensorReadings);
|
notifyClients(sensorReadings);
|
||||||
if (((millis() - lastSwitch) > switchDelay) && thermocouple.readCelsius() >= (targetTemp - overShoot)) // >= 285°C
|
regulateRelais();
|
||||||
{
|
|
||||||
digitalWrite(relay, LOW);
|
|
||||||
lastSwitch = millis();
|
|
||||||
}
|
|
||||||
if (((millis() - lastSwitch) > switchDelay) && thermocouple.readCelsius() < (targetTemp - underShoot)) // < 270°C
|
|
||||||
{
|
|
||||||
digitalWrite(relay, HIGH);
|
|
||||||
lastSwitch = millis();
|
|
||||||
}
|
|
||||||
lastTime = millis();
|
lastTime = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+26
-13
@@ -19,17 +19,17 @@ let ws: WebSocket;
|
|||||||
const now = new Date()
|
const now = new Date()
|
||||||
|
|
||||||
let container: HTMLElement | null = document.querySelector('#plot')
|
let container: HTMLElement | null = document.querySelector('#plot')
|
||||||
let temperatureData = [
|
|
||||||
[now.getTime(), 25]
|
|
||||||
]
|
|
||||||
|
|
||||||
let relais = 0
|
let relais = 0
|
||||||
let relaisData = [
|
let relaisData = [
|
||||||
[now.getTime(), 0]
|
[now.getTime(), 0]
|
||||||
]
|
]
|
||||||
|
|
||||||
let temp = 25;
|
let temp = 300;
|
||||||
let targetTemp = 350
|
let targetTemp = 300
|
||||||
|
let targetTempOverShoot = 300
|
||||||
|
let targetTempUnderShoot = 300
|
||||||
|
|
||||||
const oven = document.querySelector('#oven')
|
const oven = document.querySelector('#oven')
|
||||||
const temperature = document.querySelector('#temperature')
|
const temperature = document.querySelector('#temperature')
|
||||||
@@ -42,6 +42,10 @@ let maxValues = 4 * 60 * 60 // 60 minutes (4 values/sec)
|
|||||||
let hs: Highcharts.StockChart;
|
let hs: Highcharts.StockChart;
|
||||||
let hsOptions: Highcharts.Options
|
let hsOptions: Highcharts.Options
|
||||||
|
|
||||||
|
let temperatureData = [
|
||||||
|
[now.getTime(), temp]
|
||||||
|
]
|
||||||
|
|
||||||
const getRelaisBands = () => {
|
const getRelaisBands = () => {
|
||||||
let relaisBands = []
|
let relaisBands = []
|
||||||
let active = false;
|
let active = false;
|
||||||
@@ -65,15 +69,18 @@ const getRelaisBands = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const dashStyle: DashStyleValue = 'Dash'
|
const dashStyle: DashStyleValue = 'Dash'
|
||||||
const getTargetLine = () => {
|
const getTargetLines = () => {
|
||||||
return [
|
return [
|
||||||
{ value: targetTemp, width: 3, dashStyle: dashStyle }
|
{ value: targetTemp, width: 3, dashStyle: dashStyle },
|
||||||
|
{ value: targetTempOverShoot, width: 1, dashStyle: dashStyle, color: "red" },
|
||||||
|
{ value: targetTempUnderShoot, width: 1, dashStyle: dashStyle, color: "red" }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
const createChart = () => {
|
const createChart = () => {
|
||||||
hsOptions = {
|
hsOptions = {
|
||||||
chart: {
|
chart: {
|
||||||
|
height: '650px',
|
||||||
animation: {
|
animation: {
|
||||||
duration: 250,
|
duration: 250,
|
||||||
easing: 'linear'
|
easing: 'linear'
|
||||||
@@ -121,7 +128,7 @@ const createChart = () => {
|
|||||||
to: 600,
|
to: 600,
|
||||||
color: 'rgba(255, 0, 0, 0.4)'
|
color: 'rgba(255, 0, 0, 0.4)'
|
||||||
}],
|
}],
|
||||||
plotLines: getTargetLine()
|
plotLines: getTargetLines()
|
||||||
},
|
},
|
||||||
|
|
||||||
xAxis: {
|
xAxis: {
|
||||||
@@ -233,7 +240,7 @@ const onLoad = () => {
|
|||||||
|
|
||||||
|
|
||||||
hs.xAxis[0].update({ plotBands: getRelaisBands() })
|
hs.xAxis[0].update({ plotBands: getRelaisBands() })
|
||||||
hs.yAxis[0].update({ plotLines: getTargetLine() })
|
hs.yAxis[0].update({ plotLines: getTargetLines() })
|
||||||
hs.series[0].setData(temperatureData, true)
|
hs.series[0].setData(temperatureData, true)
|
||||||
}, 250)
|
}, 250)
|
||||||
}
|
}
|
||||||
@@ -302,10 +309,16 @@ const onMessage = (event: MessageEvent) => {
|
|||||||
if (relaisSwitchInput)
|
if (relaisSwitchInput)
|
||||||
relaisSwitchInput.checked = false
|
relaisSwitchInput.checked = false
|
||||||
}
|
}
|
||||||
|
} else if (key === 'target_temp') {
|
||||||
|
targetTemp = myObj[key]
|
||||||
|
} else if (key === 'derived_overshoot') {
|
||||||
|
targetTempOverShoot = myObj[key]
|
||||||
|
} else if (key === 'derived_undershoot') {
|
||||||
|
targetTempUnderShoot = myObj[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
hs.xAxis[0].update({ plotBands: getRelaisBands() })
|
hs.xAxis[0].update({ plotBands: getRelaisBands() })
|
||||||
hs.yAxis[0].update({ plotLines: getTargetLine() })
|
hs.yAxis[0].update({ plotLines: getTargetLines() })
|
||||||
hs.series[0].setData(temperatureData, true)
|
hs.series[0].setData(temperatureData, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -336,10 +349,10 @@ const switchRelais = () => {
|
|||||||
const changeTargetTemp = (e: Event) => {
|
const changeTargetTemp = (e: Event) => {
|
||||||
const target = e.target as HTMLTextAreaElement;
|
const target = e.target as HTMLTextAreaElement;
|
||||||
let value = Number(target?.value)
|
let value = Number(target?.value)
|
||||||
targetTemp = value
|
// targetTemp = value
|
||||||
console.log('Changed target temp to ' + targetTemp)
|
console.log('Changed target temp to ' + value)
|
||||||
if (!import.meta.env.DEV) {
|
if (!import.meta.env.DEV) {
|
||||||
ws.send("setTargetTemp: " + pad(targetTemp, 3));
|
ws.send("setTargetTemp: " + pad(value, 3));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -36,7 +36,7 @@ p {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.graph {
|
.graph {
|
||||||
height: 310px;
|
height: 570px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|||||||
Reference in New Issue
Block a user