Using indoor dew-point and node-red to control temperature/relative humidity

This might interest those living in areas with high humidity and high heat (sticky weather), like me.

The background to this post is that I have been controlling my thermostat using a NR flow that uses the average temperature in my house, shifting the set-point down by 3 degrees when the average exceeds the set-point; when the average is lower than the set-point by 1 degree, the central AC is turned off by raising the set-point to be 5 degrees above ambient. Different set-points were used for Home, Away, and Sleep modes.

This worked well enough for ~6 months for temperature control. But the problem with this method is that it didn’t really take into account relative humidity. RH is a function of temperature. So while an RH of 60% is tolerable when the temperature is 70F, it is uncomfortable when the temperature is 75F.

I tried modifying my NR flow to trigger cooling based on RH. But this has its own issues - mainly that it promoted the equivalent of short-cycling. Or sometimes resulted in an uncomfortably cold situation, like 68F to achieve an RH end-point of 55%.

For a long time, I have wanted a thermostat that controlled my heat-pump based on indoor dew-point, the latter being a measure that takes both temperature and humidity into account. With nothing else to do, I decided to recreate a dew-point thermostat using NR, and then evaluate whether it created a more comfortable indoor environment. The goal of this exercise was the hope that controlling my heat-pump based on dew-point would take both temperature and relative humidity into account, and therefore provide better humidity control.

There are lots of charts comparing dew-point (Td) to human comfort perception that are available online. I used Td ranges based on this chart from meteorologist David Epstein. I chose a Td range of 57.5-55.0 Fahrenheit for Home mode (heat-pump turned on when Td > 57.5 and turned off when Td <= 55.0), 56.5-55.0 Fahrenheit for Sleep mode, and 60-57.5 Fahrenheit for Away mode.

Here’s what happened:

  1. My house used to frequently have an RH >60%, sometimes as high as 65%. The RH rarely exceeds 56% now.
  2. I used to never let the house get above 73F in Home mode. It can exceed that now and still feels fine.
  3. I used to keep the house at 70.5-71F in Sleep mode. It is around 72-72.5F now, and feels fine.
  4. Heat pump run times range from 20 minutes to > 1 hour. This has not changed from before. But overall, the heat-pump is running a little less each day.
  5. While I am a biased observer, one of the ladies who has been coming home to give me some assistance keeps commenting that my AC works better than theirs because it feels good in here. As far as I remember, she never said that back in July/August.

This is what the data looks like:

Cooling run time is the length of the thermostat “call for cool”. Indoor Temperature and Humidity are averages calculated from multiple sensors. The averaging algorithm periodically resets leading to dips/peaks in the data. Dew-point is calculated using the average temp/RH.

I use the August-Roche-Magnus approximation to calculate Td in NR. I got the equation from this website.

Here is my electric consumption from 9PM yesterday to 9AM today. The peaks are my heat-pump. When the peak is higher, it is in stage 2.

Here is my electric consumption from an equivalent day a few weeks ago before I started using Td to control the heat-pump. There's two examples of short-cycling (or least the heat-pump being turned off prematurely) in this profile.

I am happy to provide any of the sequences used to calculate Td or control the thermostat. But it may take me a while.


Cool (no pun intended). Mind posting the NR flow that calculated Td?

I'm in the gulf south, recently added an AprilAire whole-home dehumidifier. I installed this to address high indoor humidity issues after several improvements to the thermal envelope of the house (windows, attic foam, LED lighting,...). The A/C units 'became' oversized due to sensible load dramatic reduction following the improvements. I played around with different tweaks to address the high indoor humidity prior to biting the bullet on the AprilAire - lower variable speed fan CFM, reducing the compressor cycles/hr, installed two of the Honeywell T6 ZWave t-stats for each of my systems (upstairs and downstairs), and added some NR logic to manipulate set points.

So interested in your approach to control to a Td set point. With the dehumidifier installed, I wrote a Humidistat app for the Hubitat, so now I'm controlling relative humidity and temperature independently. Maybe I can use less overall energy with a variant of your approach.

Thanks for the detailed write up!

[{"id":"1ea41050.646bd8","type":"join","z":"74d2e0f3.800ff8","name":"Merge Temperature & Humidity","mode":"custom","build":"array","property":"payload.value","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":2490,"y":1329,"wires":[["2f6922d4.083d9e"]]},{"id":"e7dfd01c.baa86","type":"hubitat device","z":"74d2e0f3.800ff8","name":"Average Temperature","server":"a22e0ea9.276dc8","deviceId":"1794","attribute":"temperature","sendEvent":false,"x":2200,"y":1300,"wires":[["706a1e0a.946868","1ea41050.646bd8"]]},{"id":"2f6922d4.083d9e","type":"function","z":"74d2e0f3.800ff8","name":"Dew-point calculator","func":"function f2c(F) {\nvar C = 5 * ((F-32)/9);\nreturn C;\n}\nfunction dpC(T,RH) {\nvar Td = 243.04 * (Math.log(RH/100)+((17.625*T)/(243.04+T)))/(17.625-Math.log(RH/100)-((17.625*T)/(243.04+T)));\nreturn Td;\n}\nfunction c2f(C) {\nvar F = parseFloat((32 + (9*(C/5))).toFixed(2));\nreturn F;\n}\nvar tempf;\ntempf = msg.payload.value[0];\nvar rel_hum;\nrel_hum = msg.payload.value[1];\nvar tempc;\ntempc = f2c(tempf);\nvar dewpointc;\ndewpointc = dpC(tempc,rel_hum);\nmsg.payload = c2f(dewpointc);\nmsg.topic = \"dewpoint\";\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":2760,"y":1329,"wires":[["d5ef1b15.394d98"]]},{"id":"a4e7dde4.cca2b","type":"delay","z":"74d2e0f3.800ff8","name":"25ms","pauseType":"delay","timeout":"25","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":2315,"y":1360,"wires":[["1ea41050.646bd8"]],"l":false},{"id":"a6fe0688.6fdb1","type":"inject","z":"74d2e0f3.800ff8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"60","crontab":"","once":true,"onceDelay":"90","topic":"","payload":"","payloadType":"str","x":1970,"y":1331,"wires":[["e7dfd01c.baa86"]]},{"id":"706a1e0a.946868","type":"hubitat device","z":"74d2e0f3.800ff8","name":"Average Humidity","server":"a22e0ea9.276dc8","deviceId":"1794","attribute":"humidity","sendEvent":false,"x":2190,"y":1360,"wires":[["a4e7dde4.cca2b"]]},{"id":"d5ef1b15.394d98","type":"mqtt out","z":"74d2e0f3.800ff8","name":"Indoor Dewpoint","topic":"dewpoint","qos":"2","retain":"true","broker":"40144fb8.a1c1e","x":2990,"y":1329,"wires":[]},{"id":"a22e0ea9.276dc8","type":"hubitat config","z":"","name":"HubitatM","usetls":false,"host":"","port":"80","appId":"1522","nodeRedServer":"","webhookPath":"/hubitat/webhook","autoRefresh":true,"useWebsocket":false},{"id":"40144fb8.a1c1e","type":"mqtt-broker","z":"","name":"","broker":"","port":"1883","tls":"","clientid":"","usetls":false,"compatmode":false,"keepalive":"15","cleansession":true,"birthTopic":"","birthQos":"0","birthRetain":"false","birthPayload":"","closeTopic":"","closeRetain":"false","closePayload":"","willTopic":"","willQos":"0","willRetain":"false","willPayload":""}]