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 roadmap 2.1 & 2.2

We had a meeting on the syslog-ng roadmap today where we decided some important things, and I thought I'd use this channel to tell you about it. The Open Source Edition will see a 2.1 release incorporating all core changes currently in the Premium Edition and additionally the SQL destination driver. We are going to start development on the 2.2 PE features, but some of those will also be incorporated in the open source version: support for the latest work of IETF syslog protocols unique sequence numbering for messages support for parsing message contents Previously syslog-ng followed the odd/even version numbering to denote development/stable releases. I'm going to abandon this numbering now: the next syslog-ng OSE release is going to have a 2.1 version number and will basically come out with tested code changes only. The current feature set in PE were developed in a closed manner and I don't want to repeat this mistake. The features that were decided to be part of the Open

syslog-ng 3.0 and SNMP traps

Last time I've written about how syslog-ng is able to change message contents. I thought it'd be useful to give you a more practical example, instead of a generic description. It is quite common to convert SNMP traps to syslog messages. The easiest implementation is to run snmptrapd and have it create a log message based on the trap. There's a small issue though: snmptrapd uses the UNIX syslog() API, and as such it is not able to propagate the originating host of the SNMP trap to the hostname portion of the syslog message. This means that all traps are logged as messages coming from the host running snmptrapd, and the hostname information is part of the message payload. Of course it'd be much easier to process syslog messages, if this were not the case. A solution would be to patch snmptrapd to send complete syslog frames, but that would require changing snmptrapd source. The alternative is to use the new parse and rewrite features of syslog-ng 3.0. First, you need to f