📜 ⬆️ ⬇️

Temperature control in the house

In the previous article, “Weather Station with Ethernet and Tablet as a Display Device,” I talked about how I organized the collection, storage, processing and output of meteorological data in my home and beyond. It was also mentioned there that the principles underlying the system allow building something wider than just collecting weather data, and an article about temperature control was announced. It is time to fulfill the promise and tell about this very temperature control.


Introduction


Modern country house with independent heating usually implies the presence of a gas boiler. In the most primitive version of the heating control is carried out in two ways:
  1. For the task, so to speak, of the general thermophone in the house, the power that the boiler “pumps” into the batteries is set. Typically, the power adjustment is carried out in terms of the temperature of the water after the heating circuit.
  2. Since the rooms in the house are different (different windows, walls, sides of the world, etc.), they must also be heated in different ways. In conditions when the heating circuit for the whole house is one, this goal is achieved by adjusting the water supply to the batteries themselves.

At the same time, modern boilers, as a rule, support external control. The main purpose of this feature is to connect various kinds of thermostats, which allow to set the boiler power not in abstract degrees of water in batteries (the same water temperature figures can lead to completely different results depending on external conditions), but in terms of a much more understandable target temperature of the place where the regulator is installed. “External control” can mean anything, but usually it is either some kind of proprietary protocol of a specific equipment manufacturer (as, for example, Bosch does), or one of the implementations of the OpenTherm protocol.
The main problem of these thermostats for me is the price. When the cost of the boiler is about 25,000 rubles, the regulator price of 9,000 rubles seems somewhat too high.
As a result of bilateral consultations with the toad, an estimate was agreed upon, one and a half orders of magnitude lower than the cost of a typical commercial regulator, after which the development of options for the implementation of the homegrown regulator began.
The following objectives were set for the regulator:
  1. It must maintain the target temperature in the place whose temperature sensor is selected as the reference, with an accuracy of + -0.5 degrees
  2. It must allow the target temperature to be set.
  3. It should allow monitoring of the basic aspects of the regulator and the boiler itself.


Opentherm


The study of building possibilities began with a study of the capabilities of the boiler in external control. After removing the casing, a certain connector was found on which the jumper hung. The study of the documentation for the boiler instilled hope that it is the very connector for external control. Here we must mention the special zeal with which the Russian-language documentation was prepared for my Italian boiler Ferroli. The documentation has a description of the connectors. Opposite of me, the sacred inscription "Wednesday Unit" was listed. Intuition insistently hinted that it was the work of translators who were unfamiliar with the subject area, we should look for English-language documentation (they should have been better translated into English). After digging out PDFs with the English version of the boiler manual from the Internet, everything cleared up, opposite the same connector there was the text “Room unit”. There was also a ma-a-a-ah-ah icon, which with a certain amount of fantasy could be taken for the OpenTherm logo. “This is what you need” - I thought and began to plan atrocious experiments on the boiler (it was -25 outside the window, so it was time to burn the heater electronics).
Here you need to make the necessary excursion into OpenTherm. The protocol is not closed and not open. Not closed because if you have a specification, no one will haunt you. Not open because no one will give you a protocol specification. Join the OpenTherm Alliance for $$$$$$$$, then get access to the body of the protocol. Rummaging in the depths of the Internet, I got out the OT2.2 specification.
On the physical layer, OpenTherm is two low-current open-voltage lines of the order of 42V. The control device, being connected to them, can simultaneously feed and control the slave.
The specification defines two protocol levels: OT / + and OT / Lite.
The first is the protocol in the sense in which most people in IT understand this word. Those. it is a certain set of requests and responses that go between the control device (it’s the master unit, it’s the room unit, in our case, the controller) and the slave (it’s the slave unit, it’s the boiler). The protocol is divided into the obligatory part, which includes the commands “turn on / off the burner”, “report status” and “set that water temperature after the heating circuit (the parameter is called setpoint)”. In the optional - a bunch of others, ranging from controlling the modulation of the flame to the removal of gas flow, pressure and water velocity in the circuit. In this case, the control device controls the voltage change in these lines, and the slave responds by changing the current.
OT / Lite is a simpler thing. If you are not smart enough to implement OT / +, you can simply generate a PWM signal, according to the duty cycle of which the boiler will control the setpoint setting.
In addition, the specification also defines a test mode in which the lines are short-circuited. In this mode, the boiler heats until it gets bored (read, until the upper bar of the water temperature is reached, which is installed on the boiler itself). So the boiler works without an external regulator (so there was a jumper when opened there).
')

OpenTherm, but not quite


Immediately dispel the intrigue and say that steer the boiler on OpenTherm did not work. A pairing scheme was assembled and even a library was written that implements a fairly large part of OpenTherm, but the boiler stubbornly refused to be included in the OpenTherm control mode and did not respond. More precisely, the microcontroller did not register anything as an answer. Whether the boiler answered or not, it is impossible to say without an oscilloscope. As soon as an understanding of this fact came, a USB oscilloscope was ordered (it’s also an eight-channel logic analyzer, a USB-blaster) for 40 evergreens (which, I have to say, is just a megavext!). The oscilloscope, as it should be, had to go from China for an indefinite time and come somewhere in the spring, when the relevance of thermal control, hmm, is somewhat less than in winter. Therefore, it was decided to use the same test feature of OpenTherm to control the boiler in order to at least see what the idea might be.

How to steer the boiler


Contemplation of the boiler during the long winter evenings led to the understanding that the logic of its operation is quite simple. You set the temperature of the water (setpoint), say 55C. It begins to warm up until the temperature reaches 60C. It then turns off and on again when the water temperature reaches 50 ° C. A sort of swing with hysteresis around the set value. Having a "test feature", it is very easy to control the boiler using an external device so that it works exactly the same way as without it.
Another consequence of the contemplation of the boiler - an understanding of what water temperature you need to put on it, depending on the temperature outside, so that the house plus or minus bast was comfortable.
So, the boiler control consists of two algorithms:
  1. Burner on-off algorithm depending on the desired setpoint and the current water temperature
  2. Algorithm for calculating setpoint based on available temperature data

Here it is necessary to make the necessary digression to the principle of operation of thermostats available on the market. They come in two kinds:
  1. Classic. The principle of operation is colder than it should be - it is necessary to warm it, warmer - it is not necessary to warm it. The second principle - if it is much colder, you need to be very warm.
  2. The so-called regulators c OTC (outdoor temperature compensation), i.e. regulators with temperature compensation in the street. These are crafted. They allow the user to set the dependence of setpoint on the temperature outside. Theoretically, they should steer the temperature in the house more carefully

Since I had data on the temperature both in the rooms and in the street, I could, in principle, realize the device with OTC. In fact, both schemes were tested, and, confirmed by experiments, the second is more profitable.
I want to remind you that as a result of the implementation of the weather station, weather data appeared on the air around my house. The algorithm of the thermostat should be something like this:

Hardware


From the hardware it is required that it:
  1. Received data from the air
  2. Allows you to set the target temperature in the house
  3. Displayed baseline indicators
  4. She was able to "short the line" control of the boiler
  5. Send data about your work and the work of the boiler back to the air, so that they can be caught by the central unit and then visualized

These requirements dictate the scheme.
image
It is worth starting with the simplest part - part of the boiler control. JP1 is the connector to which two boiler control lines are connected. S1 is a toggle switch that short-circuits the control lines of the boiler and, thus, puts it into an autonomous mode (you never know what will happen to the controller). Bridge D1-D4 is needed to ensure tolerance on the polarity of the connection to the boiler. Optocoupler U1 acts as a relay and provides a galvanic isolation between the high-voltage line of the control of the boiler (remember, in the open state it is as much as 42V) and the TTL part of the circuit. R2 is the limiting resistor needed to ensure that the current through the D5 pin (through which the control is performed) of the microcontroller is not too large. In principle, this part could be replaced with low-current relays, but ... In the depths of the soul there is a hope that the boiler supports OT / + and will manage to manage it in a civilized way. The real scheme of interfacing with the boiler is somewhat more complicated. Here it is described only to the extent necessary to control the boiler in the closed / open mode.
The temperature sensor DS18B20 is connected to pin 12 of the microcontroller. A resistor R4 is connected between the DS18B20 data output and the power bus in accordance with the specifications.
LCD screen based on the HD44780 controller - two lines of eight characters. The classical connection scheme: Vcc - to the power bus, Vss - ground, the reference voltage for adjusting the contrast formed by the divider in the face of the building resistor R3 is applied to V0. R3 can be tweaked once to taste and forget. Conclusion R / W planted on the ground. The remaining pins are connected as follows: RS-> pins 11 of the controller, Enable -> 10, DB4-> 4, DB5-> 7, DB6-> 8, DB7-> 9.
The receiver is connected to pin 2, the transmitter to pin 3.
A variable resistor forming the divider is connected to pin A0. Based on the voltage at pin A0, the controller firmware will infer the target temperature in the house.

Software part


The algorithm works like this:
image
Basically, MK spends time waiting for messages on the air. If the message did not arrive within the specified time, the algorithm still performs the main body (after all, during this time the temperature of the water in the circuit could change and perhaps it was time to turn the burner on or off).
In parallel, the timer measures the voltage at A0, according to which the target temperature in the house is set. Voltage 0 corresponds to a temperature of 18C, voltage Vcc corresponds to a temperature of 26C. If the temperature changes, i.e. the user is currently turning the knob, then the screen is updated, on which three parameters are always displayed: the target room temperature, the water temperature in the circuit, the target water temperature in the circuit at the current time.
The target water temperature in the circuit is calculated by the following formula:
Trrw = 20 + (Trr-To) + (Tr-Trr) * 30, where
Trrw- target water temperature in the circuit
Trr - target temperature in the house
To - outside temperature
Tr - the temperature in the house
As you can see, there is some term of shift 20 (matched heuristically), the term OTC (Trr-To) which is greater, the greater the difference between the target temperature in the room and the temperature outside and the penalty for not reaching the target temperature in the room (Tr-Trr) * thirty.
The implementation of the algorithm is rather trivial, you can understand it by looking at the sketch of the firmware.
Sketch
#include <TimerTwo.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <VirtualWire.h>
#include <EEPROM.h>
#include <WirelessSensorPipe.h>
#include <LiquidCrystal.h>

#define DEBUG
#define INVALID_TEMPERATURE (1000)

/ * hardware configuration * /
#define DSPIN 12
#define TRANSMITPIN 3
#define RECEIVEPIN 2
#define HEATERCONTROLPIN 5
#define TARGETTEMPCONTROLPIN A0
// LCD pin mapping
#define LCDRS 11
#define LCDENABLE 10
#define LCDD4 4
#define LCDD5 7
#define LCDD6 8
#define LCDD7 9

#define RECEIVETIMEOUT 30 // wireless receive timeout

bool heater_enabled = false;
void enable_heater ()
{
digitalWrite (HEATERCONTROLPIN, HIGH);
heater_enabled = true;
}

void disable_heater ()
{
digitalWrite (HEATERCONTROLPIN, LOW);
heater_enabled = false;
}

float target_room_temperature, previous_target_room_temperature;
/ * reads target room temperature from the potentiometer and returns true if the value changed * /
bool updateTargetRoomTemp ()
{
uint16_t potentiometer_value = analogRead (TARGETTEMPCONTROLPIN);
target_room_temperature = 22 + 4 / 1024.0 * potentiometer_value;
if (fabs (target_room_temperature - previous_target_room_temperature) <0.1)
{
return false;
}
previous_target_room_temperature = target_room_temperature;
return true;
}

uint16_t cycle_counter = 0;
void targetTempChangeChecker ()
{
if (cycle_counter ++% 16 == 0) // max period of timer2 is 16ms,
{
if (updateTargetRoomTemp ())
updateOnScreenInfo ();
}
}

#define OUTSIDE_SENSOR_ID 27327
#define ROOM_SENSOR_ID 13467
#define TEMPERATURE_HYSTERESIS 5
#define HEATER_MAX_TEMP 80
#define HEATER_MIN_TEMP 30

float room_temperature = INVALID_TEMPERATURE;
float outside_temperature = INVALID_TEMPERATURE;
float RW_temperature;
float target_RW_temperature = 30;

OneWire one_wire (DSPIN);
DallasTemperature sensor (& one_wire);
void updateTargetRWTemperature ()
{
sensor.requestTemperatures ();
RW_temperature = sensor.getTempCByIndex (0);
target_RW_temperature = 20 + (target_room_temperature - outside_temperature) + (target_room_temperature - room_temperature) * 30;
target_RW_temperature = min (target_RW_temperature, HEATER_MAX_TEMP);
target_RW_temperature = max (target_RW_temperature, HEATER_MIN_TEMP);
}

LiquidCrystal lcd (LCDRS, LCDENABLE, LCDD4, LCDD5, LCDD6, LCDD7);
void updateOnScreenInfo ()
{
char floatBuffer [7];
lcd.setCursor (0,0);
lcd.print (F ("Room"));
lcd.print (dtostrf (target_room_temperature, 2, 1, floatBuffer));
lcd.setCursor (0,1);
lcd.print (F ("W"));
lcd.print ((int) RW_temperature);
lcd.print (F ("TW"));
lcd.print ((int) target_RW_temperature);
}

WirelessSensorPipe pipe;
void setup ()
{
#ifdef DEBUG
Serial.begin (9600);
Serial.println (F ("Entered setup"));
#endif
pinMode (HEATERCONTROLPIN, OUTPUT);
sensor.begin ();
pipe.begin (TRANSMITPIN, RECEIVEPIN, 13);

#ifdef DEBUG
Serial.print (F ("Sensor id:"));
Serial.println (pipe.id ());
#endif

updateTargetRoomTemp ();
updateTargetRWTemperature ();
TimerTwo :: init (16384, targetTempChangeChecker);
TimerTwo :: start ();

lcd.begin (8, 2);
}

int current_transmission_phase = 0;
void loop ()
{
#ifdef DEBUG
Serial.print (F ("Timestamp:"));
Serial.println (millis () / 1000);

Serial.print (F ("RW temperature:„));
Serial.println (RW_temperature);
Serial.print (F (“target_RW temperature:„));
Serial.println (target_RW_temperature);
Serial.print (F (“outside temperature:„));
Serial.println (outside_temperature);
Serial.print (F (“room temperature:„));
Serial.println (room_temperature);
Serial.print (F (“target room temperature:„));
Serial.println (target_room_temperature);

// blink the LED to read
// digitalWrite (13, HIGH);
// delay (100);
// digitalWrite (13, LOW);
#endif
updateTargetRoomTemp ();
lcd.begin (8,2); This is a temporary hack to get it off. shall be removed.
lcd.clear ();
updateOnScreenInfo ();
WirelessSensorPipe :: Packet packet;
if (pipe.receive (packet, RECEIVETIMEOUT * 1000))
{
if (packet.type == WirelessSensorPipe :: TEMPERATURE)
{
switch (packet.id)
{
case OUTSIDE_SENSOR_ID:
outside_temperature = packet.value;
break;
case ROOM_SENSOR_ID:
room_temperature = packet.value;
break;
}
}
return; // we’re skipping the code. If there is no one transmits
}
updateTargetRWTemperature ();
if (RW_temperature> = target_RW_temperature + TEMPERATURE_HYSTERESIS && target_RW_temperature <HEATER_MAX_TEMP)
{
disable_heater ();
}
if (RW_temperature <= target_RW_temperature - TEMPERATURE_HYSTERESIS && target_RW_temperature> HEATER_MIN_TEMP)
{
enable_heater ();
}

switch (current_transmission_phase ++)
{
case 0:
pipe.send (WirelessSensorPipe :: TEMPERATURE, room_temperature);
break;
case 1:
pipe.send (WirelessSensorPipe :: HEATERSETPOINT, target_RW_temperature);
break;
case 2:
pipe.send (WirelessSensorPipe :: HEATERRWTEMPERATURE, RW_temperature);
break;
case 3:
pipe.send (WirelessSensorPipe :: HEATERTARGETROOMTEMPERATURE, target_room_temperature);
break;
case 4:
pipe.send (WirelessSensorPipe :: HEATERFLAMEENABLED, heater_enabled);
current_transmission_phase = 0;
break;
}
}

It is necessary to mention that the work with the screen brought the most problems. Children's sores, like improper connection and initialization will not describe, but the problems associated with careless use of the timer, you can mention. The fact is that the first timer implementations read A0, calculated the temperature, and unconditionally updated the screen. The refresh rate was quite high - 2 Hz, and the screen refresh procedure is quite long. This led to the fact that the main loop of the algorithm (which it spends most of the time trying to receive something from the air) was often and permanently interrupted by the timer handler. This led to the fact that the software part of the receiver could not receive anything from the air, as it missed a lot during the distraction of the timer handler for execution. In addition, the screen is occasionally crazy and needs to be reinitialized in order to bring it to life. What is the reason for this behavior, I do not understand
The second problem I encountered was that the first place where the controller was installed turned out to be a place of brutal radio shadow.
These two problems have taken away from me a decent amount of evenings in trying to understand why the controller does not accept anything. The most opposite thing is that eliminating any of them did not improve the situation, it was necessary to solve both of them at the same time, so for a long time I was in error of the type “radio shadow is nothing to do with it” and “everything is fine with the receiving part”.
Another very bad idea was the transfer of all monitored parameters en masse to the airwaves at each iteration of the algorithm. The transmitted parameters include: room temperature, outdoor temperature (just repeat for control purposes), set target house temperature, calculated target water temperature, current water temperature, whether the boiler control circuit is closed or not. Since the execution of one iteration of the algorithm takes about 30 seconds, twice a minute a lot of packets were being broadcast on the air, which increased the probability of collisions. Therefore, we had to modify the firmware so that it sent only one parameter on the air in one iteration. Thus, each parameter was updated every 3 minutes.

Part list


Arduino Pro Mini - 100 rub apiece
DS18B20 - 34 rub apiece
Transmitter + 433MHz receiver - 40 rub apiece
LCD WH0802A-NGG-CT - 125 rub apiece
4N35 - 9 rub apiece
Diode Bridge DB107 - 5.5 rubles apiece
Resistors - only 5 rubles
Toggle switch (purchased offline) - 20 rubles
Building KR-606-PS - 40 rubles
The result - taking into account the solder, the breadboard, the wires and the amortization of the soldering iron - about 450 rubles. If I had ordered an LCD on Ebay, it would have been another 80 rubles cheaper.

Testing, conclusions, plans


Photos of the controller and the boiler under the spoiler. I apologize for the unevenly cut out window under the LCD.
A photo
image
image

But the DS18B20 is bolted to the boiler outlet
A photo
image

Photo of how the "control panel" looks on the same Strike.
A photo
image

As I said, two control schemes were implemented - the classical, i.e. “Not hot enough? Fry! ”, And with compensation for outdoor temperature.
In principle, the first one satisfied the requirements initially imposed on the system of statistics, i.e. provided the temperature in the room within half a degree from the target value. However, the disadvantage was oscillations around this very target value with an amplitude of almost half a degree. Those. the temperature in the room oscillated around the target, and this oscillation clearly could not be caused by external factors, since they were stable.
But the introduction of OTC gave an unexpected good result. Work on the algorithm in accordance with the formula above stabilized the temperature in the range of -0.2 + 0.1 degrees from the target. It should be noted that the dips of 0.2 degrees are not even connected with the features of the thermal control process, but with the fact that when someone opens hot water (for example, half an hour to wash) the boiler is engaged in providing hot water in the hot water circuit. The heating circuit is not heated.
image
The controller in this mode has been operating for half a month, the flight is normal, there were no failures. I can say that temperature control decently increases psychological comfort. If earlier it was necessary at least every evening and morning to set the water temperature in accordance with the current temperature on the street, the forecast and the testimony of our own intuition, which required some effort, now we don’t even remember that we have a boiler — it works and works.
The plans were to dog OT / +, the benefit of the ordered oscilloscope came, I already found out with his help that I even sent the wrong direction to the boiler I generally keep silent. In principle, the thermostat does not improve the work, but will allow you to shoot more diagnostics. In addition, it is now a fundamental problem from the category of "who is who."

Source: https://habr.com/ru/post/214257/


All Articles