fix overshoot

This commit is contained in:
Vincent van der Wal
2025-09-07 15:41:16 +02:00
parent 46cb96d26b
commit e4f93be75e
3 changed files with 121 additions and 44 deletions
+1 -1
View File
@@ -48,7 +48,7 @@
<div class="card"> <div class="card">
<p class="card-title"> <p class="card-title">
Target temperature</p> Target temperature</p>
<p class="reading"><input type="number" min="0" max="600" placeholder="350" id="target_temperature"> <p class="reading"><input type="number" min="0" max="600" placeholder="300" id="target_temperature">
</input> <label for="target_temperature"> </input> <label for="target_temperature">
&deg;C &deg;C
</p> </p>
+17 -12
View File
@@ -9,10 +9,7 @@
#include "secrets.h" #include "secrets.h"
// Create AsyncWebServer object on port 80
AsyncWebServer server(80); AsyncWebServer server(80);
// Create a WebSocket object
AsyncWebSocket ws("/ws"); AsyncWebSocket ws("/ws");
// Json Variable to Hold Sensor Readings // Json Variable to Hold Sensor Readings
@@ -30,19 +27,23 @@ int thermoCLK = 5;
MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO); MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);
float temperature = 0;
int targetTemp = 300; int targetTemp = 300;
float setOverShoot = 15; float setOverShoot = 20;
float setUnderShoot = 10; float setUnderShoot = 20;
float derivedOverShoot = targetTemp; float derivedOverShoot = targetTemp;
float derivedUnderShoot = targetTemp; float derivedUnderShoot = targetTemp;
unsigned long lastSwitch = 0; unsigned long lastSwitch = 0;
unsigned long switchDelay = 30000; // 30s unsigned long switchDelay = 30000; // 15s
bool autoSwitch = true; bool autoSwitch = true;
// Get Sensor Readings and return JSON object // Get Sensor Readings and return JSON object
String getSensorReadings() String getSensorReadings()
{ {
readings["temperature"] = thermocouple.readCelsius(); temperature = thermocouple.readCelsius();
readings["temperature"] = temperature;
if (digitalRead(relay) == HIGH) if (digitalRead(relay) == HIGH)
{ {
readings["relais"] = 1; readings["relais"] = 1;
@@ -51,6 +52,7 @@ String getSensorReadings()
{ {
readings["relais"] = 0; readings["relais"] = 0;
} }
readings["target_temp"] = targetTemp; readings["target_temp"] = targetTemp;
readings["derived_overshoot"] = derivedOverShoot; readings["derived_overshoot"] = derivedOverShoot;
readings["derived_undershoot"] = derivedUnderShoot; readings["derived_undershoot"] = derivedUnderShoot;
@@ -161,9 +163,6 @@ void regulateRelais()
{ {
if (autoSwitch) if (autoSwitch)
{ {
if ((millis() - lastSwitch) > switchDelay)
{
float temperature = thermocouple.readCelsius();
float sinceLastSwitch = millis() - lastSwitch; float sinceLastSwitch = millis() - lastSwitch;
float fiveMinutesInMillis = 5 * 60 * 1000; float fiveMinutesInMillis = 5 * 60 * 1000;
float shootFactor = sinceLastSwitch / fiveMinutesInMillis; float shootFactor = sinceLastSwitch / fiveMinutesInMillis;
@@ -177,7 +176,10 @@ void regulateRelais()
float overShootCorrectedTarget = derivedOverShoot = targetTemp - dirivedOvershoot; float overShootCorrectedTarget = derivedOverShoot = targetTemp - dirivedOvershoot;
float underShootCorrectedTarget = derivedUnderShoot = targetTemp + dirivedUndershoot; float underShootCorrectedTarget = derivedUnderShoot = targetTemp + dirivedUndershoot;
if (temperature > overShootCorrectedTarget) // > 285°C if ((millis() - lastSwitch) > switchDelay)
{
if (temperature > overShootCorrectedTarget) // > 280°C
{ {
if (digitalRead(relay) == HIGH) if (digitalRead(relay) == HIGH)
{ {
@@ -186,7 +188,10 @@ void regulateRelais()
resetDerivedValues(); resetDerivedValues();
} }
} }
else if (temperature < underShootCorrectedTarget) // < 310°C }
if ((millis() - lastSwitch) > switchDelay)
{
if (temperature < underShootCorrectedTarget) // < 320°C
{ {
if (digitalRead(relay) == LOW) if (digitalRead(relay) == LOW)
{ {
+93 -21
View File
@@ -28,15 +28,23 @@ let relaisData = [
let temp = 300; let temp = 300;
let targetTemp = 300 let targetTemp = 300
let setOverShoot = 30
let setUnderShoot = 30
let targetTempOverShoot = 300 let targetTempOverShoot = 300
let targetTempUnderShoot = 300 let targetTempUnderShoot = 300
let lastSwitch = new Date()
let lastSwitchDuration = 0
const oven = document.querySelector('#oven') const oven = document.querySelector('#oven')
const temperature = document.querySelector('#temperature') const temperature = document.querySelector('#temperature')
const relaisSwitch = document.querySelector('#relais_switch') const relaisSwitch = document.querySelector('#relais_switch')
const relaisSwitchInput: HTMLInputElement | null = document.querySelector('#relais_switch_input') const relaisSwitchInput: HTMLInputElement | null = document.querySelector('#relais_switch_input')
const targetTempInput: HTMLInputElement | null = document.querySelector('#target_temperature') const targetTempInput: HTMLInputElement | null = document.querySelector('#target_temperature')
let spoofInterval = 10
let speedFactor = 250 / spoofInterval
const switchDelay = 60 / speedFactor * 1000
let maxValues = 4 * 60 * 60 // 60 minutes (4 values/sec) let maxValues = 4 * 60 * 60 // 60 minutes (4 values/sec)
let hs: Highcharts.StockChart; let hs: Highcharts.StockChart;
@@ -91,10 +99,10 @@ const createChart = () => {
enabled: false enabled: false
}, },
title: { // title: {
text: 'Temperature', // text: 'Temperature',
align: 'left', // align: 'left',
}, // },
rangeSelector: { rangeSelector: {
enabled: false, enabled: false,
@@ -218,36 +226,95 @@ const onLoad = () => {
} }
let d = new Date() let d = new Date()
if (temp < 150) { if (temp < (targetTemp / 2)) {
temp = temp + Math.random() * 4 - 1 temp = temp + Math.random() * 0.5 - 0.125
} else if (temp < 20) { } else if (temp < (targetTemp / (3 / 2))) {
temp = temp + Math.random() * 4 - 1.3 temp = temp + Math.random() * 0.5 - 0.15
} else if (temp < targetTemp) {
temp = temp + Math.random() * 4 - 1.5
} else if (temp >= targetTemp) {
temp = temp + Math.random() * 3 - 1.6
}
if (relais) {
temp = temp + 0.2
} else { } else {
temp = temp - 0.1 temp = temp + Math.random() * 0.5 - 0.25
}
let shootFactor = Math.min(((((d.getTime() - lastSwitch.getTime()) / speedFactor) - ((lastSwitchDuration * 0.5) / speedFactor))) / ((3 * 60 * 1000) / speedFactor), 1) // 5mins
shootFactor = shootFactor
if (relais == 0) {
temp = temp - 0.8 * shootFactor
} else {
temp = temp + 1 * shootFactor
}
let mod = temp % 0.25
if (mod > 0.125) {
temp = temp - mod + 0.25
} else {
temp = temp - mod
} }
if (temperature) if (temperature)
temperature.innerHTML = temp.toFixed(2); temperature.innerHTML = temp.toFixed(2);
temperatureData.push([d.getTime(), temp])
relaisData.push([d.getTime(), relais])
temperatureData.push([d.getTime(), temp])
let derivedShootFactor = Math.min(((d.getTime() - lastSwitch.getTime()) / speedFactor) / ((3 * 60 * 1000) / speedFactor), 1) // 5mins
let overshoot = setOverShoot * derivedShootFactor; // derive over 5 mins -> 1 min eq. 3°C, 5mins eq. 15°C
let dirivedOvershoot = Math.min(overshoot, setOverShoot);
let undershoot = setUnderShoot * derivedShootFactor; // derive over 5 min -> 1 min eq. 3°C, 5mins eq. 15°C
let dirivedUndershoot = Math.min(undershoot, setUnderShoot);
targetTempOverShoot = targetTemp - dirivedOvershoot;
targetTempUnderShoot = targetTemp + dirivedUndershoot;
if ((d.getTime() - lastSwitch.getTime()) > switchDelay) {
if (temp > targetTempOverShoot) // > 270 °C
{
if (relais == 1) {
relais = 0;
oven?.classList.remove('on')
relaisSwitch?.classList.remove('on')
if (relaisSwitchInput)
relaisSwitchInput.checked = false
targetTempOverShoot = targetTemp
targetTempUnderShoot = targetTemp
lastSwitchDuration = d.getTime() - lastSwitch.getTime()
lastSwitch = new Date()
}
}
}
if ((d.getTime() - lastSwitch.getTime()) > switchDelay) {
if (temp < targetTempUnderShoot) // < 310°C
{
if (relais == 0) {
relais = 1;
oven?.classList.add('on')
relaisSwitch?.classList.add('on')
if (relaisSwitchInput)
relaisSwitchInput.checked = true
targetTempOverShoot = targetTemp
targetTempUnderShoot = targetTemp
lastSwitchDuration = d.getTime() - lastSwitch.getTime()
lastSwitch = new Date()
}
}
}
relaisData.push([d.getTime(), relais])
hs.xAxis[0].update({ plotBands: getRelaisBands() }) hs.xAxis[0].update({ plotBands: getRelaisBands() })
hs.yAxis[0].update({ plotLines: getTargetLines() }) hs.yAxis[0].update({ plotLines: getTargetLines() })
hs.series[0].setData(temperatureData, true) hs.series[0].setData(temperatureData, true)
}, 250) }, spoofInterval)
} }
} }
} }
window.addEventListener('load', onLoad); window.addEventListener('load', onLoad);
const getReadings = () => { const getReadings = () => {
@@ -329,6 +396,9 @@ const switchRelais = () => {
ws.send("switchRelais"); ws.send("switchRelais");
} else { } else {
// spoof some test data // spoof some test data
let d = new Date()
lastSwitchDuration = d.getTime() - lastSwitch.getTime()
lastSwitch = new Date()
if (!relais) { if (!relais) {
relais = 1 relais = 1
oven?.classList.add('on') oven?.classList.add('on')
@@ -338,7 +408,6 @@ const switchRelais = () => {
} else { } else {
relais = 0 relais = 0
oven?.classList.remove('on') oven?.classList.remove('on')
relaisSwitch?.classList.remove('on') relaisSwitch?.classList.remove('on')
if (relaisSwitchInput) if (relaisSwitchInput)
relaisSwitchInput.checked = false relaisSwitchInput.checked = false
@@ -349,10 +418,13 @@ 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
console.log('Changed target temp to ' + value) console.log('Changed target temp to ' + value)
if (!import.meta.env.DEV) { if (!import.meta.env.DEV) {
ws.send("setTargetTemp: " + pad(value, 3)); ws.send("setTargetTemp: " + pad(value, 3));
} else {
targetTemp = value
targetTempOverShoot = value
targetTempUnderShoot = value
} }
} }