# Thoughts on backing off room thermostat when 10c or 5c or 0c outside

**URL:** <https://discourse.nodered.org/t/thoughts-on-backing-off-room-thermostat-when-10c-or-5c-or-0c-outside/93066>\
**Category:** Hardware\
**Created:** [11 November 2024 11:59 UTC](https://discourse.nodered.org/t/thoughts-on-backing-off-room-thermostat-when-10c-or-5c-or-0c-outside/93066 "2024-11-11T11:59:01Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![questuk](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/questuk/32/4059_2.png) [@questuk](https://discourse.nodered.org/u/questuk)\
**Post date:** [11 November 2024 11:59 UTC](https://discourse.nodered.org/t/thoughts-on-backing-off-room-thermostat-when-10c-or-5c-or-0c-outside/93066/1 "2024-11-11T11:59:01Z")

</div>

Hi,

I have coded my own Arduino thermostat that is controlled by Node-RED and I can set it to various temperature 21c to 24c in .5c increments. I have noticed that at the the moment it is 10c outside and the room heating overshoots by .4c, I would like to get it closet to .1c.

I will modify my Arduino code so that it can adjust the set point down by .1 c increments

As an example set Arduino thermostat to 21c.  
My thoughts are measure temperature increase over 1 minute and if it has increased set Arduino thermostat to stop heating .2c earlier. ( That's a very simplified way of how I will do it )

For this I am going to use Node-RED and some sought of timer, but not sure what to use in Node-RED, as I am sure there are many ways to do this, what are your thoughts ?

Thanks

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [11 November 2024 12:15 UTC](https://discourse.nodered.org/t/thoughts-on-backing-off-room-thermostat-when-10c-or-5c-or-0c-outside/93066/2 "2024-11-11T12:15:31Z")

</div>

You should checkout the PID offering our very own @Colin offers.

> **[node-red-contrib-pid](https://flows.nodered.org/node/node-red-contrib-pid)**
>
> PID loop controller for Node-RED

demo flow: [PID control of a heating/cooling system with node-red-contrib-pid (flow) - Node-RED](https://flows.nodered.org/flow/4271d6617c89544ad318e7ab17211ba0)

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [11 November 2024 15:51 UTC](https://discourse.nodered.org/t/thoughts-on-backing-off-room-thermostat-when-10c-or-5c-or-0c-outside/93066/3 "2024-11-11T15:51:13Z")

</div>

I recommend using node-red-contrib-pid along with node-red-contrib-timeprop. The timeprop node will generate a time proportioned on/off signal to drive your heater. Modify the arduino code so that it just switches on/off as required by the timeprop signal.

Disclosure: I am the developer of both of those nodes.

---

<div class="post-metadata">

**Author:** ![questuk](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/questuk/32/4059_2.png) [@questuk](https://discourse.nodered.org/u/questuk)\
**Post date:** [12 November 2024 10:20 UTC](https://discourse.nodered.org/t/thoughts-on-backing-off-room-thermostat-when-10c-or-5c-or-0c-outside/93066/4 "2024-11-12T10:20:54Z")

</div>

Hi, Thanks Colin and Steve

Having thought about this more, I would like to develop simple code, that can be eventually incorporated into my Arduino thermostat code, so I can use if, then, millis, true, false ... etc

I have a working Node-RED code that checks for a difference in temperature and outputs that number and if the same outputs 0.

Also it sends true, but at the moment I am at a loss how to do check if this change is still true after 10 seconds has passed ( in the real code this will be over 5 minutes ) but for testing this is fine.

Here is my Node-RED code so far

```auto
[
    {
        "id": "91022929bf1fc133",
        "type": "inject",
        "z": "78823dae3d2dd990",
        "name": "",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "20.0",
        "payloadType": "num",
        "x": 400,
        "y": 390,
        "wires": [
            [
                "bc6ef697189fa2a9"
            ]
        ]
    },
    {
        "id": "22cc28fa0c441d5a",
        "type": "inject",
        "z": "78823dae3d2dd990",
        "name": "",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "20.01",
        "payloadType": "num",
        "x": 400,
        "y": 430,
        "wires": [
            [
                "bc6ef697189fa2a9"
            ]
        ]
    },
    {
        "id": "60bfe79be59ae3f1",
        "type": "inject",
        "z": "78823dae3d2dd990",
        "name": "",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "20.2",
        "payloadType": "num",
        "x": 400,
        "y": 470,
        "wires": [
            [
                "bc6ef697189fa2a9"
            ]
        ]
    },
    {
        "id": "942bb207e1aa8841",
        "type": "debug",
        "z": "78823dae3d2dd990",
        "name": "debug 165",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 650,
        "y": 350,
        "wires": []
    },
    {
        "id": "bc6ef697189fa2a9",
        "type": "function",
        "z": "78823dae3d2dd990",
        "name": "Check against previous",
        "func": "\nvar previous = flow.get(\"previousvalue\") || 0; // Get stored value, use payload if nothing is stored\nflow.set(\"previousvalue\", msg.payload); // Save this value for next time\n\nvar difference = msg.payload - previous; // Compare the two\nmsg.payload = difference;\n\n\nif (difference == 0) \n{\n global.set(\"timer\", false); // Save this value for checking against time.\n node.send(msg); \n}\nelse\n{\n global.set(\"timer\", true); // Save this value for checking against time.\n node.send(msg); \n}\n\n\n",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 630,
        "y": 390,
        "wires": [
            [
                "942bb207e1aa8841",
                "c62fcc1c2b353cd3"
            ]
        ]
    },
    {
        "id": "c62fcc1c2b353cd3",
        "type": "function",
        "z": "78823dae3d2dd990",
        "name": "Check rise in temperature against time",
        "func": " \nmsg.payload = global.get(\"timer\");\n\nif (msg.payload === true) \n{\n\n// Need code here to check if temperature has increased over 30 seconds\n\n node.send(msg); \n\n// If temperature has NOT increased over 30 seconds\n global.set(\"timer\", false);\n\n}\n\n\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 950,
        "y": 390,
        "wires": [
            [
                "c65b5322fa0ebc4b"
            ]
        ]
    },
    {
        "id": "c65b5322fa0ebc4b",
        "type": "debug",
        "z": "78823dae3d2dd990",
        "name": "debug 166",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 1010,
        "y": 350,
        "wires": []
    },
    {
        "id": "14053d0daad1e222",
        "type": "comment",
        "z": "78823dae3d2dd990",
        "name": "Temperatures",
        "info": "",
        "x": 380,
        "y": 350,
        "wires": []
    }
]

```

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [12 November 2024 11:32 UTC](https://discourse.nodered.org/t/thoughts-on-backing-off-room-thermostat-when-10c-or-5c-or-0c-outside/93066/5 "2024-11-12T11:32:02Z")

</div>

> [@questuk](#):
>
> I am at a loss how to do check if this change is still true after 10 seconds has passed

Personally I would do all this using the built in Switch and Trigger nodes, but if the purpose is to end up with code that you can move to the Arduino then I see why you want to write code to do it.

If you save the currrent time in milliseconds in context

```auto
const now = new Date().getTime() // current time in milliseconds
let lastSwitchTime = context.get("lastSwitchTime") ?? 0 // time last switched
...
// compare current time with last switched time
...
// when appropriate save the time switched
context.set("lastSwitchTime", now)
...

```

---

<div class="post-metadata">

**Author:** ![questuk](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/questuk/32/4059_2.png) [@questuk](https://discourse.nodered.org/u/questuk)\
**Post date:** [12 November 2024 11:54 UTC](https://discourse.nodered.org/t/thoughts-on-backing-off-room-thermostat-when-10c-or-5c-or-0c-outside/93066/6 "2024-11-12T11:54:55Z")

</div>

Hi Colin,

I have something close to what I want ( I had to resort to asking chatgpt ) 🙄

I an fine writing the code for Arduino as I have something similar already, but as my central heating and the Arduino are running my house heating at the moment, I thought it would be better to do all testing in Node-RED and simple send the command to my Arduino to change it's 'target temperature'. by 0.2 c etc

My only concern is if we have a power cut, I have to manually start Node-RED, so it would be better if eventually I have the code in my Arduino as that does auto recover. 👍

My code so far ( as I have not written this does it all look ok or anything could be improved )  
Thanks

```auto
const currentTemp = msg.payload;
const previousTemp = context.get('previousTemp') || currentTemp;
const lastTimestamp = context.get('lastTimestamp') || 0;
const currentTime = Date.now();

// Check if the last reading was within xx seconds
if (currentTime - lastTimestamp <= 30000) {
    // Compare temperatures
    if (currentTemp > previousTemp) {
        msg.payload = true;
    } else {
        msg.payload = false;
    }
} else {
    // If more than xx seconds, reset previous temperature
    msg.payload = false;
}

// Store current temperature and timestamp
context.set('previousTemp', currentTemp);
context.set('lastTimestamp', currentTime);

return msg;

```

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [12 November 2024 13:45 UTC](https://discourse.nodered.org/t/thoughts-on-backing-off-room-thermostat-when-10c-or-5c-or-0c-outside/93066/7 "2024-11-12T13:45:55Z")

</div>

> [@questuk](#):
>
> My only concern is if we have a power cut, I have to manually start Node-RED,

There are ways to autostart node red on boot. What OS are you running on?

> [@questuk](#):
>
> `const currentTime = Date.now();`

As in my suggested code, I suggest you work directly in msec, using getTime() to get that. The interpretor has to do that anyway any time you do arithmentic on a Date object so it is marginally more efficient to do that conversion once. Also the code analyser may give warnings when you do arithmetic on Dates as it does not know about the implicit conversion that will happen.

> [@questuk](#):
>
> `const previousTemp = context.get('previousTemp') || currentTemp;`

That code will fail to do what you expect if ever the previous temp is zero. You should use the newer `??` operator which tests for undefined and null rather than anything that is falsy. So use  
`const previousTemp = context.get('previousTemp') ?? currentTemp;`

---

<div class="post-metadata">

**Author:** ![questuk](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/questuk/32/4059_2.png) [@questuk](https://discourse.nodered.org/u/questuk)\
**Post date:** [12 November 2024 14:01 UTC](https://discourse.nodered.org/t/thoughts-on-backing-off-room-thermostat-when-10c-or-5c-or-0c-outside/93066/8 "2024-11-12T14:01:15Z")

</div>

Hi Colin,

I am using linux OS and Node-RED is running in Docker ( I know you dislike that, but I wanted to learn how to use it ). I can most probably start Docker if a power cut, but I also like my Arduino thermostat to run in a default mode set to 22c , without requiring Node-RED to be running.

I use Node-RED to adjust the temperature as my Arduino has no display i just use Node-RED GUI..

Thanks for the other suggestions, so much to learn over the years that I have been developing my home automation, I can do the code I need to in Node-RED and Arduino but certainly not anywhere near a master, so that's why I ask from time to time the wise people on here 👍

When someone points something out I always look for more info so I learn from it. 🤔

Thanks, I may well be back when I am further down the line on this particular code.

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [12 November 2024 14:04 UTC](https://discourse.nodered.org/t/thoughts-on-backing-off-room-thermostat-when-10c-or-5c-or-0c-outside/93066/9 "2024-11-12T14:04:38Z")

</div>

> [@questuk](#):
>
> I am using linux OS and Node-RED is running in Docker ( I know you dislike that,

I don't dislike Docker, it is a tool which is excellent when it is the appropriate tool. For most node-red users it adds just complexity for little, if any, gain.

---

<div class="post-metadata">

**Author:** ![questuk](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/questuk/32/4059_2.png) [@questuk](https://discourse.nodered.org/u/questuk)\
**Post date:** [12 November 2024 14:14 UTC](https://discourse.nodered.org/t/thoughts-on-backing-off-room-thermostat-when-10c-or-5c-or-0c-outside/93066/10 "2024-11-12T14:14:56Z")

</div>

Yes i agree, but in my case I knew I wanted Node-RED and grafana and sqlite and PostgreSQL as well.

So I gradually learnt how to use these without corrupting my linux OS and at worst just crashing Docker.

As I said I am no expert but I get by 🙃

Anyway thank you so much for your help and comments, i have just watched a video and learnt what ?? means.

---

<div class="post-metadata">

**Author:** ![questuk](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/questuk/32/4059_2.png) [@questuk](https://discourse.nodered.org/u/questuk)\
**Post date:** [12 November 2024 14:30 UTC](https://discourse.nodered.org/t/thoughts-on-backing-off-room-thermostat-when-10c-or-5c-or-0c-outside/93066/11 "2024-11-12T14:30:30Z")

</div>

Hi,

Just modified my code purely for testing and if the temperature is equal or above 20.3 to send out a command to my Arduino and now I have an error ?

Not sure if this is a problem and thoughts ?

Thanks

I did try `const currentTemp = msg.payload ?? 0;` but it didn't change that error

 ![17](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/b/3/b3002b7b42dfff0aa7b1838dec12bf33a0405237.png)

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [12 November 2024 14:33 UTC](https://discourse.nodered.org/t/thoughts-on-backing-off-room-thermostat-when-10c-or-5c-or-0c-outside/93066/12 "2024-11-12T14:33:01Z")

</div>

`=>` is a fat arrow function. `>=` is the "Greater than or Equal to" operator.

---

<div class="post-metadata">

**Author:** ![questuk](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/questuk/32/4059_2.png) [@questuk](https://discourse.nodered.org/u/questuk)\
**Post date:** [12 November 2024 14:34 UTC](https://discourse.nodered.org/t/thoughts-on-backing-off-room-thermostat-when-10c-or-5c-or-0c-outside/93066/13 "2024-11-12T14:34:59Z")

</div>

Thanks steve my silly mistake 🙄

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [11 January 2025 14:35 UTC](https://discourse.nodered.org/t/thoughts-on-backing-off-room-thermostat-when-10c-or-5c-or-0c-outside/93066/14 "2025-01-11T14:35:19Z")

</div>

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.
