Skip to main content

Per room heating control with smart thermostats

This post is a continuation of my last post about KNX thermostats, which is part of my series about the troubleshooting of our heating system. In the last post I gave a "software sided" intro on our smart thermostats, but I've found the control theory behind these devices even more fascinating.

But first of all, let me introduce you to our thermostats:

As you can see, there are some leds, a push button and a rotary control labeled from -3 ... +3. The leds indicate the current operating mode (comfort, standby & night mode), as well as frost and heat protection. The rotary control allows the user to customize the temperature in the room: the mid-point is set with KNX parameters and the user may subtract from or add to maximum 3 degrees to that value.

I mentioned in the last article that the midpoints were not set to the same value, which could explain some of the temperature differences. I also mentioned that you can set an adjustment to the temperature measurement, which was also incorrect in one case.

What I wanted to explain in this post how this thermostat controls the valves by setting them on or off.

My initial assumption was that nothing could be simpler: whenever the temperature falls below a threshold (e.g. setpoint minus 0.5C), heating would turn on, and then when it reaches setpoint plus 0.5C it would turn it off. The difference between the lower and higher threshold is the hysteresis, as described nicely in this article. This way room temperature would always be around the setpoint, but would very rarely be the exact temperature that was set.

This assumption proved false, at least with the thermostat on display above.

I had to learn that there are more sophisticated control mechanisms, ones that can set match the setpoints to 0.1C accuracy, even if all the control they have is an on-off valve. A more thorough article about P-I-D (or PID for short) can be found here.

If you are not that patient, a short summary follows.

A PID controller is a combination (e.g. sum) of three terms (e.g. components). The last one or two components can be omitted, e.g. we can talk about a P-only and a PI controller, the first only using one component, the second omitting only the "D" component. The full concept is delivered when all the components are in use.

The goal of the PID controller is to determine how much we want to turn on heating, represented as a percentage from 0 to 100%. I know that I mentioned fully on or fully off valves that are unable to open halfway, much less to a random value, but more on that portion later. Let's just say for now, that the output of the PID function is a percentage: the capacity of heating we want enable. 0% means no heating, 100% means all we have.

Back to PID:
  • P for Proportional: proportional to the difference between setpoint and the current temperature (e.g. let's say 5C below the setpoint means 100% capacity, 2.5C would mean 50%)
  • I for Integral: in addition to P, it also takes the past into account, e.g. if the error is small (thus the P component would not increase capacity much) but has been around for a long time, we would still increase capacity as the time goes.
  • D for Derivative: in addition to PI, the derivative component takes the steepness of the change into account. E.g. it also matters how fast our increase of capacity results in the increase of temperature.
My thermostats are running PI, so they don't have the derivative component. But if you need to control temperature (or something else), look for a PID implementation, you can find one for Arduino here.

The tricky part of setting up PID is to set up the tuning parameters, I can't provide good advice there, if you are in that situation, just read the articles and do measurements to validate them back.

Back to the question of how we apply a percentage based capacity setting to an on-off valve? I already explained this in my last post, but let me repeat a bit: in every 10 minutes, keep them open for a time proportional to the capacity setting. If that setting is 70%, keep the valve open for seven minutes and closed for three minutes. If you need more juice, keep them open longer. At 100% you'll simply be opening the valves completely, without closing them off. This is pretty similar to how PWM is applied to leds, but at a much slower pace. And there's a reason for being slower: valve driving motors may not appreciate if you'd try to open the valve 50 per second :)

Comments

Popular posts from this blog

syslog-ng fun with performance

I like christmas for a number of reasons: in addition to the traditional "meet and have fun with your family", eat lots of delicious food and so on, I like it because this is the season of the year when I have some time to do whatever I feel like. This year I felt like doing some syslog-ng performance analysis. After reading Ulrich Deppert's series about stuff "What every programmer should know about memory" on LWN, I thought I'm more than prepared to improve syslog-ng performance. Before going any further, I'd recommend this reading to any programmer, it's a bit long but every second reading it is worth it. As you need to measure performance in order to improve it, I wrote a tool called "loggen". This program generates messages messages at a user-specifyable rate. Apart from the git repository you can get this tool from the latest syslog-ng snapshots. Loggen supports TCP, UDP and UNIX domain sockets, so really almost everything can be me...

syslog-ng OSE 2.1 released

I have just uploaded the first release in the syslog-ng Open Source Edition 2.1 branch to our website. It is currently only available in source format at this location: http://www.balabit.com/downloads/files/syslog-ng/sources/2.1/src This release synchronizes the core of syslog-ng to the latest PE version and adds the SQL destination driver. This is an alpha release and thus might be rough around the edges, but it basically only contains code already tested in the context of the Premium Edition. The SQL functionality requires a patched libdbi package, which is available at the same link. We're going to work on integrating all our libdbi related patches to the upstream package. If you want to know how the SQL logging works, please see the Administrator's Guide or our latest white paper Collecting syslog messages into an SQL database with syslog-ng. The latter describes the Premium Edition, but it applies to the Open Source one equally well.

syslog-ng 3.2 changes

I've just pushed a round of updates to the syslog-ng 3.2 repository, featuring some interesting stuff, such as: SQL reorganization: Patrick Hemmer sent in a patch to implement explicit transaction support instead of the previous auto-commit mode used by syslog-ng. I threw in some fixes and refactored the code somewhat. Configuration parser changes: the syntax errors produced by syslog-ng became much more user-friendly: not only the column is displayed, but also the erroneous line is printed and the error location is also highlighted. Additional plugin modules were created: afsql for the SQL destination, and afstreams for Solaris STREAMS devices. Creating a new plugin from core code takes about 15 minutes. I'm quite satisfied. With the addition of these two modules, it is now possible to use syslog-ng without any kind of runtime dependency except libc. The already existing afsocket module (providing tcp/udp sources & destinations) is compiled twice: once with and once withou...