We had very hot summers in Belgium this and last year. When we returned from vacation, the house had heated up and it was impossible to cool it down as the hot weather continued.
This made me wonder if the heat-recovery ventilation unit's bypass system that should inject cold air into the house during the night is working properly and if it can be made to work better.
The ventilation unit generates and controls two air flows : the indoor-to-outside flow carrying moisture and CO2 and the outside-to-indoor fresh air flow. In normal working conditions the unit will extract thermal energy from the indoor-to-outdoor air stream and inject that energy back into the outdoor-to-indoor air stream, like illustrated below.
The system has 3 working levels. At present it is always at level two because it generates too much noise at level 3 for my family members to be able to fall asleep and because the cabling and the control algorithm to switch the working level are not in place
The unit has a bypass system that allows it to inactivate the heat exchanger during summer nights when the outside air is cooler than the inside of the house and when the house needs to be cooled down.
These are the things I have to evaluate/monitor in order to get answers to my main question :
- Does the bypass system work at all and does it work correctly ?
- Is it an option to increase the working level to 3 after everyone has fallen asleep during bypass operation ?
- Would an air moisturizer be a valuable investment ? Such a system cools down the indoor-to-outside air flow by humidifying it and uses the heat exchanger to cool down the outside-to-inside air flow. Such a setup can cool the house during the day, but it can only work effectively if the inside air is dry enough.
To get answers to my questions, I need to monitor temperature and humidity both before and after the heat exchanger on the two air streams, monitor the status of the bypass and have the ability to set the working level depending on temperature conditions and time.
Initial Ideas and TestsI used Si7021 sensor chips before, these would be ideal to monitor the temperature and humidity of the air flows.
After some testing with an old Gertboard, I found that the working level of the ventilation unit can be controlled with the ULM2803 open collector driver chip of the Gertboard.
That leaves the detection of the bypass operation to be tackled. The bypass is commanded with a 230V ac signal. After some Googling, I found some circuit examples for detecting 230V with a 3.3V controller, but none of them were satisfactory. As I didn't want to spend too much time on this challenge, I decided to go low-tech and use a simple relay to do the level conversion.
In Comes an ArduinoA mayor challenge in this setup is that the i²c address of the Si7021's is fixed. It is easy enough to read out one sensor directly from the rPi (Raspberry Pi), but more than one causes an i²c address collision and the rPi has only one i²c bus. There's a number of workarounds for this
- Selecting a different sensor chip with 4 different selectable i²c addresses
- Using an i²c multiplexer like the TCA9548
- Adding an Arduino to the setup
I decided to go with the last option because I have a number of Arduino's laying around and wanted to avoid buying more kit.
An Arduino can have any number of i²c busses thanks to the (many) soft-i²c libraries. The downside of this option is that it requires communication between the rPi and the Arduino. The options for this are : i2c, SPI, UART,... I decided to go for UART communication.
UART serial communication has a reputation for being tricky in essence because there's no protocol stack that cares for error correction like there is in the TCP/IP stack.
I decided not to use any helper libraries like Firmata (which add their own level of complexity), but to take some precautions to avoid the common pitfalls
- Use CR as separation symbol, this give me message separation support from the libraries/operating system both on the Arduino side and on the rPi side
- To keep the messages as simple as possible and shorter than the serial buffers at both sides, this way I don't have to worry about buffer overrun issues
- Design the protocol in such a way that losing messages is not a big deal
- Use the power of regular expressions to detect errors in messages and nothing more than that. Simply disregard messages that don't look right. Granted, this is a leap of faith, but I' a big fan of the KISS principle and I'll notice soon enough if my instinct on this one is wrong.
Here's how I designed the communication protocol between the two devices:
Arduino to Raspberry Pi
The Arduino will cycle through 6 steps (4 temperature sensors, set working level feedback and digital inputs) every few seconds and outputs.
- "S<x> <temperature> <humidity>" with x the sensor number 1-4
- "FB <wl>" with wl being the set working level
- "DI <a> <b>" with a=0|1 indicating the status of the bypass and B=0|1 being the status of the "filter dirty" output of the unit
I only need 1 measurement of each sensor every five minutes, so there's plenty of room for errors in the communication. As long as there is a CR symbol once in a while, the communication will automatically align. The CR symbol will appear regularly, so there's ample time for things to settle down after an error.
The UART ouput will be an ethernal repetition of something similar to
S1 24.043 66.422
S2 24.268 64.927
S3 24.161 64.530
S4 24.708 61.219
FB 3
DI 11
Raspberry Pi to Arduino
This one is even simpler as there is only the working level to be sent over: the rPi will send 1, 2 or 3 + CR to indicate which working level must be activated.
PCB Design
After initial tests with a breadboard and jumper wires, I decided this is not the way to go for the final product, so I needed to design a PCB.
I used Fritzing before but while trying to design the board, I came to the conclusion that Fritzing would fall short for this one. I used KiCad instead.
The schematics is attached as a file, below is a snapshot of the PCB design.
I scambled to get the order out before our holiday and the day after we returned, the PCB was in the letterbox. What a great era to live in!
This is how it looks after soldering the components
Here's a picture of both device "installed" on top of the ventilation unit. I know, cable management is not my strongest point :-)
Great! Now we can move on to the interesting part: developing software
Arduino FirmwareThanks to SparkFun's software i²c library, the Arduino firmware turns out to be compact and simple. Nothing complicated, just cycle through the 6 steps, collect measurements and format as decided in the protocol design. The .ino file is attached.
I use minicom to test the board with the Raspberry Pi. Thanks to the simple protocol, all I need to do is watch the measurement values come in and hit 1, 2 or 3 + <Enter> to change the working level of the ventilation unit.
Raspberry Pi SoftwareI got into the habit of using nodejs for this type of code. As usual with nodejs, the code is compact for what it's doing. Basically it monitors the serial port, disregards anything that doesn't look familiar, parses everything else and temporary stores the received measurements. Every five minutes, the last received measurements are pushed out to an MQTT broker and stored into an InfluxDb database.
Here's how one of the event handlers works (extract from app.js)
var port = new SerialPort(config.serialPort.portName, { baudRate: 57600 });
const parser = port.pipe(new Readline({ delimiter: '\n' }));
const sensorRegex = /S(\d)\s([-+]?[0-9]*\.?[0-9]*)\s([-+]?[0-9]*\.?[0-9]*)/;
parser.on('data', function (message) {
let sensorMatch = sensorRegex.exec(message);
if (sensorMatch !== null) {
let sensorId = parseInt(sensorMatch[1]);
let temp = parseFloat(sensorMatch[2]);
let hum = parseFloat(sensorMatch[3]);
let measurement = measurements.find((m) => m.id == sensorId);
if (measurement !== undefined) {
measurement.temperature = temp;
measurement.humidity = hum;
measurement.timestamp = Date.now();
};
}
});
The callback function in parser.on('data', callBack)
is called whenever a \n
symbol is received on the serial port. The sensorRegex
regular expression will match any string that starts with a capital 'S' followed immediately by a one-digit number and followed by two floating point numbers. Any part of the regular expression between round brackets (called capture groups) is extracted from the string and returned in the sensorMatch[i]
statements.
Next, the received sensorId
is searched within a pre-filled array of measurement
objects. If found, the temperature, humidity and timestamp values of the measurement object are updated.
Clearly, this code would be a lot more complex without the power of regular expressions. Regex101 is a great website to help you build and test regular expressions.
I use PM2 to deamonize node.js apps. It's a super tool, check it out.
Controlling the UnitThe working level of the unit can now be controlled by sending MQTT packets to the Raspberry Pi. This will have to be done by an algorithm running on the NAS in the future, but can be tested by using a program like mqtt-spy as shown below.
The heat wave is gone now so I'll have to wait till next summer to make final conclusions, but here are some preliminary ones:
The above graph is produced with Grafana on top of an Influx database running on my Synology NAS. The colours are purple: outside temperature (measured with a sensor outside the house), light-green: air extracted from the house, dark green: extracted air after the heat exchanger, light-blue: fresh outside air entering the unit, dark blue: fresh air behind the heat exchanger.
The activation and deactivation of the bypass can be observed in the dark green and dark blue lines.
Before 11:30 the bypass is active: the dark blue line is relatively close to the light green line as there is not much energy extracted from the extracted/expelled air flow. Between 11:30 and 14:00 the bypass switched off and on three times, When turned off, the dark green line jumps up and the dark blue line goes down because energy is exchanged between the fresh and the extracted air.
- Conclusion 1: the bypass works
- Conclusion 2: it doesn't all that well
The reason for conclusion 2 is that there is between 2.5° and 1.2° of difference between the fresh air entering and leaving the ventilation box (dark blue and dark green lines) which means that even with the bypass on, there is still heat exchanged, otherwise the dark green and the light blue line would coincide. The reason for this is in the construction of the ventilation unit. The bypass is has relatively small surface compared to the heat exchanger and the heat exchanger is not blocked when the bypass opens. The air will not 100% flow through the bypass but a large portion still flows through the heat exchanger.
- Observation 1: incoming fresh air is (a lot) hotter than the outside air
During the night, the incoming fresh air is about 3° hotter than the outside air (light blue vs light green line). This must be because of the accumulated heat in the piping system between the air intake register and the ventilation unit and it is not a good thing. I'll have to make this piping shorter and add insulation.
- Observation 2: there is a +/- 0.5° rimple on the air extracted from inside the house
This one is quite baffling. I have no idea why it is there. There was not heating in the house when the measurement was taken. I suspected the water boiler, but turning it off did not make the wobbly line go flat. Next suspects are the refrigerator or the freezer but these are not so easy to turn off.
- Observation 3: with the bypass off, the air flow going into the house is warmer than the air extracted from the house. (dark green line above the light green one)
The difference between the two temperatures is only a few tenths of degrees but it is very remarkable as it is... a direct violation of thermodynamics laws : heat will never travel from a colder to a hotter object by itself - the heat exchanger is a passive device. The only explanation I can come up with is measurement error. The Si7021's are accurate to within 0.5° so the few tenths of degrees fall within the combined measurement error for the two sensors.
Comments