Skip to content

Instantly share code, notes, and snippets.

@glsorre
Last active December 15, 2023 12:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save glsorre/ad251988b618979310fcc0347b8f658b to your computer and use it in GitHub Desktop.
Save glsorre/ad251988b618979310fcc0347b8f658b to your computer and use it in GitHub Desktop.
Basic javascript thermostat to be used with nodered

Basic javascript thermostat to be used with nodered

Here's the output on the columns there are external temperatures. On the rows internal temperatures.

│       │  -2   │  -1   │   0   │   1   │   2   │   3   │   4   │   5   │   6   │   7   │   8   │   9   │  10   │  11   │  12   │  13   │  14   │  15   │  16   │  17   │
|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
│  15   │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │
│ 15.25 │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │
│ 15.5  │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │
│ 15.75 │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │
│  16   │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │
│ 16.25 │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │
│ 16.5  │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │
│ 16.75 │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │
│  17   │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │
│ 17.25 │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │ 'MIN' │
│ 17.5  │ 'ON'  │ 'ON'  │ 'ON'  │ 'ON'  │ 'ON'  │ 'ON'  │ 'ON'  │ 'ON'  │ 'ON'  │ 'ON'  │ 'BUF' │ 'BUF' │ 'BUF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │
│ 17.75 │ 'ON'  │ 'ON'  │ 'ON'  │ 'ON'  │ 'ON'  │ 'ON'  │ 'ON'  │ 'ON'  │ 'ON'  │ 'BUF' │ 'BUF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │
│  18   │ 'ON'  │ 'ON'  │ 'ON'  │ 'ON'  │ 'ON'  │ 'ON'  │ 'ON'  │ 'ON'  │ 'BUF' │ 'BUF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │
│ 18.25 │ 'ON'  │ 'ON'  │ 'ON'  │ 'ON'  │ 'ON'  │ 'ON'  │ 'BUF' │ 'BUF' │ 'BUF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │
│ 18.5  │ 'ON'  │ 'ON'  │ 'ON'  │ 'ON'  │ 'ON'  │ 'BUF' │ 'BUF' │ 'BUF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │
│ 18.75 │ 'ON'  │ 'ON'  │ 'ON'  │ 'ON'  │ 'BUF' │ 'BUF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │
│  19   │ 'ON'  │ 'ON'  │ 'ON'  │ 'BUF' │ 'BUF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │
│ 19.25 │ 'BUF' │ 'BUF' │ 'BUF' │ 'BUF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │
│ 19.5  │ 'BUF' │ 'BUF' │ 'BUF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │
│ 19.75 │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │
│  20   │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │ 'OFF' │
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> THIS IS THE IMPORTANT PIECE >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
const targetTemperatureBuffer = .5
const minimalTargetTemperature = 17.5
const targetTemperature = 19
const externalCutOffTemperature = 16.5
const deltaTargetTemperature = (et, tt, co) => {
if (et <= 0) {
return tt
} else if (et > 0 && et <= co) {
return - .075 * et + tt
} else {
return -Infinity
}
}
const deltaMinimalTargetTemperature = (et, tt, co) => {
if (et <= 0) {
return tt
} else if (et > 0 && et <= co) {
return - .0325 * et + tt
} else {
return -Infinity
}
}
function heatThermostat(externalTemperature, internalTemperature, targetTemperature, minimalTargetTemperature, targetTemperatureBuffer, externalCutOffTemperature) {
const optimalMinimalTemperatureTarget = deltaMinimalTargetTemperature(externalTemperature, minimalTargetTemperature, externalCutOffTemperature)
const optimalTemperatureTarget = deltaTargetTemperature(externalTemperature, targetTemperature, externalCutOffTemperature)
if (internalTemperature < optimalMinimalTemperatureTarget + targetTemperatureBuffer) {
return internalTemperature <= optimalMinimalTemperatureTarget ? 'MIN' : 'MBF'
}
if (
internalTemperature <= optimalTemperatureTarget + targetTemperatureBuffer
) {
return internalTemperature <= optimalTemperatureTarget ? 'ON' : 'OBF'
}
return 'OFF'
}
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
const internalTemperaturesSequence = [ 15, 15.25, 15.5, 15.75, 16, 16.25, 16.5, 16.75, 17, 17.25, 17.5, 17.75, 18, 18.25, 18.5, 18.75, 19, 19.25, 19.5, 19.75, 20, 20.25, 20.5, 20.75, 21, 21.25, 21.5, 21.75, 22, 22.25, 22.5, 22.75, 23 ]
const externalTemperaturesSequence = [ -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 ]
const results = [ [ ...externalTemperaturesSequence ] ]
for (let i = 0; i < internalTemperaturesSequence.length; i++) {
results[i + 1] = [ internalTemperaturesSequence[i] ]
}
results[0].unshift('+')
for (let i = 0; i < internalTemperaturesSequence.length; i++) {
const internalTemperature = internalTemperaturesSequence[i]
for (let j = 0; j < externalTemperaturesSequence.length; j++) {
const externalTemperature = externalTemperaturesSequence[j]
const result = heatThermostat(externalTemperature, internalTemperature, targetTemperature, minimalTargetTemperature, targetTemperatureBuffer, externalCutOffTemperature)
results[i + 1][j + 1] = result
}
}
console.table(results)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment