From e4f93be75ee12eab2a3d1881ec47990b176fe731 Mon Sep 17 00:00:00 2001 From: Vincent van der Wal Date: Sun, 7 Sep 2025 15:41:16 +0200 Subject: [PATCH] fix overshoot --- index.html | 2 +- src/main.cpp | 49 ++++++++++++---------- src/main.ts | 114 +++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 121 insertions(+), 44 deletions(-) diff --git a/index.html b/index.html index 2806ce1..11a8958 100644 --- a/index.html +++ b/index.html @@ -48,7 +48,7 @@

Target temperature

-

+

diff --git a/src/main.cpp b/src/main.cpp index 1ec06e3..a75a91d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,10 +9,7 @@ #include "secrets.h" -// Create AsyncWebServer object on port 80 AsyncWebServer server(80); - -// Create a WebSocket object AsyncWebSocket ws("/ws"); // Json Variable to Hold Sensor Readings @@ -30,19 +27,23 @@ int thermoCLK = 5; MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO); +float temperature = 0; int targetTemp = 300; -float setOverShoot = 15; -float setUnderShoot = 10; +float setOverShoot = 20; +float setUnderShoot = 20; float derivedOverShoot = targetTemp; float derivedUnderShoot = targetTemp; unsigned long lastSwitch = 0; -unsigned long switchDelay = 30000; // 30s +unsigned long switchDelay = 30000; // 15s bool autoSwitch = true; // Get Sensor Readings and return JSON object String getSensorReadings() { - readings["temperature"] = thermocouple.readCelsius(); + temperature = thermocouple.readCelsius(); + + readings["temperature"] = temperature; + if (digitalRead(relay) == HIGH) { readings["relais"] = 1; @@ -51,6 +52,7 @@ String getSensorReadings() { readings["relais"] = 0; } + readings["target_temp"] = targetTemp; readings["derived_overshoot"] = derivedOverShoot; readings["derived_undershoot"] = derivedUnderShoot; @@ -161,23 +163,23 @@ void regulateRelais() { if (autoSwitch) { + 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 ((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 (temperature > overShootCorrectedTarget) // > 280°C { if (digitalRead(relay) == HIGH) { @@ -186,7 +188,10 @@ void regulateRelais() resetDerivedValues(); } } - else if (temperature < underShootCorrectedTarget) // < 310°C + } + if ((millis() - lastSwitch) > switchDelay) + { + if (temperature < underShootCorrectedTarget) // < 320°C { if (digitalRead(relay) == LOW) { diff --git a/src/main.ts b/src/main.ts index 0dd479e..5813a57 100644 --- a/src/main.ts +++ b/src/main.ts @@ -28,15 +28,23 @@ let relaisData = [ let temp = 300; let targetTemp = 300 +let setOverShoot = 30 +let setUnderShoot = 30 let targetTempOverShoot = 300 let targetTempUnderShoot = 300 +let lastSwitch = new Date() +let lastSwitchDuration = 0 const oven = document.querySelector('#oven') const temperature = document.querySelector('#temperature') const relaisSwitch = document.querySelector('#relais_switch') const relaisSwitchInput: HTMLInputElement | null = document.querySelector('#relais_switch_input') 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 hs: Highcharts.StockChart; @@ -91,10 +99,10 @@ const createChart = () => { enabled: false }, - title: { - text: 'Temperature', - align: 'left', - }, + // title: { + // text: 'Temperature', + // align: 'left', + // }, rangeSelector: { enabled: false, @@ -218,36 +226,95 @@ const onLoad = () => { } let d = new Date() - if (temp < 150) { - temp = temp + Math.random() * 4 - 1 - } else if (temp < 20) { - temp = temp + Math.random() * 4 - 1.3 - } 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 + if (temp < (targetTemp / 2)) { + temp = temp + Math.random() * 0.5 - 0.125 + } else if (temp < (targetTemp / (3 / 2))) { + temp = temp + Math.random() * 0.5 - 0.15 } 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) 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.yAxis[0].update({ plotLines: getTargetLines() }) hs.series[0].setData(temperatureData, true) - }, 250) + }, spoofInterval) } } } + + window.addEventListener('load', onLoad); const getReadings = () => { @@ -329,6 +396,9 @@ const switchRelais = () => { ws.send("switchRelais"); } else { // spoof some test data + let d = new Date() + lastSwitchDuration = d.getTime() - lastSwitch.getTime() + lastSwitch = new Date() if (!relais) { relais = 1 oven?.classList.add('on') @@ -338,7 +408,6 @@ const switchRelais = () => { } else { relais = 0 oven?.classList.remove('on') - relaisSwitch?.classList.remove('on') if (relaisSwitchInput) relaisSwitchInput.checked = false @@ -349,10 +418,13 @@ const switchRelais = () => { const changeTargetTemp = (e: Event) => { const target = e.target as HTMLTextAreaElement; let value = Number(target?.value) - // targetTemp = value console.log('Changed target temp to ' + value) if (!import.meta.env.DEV) { ws.send("setTargetTemp: " + pad(value, 3)); + } else { + targetTemp = value + targetTempOverShoot = value + targetTempUnderShoot = value } }