Raspberry pi Multi Zone Heating Control System Relay: If your house have Multi Zone Heating then you can control each zone heating independently with raspberry pi and this will save you lot on your heating cost considering that you don’t have to heat all the house all the time. In this post i will show you how to build wired multi zone heating control system relay and control it from raspberry pi gpio so we can open and close zone valve to circulate water in each zone as needed.
Firstly we will connect the raspberry pi and the 4 relay module and test it from command line, but before we do that can you make sure you have WiringPi installed on your raspberry pi otherwise this wouldn’t work at all.
Note: WiringPi Pin number and Raspberry Pi GPIO numbers are not the same and make sure you have correct WiringPi GPIO saved int MySQL/MariaDB table otherwise you will have problems, see below image for Raspberry Pi GPIO pins and WiringPi Pins.
Raspberry Pi Relay Module Wiring connection for zoned heating system.
MySQL/MariaDB Zone Table
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
CREATE TABLE `zone` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `status` TINYINT(4) NULL DEFAULT NULL, `index_id` TINYINT(4) NULL DEFAULT NULL, `name` CHAR(50) NULL DEFAULT NULL COLLATE 'utf8_bin', `type` CHAR(50) NULL DEFAULT NULL COLLATE 'utf8_bin', `model` CHAR(50) NULL DEFAULT NULL COLLATE 'utf8_bin', `max_c` TINYINT(4) NULL DEFAULT NULL, `max_operation_time` TINYINT(4) NULL DEFAULT NULL, `hysteresis_time` TINYINT(4) NULL DEFAULT NULL, `sensor_id` INT(11) NULL DEFAULT NULL, `sensor_child_id` INT(11) NULL DEFAULT NULL, `controler_id` INT(11) NULL DEFAULT NULL, `controler_child_id` INT(11) NULL DEFAULT NULL, `boiler_id` INT(11) NULL DEFAULT NULL, `gpio_pin` INT(11) NULL DEFAULT NULL, PRIMARY KEY (`id`), INDEX `FK_zone_nodes` (`sensor_id`), INDEX `FK_zone_nodes_2` (`controler_id`), INDEX `FK_zone_boiler` (`boiler_id`), CONSTRAINT `FK_zone_boiler` FOREIGN KEY (`boiler_id`) REFERENCES `boiler` (`id`), CONSTRAINT `FK_zone_nodes` FOREIGN KEY (`sensor_id`) REFERENCES `nodes` (`id`), CONSTRAINT `FK_zone_nodes_2` FOREIGN KEY (`controler_id`) REFERENCES `nodes` (`id`) ) COLLATE='utf8_bin' ENGINE=InnoDB AUTO_INCREMENT=1 ; |
PHP Script to Run Test for Zone/Boiler Relay
You can download this script from PiHome github or you can copy below and save it as php file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
<?php #!/usr/bin/php echo "\033[36m"; echo "\n"; echo " _____ _ _ _ \n"; echo " | __ \ (_) | | | | \n"; echo " | |__) | _ | |__| | ___ _ __ ___ ___ \n"; echo " | ___/ | | | __ | / _ \ | |_ \_ \ / _ \ \n"; echo " | | | | | | | | | (_) | | | | | | | | __/ \n"; echo " |_| |_| |_| |_| \___/ |_| |_| |_| \___| \n"; echo " \033[0m \n"; echo " \033[45m S M A R T H E A T I N G C O N T R O L \033[0m \n"; echo "\033[31m"; echo "***********************************************************\n"; echo "* Zone/Boiler Relay Testing Script for PiHome Version 0.1 *\n"; echo "* Build Date 27/02/2018 - Update on 27/02/218 *\n"; echo "* Have Fun - PiHome.eu *\n"; echo "***********************************************************\n"; echo " \033[0m \n"; require_once(__DIR__.'/st_inc/connection.php'); require_once(__DIR__.'/st_inc/functions.php'); //Set php script execution time in seconds ini_set('max_execution_time', 40); //GPIO Value for SainSmart Relay Board to turn on or off $relay_on = '1'; //GPIO value to write to turn on attached relay $relay_off = '0'; // GPIO value to write to turn off attached relay $query = "SELECT * FROM zone_view where status = 1 order by index_id asc;"; $results = mysql_query($query, $connection); while ($row = mysql_fetch_assoc($results)) { $zone_id=$row['id']; $zone_name=$row['name']; $zone_gpio_pin=$row['gpio_pin']; echo "\033[36m".date('Y-m-d H:i:s'). "\033[0m - GPIO \033[41m".$zone_gpio_pin."\033[0m set to \033[41mOn Status\033[0m for Zone: \033[32m".$zone_name."\033[0m\n"; exec("/usr/local/bin/gpio write ".$zone_gpio_pin." ".$relay_on); exec("/usr/local/bin/gpio mode ".$zone_gpio_pin." out"); sleep(5); echo "\033[36m".date('Y-m-d H:i:s'). "\033[0m - GPIO \033[41m".$zone_gpio_pin."\033[0m set to \033[44mOff Status\033[0m for Zone: \033[32m".$zone_name."\033[0m\n"; exec("/usr/local/bin/gpio write ".$zone_gpio_pin." ".$relay_off); exec("/usr/local/bin/gpio mode ".$zone_gpio_pin." out"); echo "----------------------------------------------------------------------- \n"; } $query = "SELECT * FROM boiler_view;"; $results = mysql_query($query, $connection); while ($row = mysql_fetch_assoc($results)) { $boiler_status=$row['status']; $boiler_name=$row['name']; $boiler_gpio_pin=$row['gpio_pin']; echo "\033[36m".date('Y-m-d H:i:s'). "\033[0m - GPIO \033[41m".$boiler_gpio_pin."\033[0m set to \033[41mOn Status\033[0m for Boiler: \033[32m".$boiler_name."\033[0m\n"; exec("/usr/local/bin/gpio write ".$boiler_gpio_pin." ".$relay_on); exec("/usr/local/bin/gpio mode ".$boiler_gpio_pin." out"); sleep(5); echo "\033[36m".date('Y-m-d H:i:s'). "\033[0m - GPIO \033[41m".$boiler_gpio_pin."\033[0m set to \033[44mOff Status\033[0m for Boiler: \033[32m".$boiler_name."\033[0m\n"; exec("/usr/local/bin/gpio write ".$boiler_gpio_pin." ".$relay_off); exec("/usr/local/bin/gpio mode ".$boiler_gpio_pin." out"); echo "----------------------------------------------------------------------- \n"; } ?> |
19 comments
this project is really very good, but as per my comments in other post you should make one sd card image with all required software preinstalled so people like myself can benefit from your work.
Ed
Is the test code here used in the full program? If so, what file is it in? I need to amend it to work with the relay boards i will be using (which work over i2c rather then direct gpio on/off).
@raj vora
if you are referring to relay_test.php then no this file isnt used anywhere its only for testing GPIO connected relay module. you should check cron/boiler.php file
I have installed and configured LAMP. I have a DS18B20 temperature sensor nd a single channel relay wired directly to the RPi. Per your recommendation, I have a boiler and one one configured. The zone is linked to the temp. sensor and relay. I have set all the (existing) schedule time slots to a temperature of zero. I have noticed that the boiler script sets the sensor to ON immediately despite no schedule, override, boost or night climate triggers. The boiler script triggers the relay to ON with these lines (200-206, or 205-6 specifically):
/***************************************************************************************
Zone Vole Wired to Raspberry Pi GPIO Section: Zone Vole Connected Raspberry Pi GPIO.
****************************************************************************************/
$relay_status = ($zone_status == ‘1’) ? $relay_off : $relay_on;
echo “\033[36m”.date(‘Y-m-d H:i:s’). “\033[0m – Zone: GIOP Relay Status: \033[41m”.$relay_status. “\033[0m (1=On, 0=Off) \n”;
exec(“/usr/local/bin/gpio write “.$zone_gpio_pin.” “.$relay_status );
exec(“/usr/local/bin/gpio mode “.$zone_gpio_pin.” out”);
Any suggestions to the cause and/or how I should address this undesired issue?
Thanks in advance,
Jason
Hi Jason,
Thank you for reporting error back, you need to change following lines
from
$relay_status = ($zone_status == '1') ? $relay_off : $relay_on;
echo "\033[36m".date('Y-m-d H:i:s'). "\033[0m - Zone: GIOP Relay Status: \033[41m".$relay_status. "\033[0m (1=On, 0=Off) \n";
to
$relay_status = ($zone_status == '1') ? $relay_on : $relay_off;
echo "\033[36m".date('Y-m-d H:i:s'). "\033[0m - Zone: GIOP Relay Status: \033[41m".$relay_status. "\033[0m (0=On, 1=Off) \n";
Thanks.
It would seem that the issue does not lie in the logic that you have implemented rather the issue appears to be with WiringPi when using bash. I have version 2.46 and what I observed was that the relay_test.php, like boiler.php, could close the relay (HIGH) but could not open the relay (LOW). I then wrote a PYTHON script with command line arguments (pin, 0/1) and to test I modified the relay_test.php so that
exec(“/usr/local/bin/gpio write “.$boiler_gpio_pin.” “.$relay_on);
exec(“/usr/local/bin/gpio mode “.$boiler_gpio_pin.” out”);
was replaced with:
exec(“python /var/www/relay_control.py -p “.$boiler_gpio_pin.” -“.$relay_on);
Depending on the location $boiler_gpio_pin was replaced with $zone_gpio_pin, and $relay_on with $relay_off. This was to maintain the logic that you implemented. This worked well, so I then modified boiler.php in exactly the same way.
Here is the relay_control.py
#!/usr/bin/env python
import RPi.GPIO as GPIO
import optparse
bcm = [-1,-1,2,-1,3,-1,4,14,-1,15,17,18,27,-1,22,23,-1,24,10,-1,9,25,11,8,-1,7,0,1,5,-1,6,12,13,-1,19,16,26,20,-1,21]
wpi = [-1,-1,8,-1,9,-1,7,15,-1,16,0,1,2,-1,3,4,-1,5,12,-1,13,6,14,10,-1,11,30,31,21,-1,22,26,23,-1,24,27,25,28,-1,29]
parser = optparse.OptionParser()
parser.add_option(“-p”, type=”int”, dest=”pin”)
parser.add_option(“-1”, “–HIGH”, action=”store_true”, dest=”verbose”)
parser.add_option(“-0”, “–LOW”, action=”store_false”, dest=”verbose”)
(options, args) = parser.parse_args()
# Determine the BCM from the specified WPi pin
channel = bcm[wpi.index(options.pin)]
# GPIO setup
GPIO.setmode(GPIO.BCM) # setmode = BCM or BOARD, how we address pins
GPIO.setwarnings(False) # Disable Warnings 🙂
GPIO.setup(channel, GPIO.OUT)
if __name__ == ‘__main__’:
try:
if options.verbose:
GPIO.output(channel, GPIO.HIGH) # Relay ON
else:
GPIO.output(channel, GPIO.LOW) # Realy OFF
GPIO.cleanup()
except KeyboardInterrupt:
GPIO.cleanup()
It looks like the PYTHON code was truncated for the bam and dpi lists!
Jason,
quick question, did you download PiHome IMG file and burn it on sd card or LAMP img and then installed pihome on that?
Apologies, I downloaded the PiHome IMG file!
Hi,
I have been planning a project just like this for a while now and have everything designed and each component tested ready to deploy.
One question I can’t find an answer to is whether I should disconnect the existing programmer.
My design allows for a simple override of my system so as to return control to the programmer. I’ve done this so that when I’m not at home other household members do not have to understand anything new if something goes wrong or if they just want to alter temperature, etc.
So my question….is it safe to apply mains voltage to the zone valve (and hence to the ‘CH on’ terminal of the programmer) via my relay at a time when the programmer is not demanding heat? Or would this damage the programmer?
@Cripsy,
yes you could do that, you can run as many parallel heating control as you like just have to draw all the wiring diagram, so if you feeding positive (Live) from exiting controller to your zone valve then you can feed positive (Live) from any other as well end of the day its only opening and closing valve and turning on/off boiler. best to draw on paper first. hop this helps
Thanks, that’s helpful, and thanks for the speedy reply.
So, I guess your answer tells me that it will work.
The big question though, is will it damage my existing programmer by feeding positive (Live) to the ‘wrong’ side of its heating demand output (its a Honeywell ST9400C digital 7-day programmer, so pin 4 here), which is what I’d be doing by feeding positive (Live) to the zone valve.
I have drawn it out, just need to find a way to put that online then I can link to it from here.
Thanks again
you can take live from same location as you are feeding ST9400C and then run that through your secondary controller and then out of your controller give connection to 3, 4 for each zone, this is my understanding is but i would highly recommend to see professional opinion as working with 220v can be dangerous.
Is there an easy way to swap the state of a wired GPIO using a relay? Everything is tested and working fine, however the default program seems that when calling for heat GPIO v=0 and I’d like it to be the opposite, so if the pi fails I don’t have a closed circuit calling for heat on thermostat. Is there a global setting?
Damon,
yes its easy, you can modify this in
/cron/boiler.php
file and modify as you want, in your case you need to set relay_on to 1 and relay_off 0//GPIO Value for SainSmart Relay Board to turn on or off
$relay_on = '0'; //GPIO value to write to turn on attached relay
$relay_off = '1'; // GPIO value to write to turn off attached relay