# This is a very custom script, but shows logic that others can reuse to do hvac # control in misterhouse as well as controlling booster fans based on HAI RC-80 # fan status. our $hvac_damper; my $OUTCOOL_TEMPDIFF_START = 12; my $OUTCOOL_TEMPDIFF_STOP = 10; my ($house_output, $mbr_output); my ($set_fan_mbr, $set_fan_fmr); my $status_message; my $log_mesg; my $fan_mesg; # my $var = foo is not safe, it only gets run once outside of the loop $status_message = "status changed to"; $log_mesg = ''; $fan_mesg = ''; undef $set_fan_mbr; undef $set_fan_fmr; # trigger an update of the stat output every 10 seconds at a 5sec offset to make the serial port happy. $house_output = $house_stat->get_stat_output if ($New_Second and $Second =~ /0$/); $mbr_output = $mbr_stat->get_stat_output if ($New_Second and $Second =~ /5$/); if ($New_Second and ($Second == 0 or $Second == 30)) { $hvac_damper = `sudo /var/local/scr/hvac_damper status`; chomp($hvac_damper); #print_log("MYLOG7: FMR Booster Fan: ".$fan_fmr->state().", MBR Booster Fan: ".$fan_mbr->state().", Damper status: $hvac_damper"); if ($hvac_damper eq "outside" and $fan_fmr->state eq "off" and $fan_mbr->state eq "off") { print_log("MYLOG7: HVAC FIX: Damper is set to outside but no fans are running, change back to hvac"); set_damper("hvac"); } } # this is how to convert the combined value in cacti # to query bit #2, this is the formula: # CURRENT_DATA_SOURCE,2,/,FLOOR,2,%,1,EQ,INF,UNKN,IF # bit to change is here ^ # this shows how it works: # 6 = 4 + 2 / 2 = 2 + 1 % 2 = 1 # 9 = 8 + 1 / 2 = 4 % 2 = 0 # 10 = 8 + 2 / 2 = 4 + 1 % 2 = 1 # 11 = 8 + 2 + 1 / 2 = 4 + 1 % 2 = 1 # 12 = 8 + 4 / 2 = 4 + 2 % 2 = 0 if ($New_Second and $Second == 40) { my $house_stat_state_h = $house_stat->get_stat_output =~ /heat/ ? 1 : 0; my $house_stat_state_c = $house_stat->get_stat_output =~ /cool/ ? 1 : 0; my $mbr_stat_state_h = $mbr_stat->get_stat_output =~ /heat/ ? 1 : 0; my $mbr_stat_state_c = $mbr_stat->get_stat_output =~ /cool/ ? 1 : 0; my $fmr_fan_state = $fan_fmr->state eq "on" ? 1 : 0; my $mbr_fan_state = $fan_mbr->state eq "on" ? 1 : 0; my $dampers = $hvac_damper eq "outside" ? 1 : 0; my $compfan = $compcloset_fan->state eq "on" ? 1 : 0; my $outputs = $house_stat_state_h + $house_stat_state_c*2 + $mbr_stat_state_h*4 + $mbr_stat_state_c*8 + $fmr_fan_state*16 + $mbr_fan_state*32 + $dampers*64 + $compfan*128; $_ = "Full HVAC Status: $outputs. House Stat Heat:$house_stat_state_h, House Stat Cool:$house_stat_state_c, MBR Stat Heat:$mbr_stat_state_h, MBR Stat Cool:$mbr_stat_state_c, FMR Boost Fan State: $fmr_fan_state, MBR Boost Fan State: $mbr_fan_state, Dampers to Outside Air: $dampers, Computer Closet Fan: $compfan, Cool Outside Flag: $Save{cool_outside}"; Omnistat::omnistat_log($_); print_log($_); } ## reset to something sane #if ($Startup) #{ # system("sudo /var/local/scr/hvac_damper hvac"); # $hvac_damper = "hvac"; #} if ($house_stat->state_now eq "current_output_change" or new_minute 5) { my ($cool_sp, $heat_sp, $mode, $fan, $hold, $temp); ($cool_sp, $heat_sp, $mode, $fan, $hold, $temp) = $house_stat->read_group1(); # get fresh data, just in case. $house_output = $house_stat->get_stat_output; $mbr_output = $mbr_stat->get_stat_output; $status_message = "FIXED BY TIMED TRIGGER to state" if ($house_stat->state_now ne "current_output_change"); $log_mesg = "MYLOG7: House Stat Fan turned on ($status_message $house_output): "; if ($house_output =~ /fan/) { if ($Save{cool_outside}) { print_log("MYLOG7: House Stat Fan turned on ($status_message $house_output) while outside cooling was on: Stop outside cooling."); $Save{cool_outside} = 0; } if ($hvac_damper ne "hvac") { print_log("MYLOG7: House Stat Fan turned on ($status_message $house_output): setting damper to hvac"); set_damper("hvac"); } $set_fan_fmr = "on"; # this is redundant, but can't hurt to reset. $set_fan_mbr = "off" if ($mbr_output !~ /fan/); } elsif ($hvac_damper eq "hvac") { $log_mesg = "MYLOG7: House Stat Fan turned off ($status_message $house_output): "; $set_fan_fmr = "off"; } } if ($mbr_stat->state_now eq "current_output_change" or new_minute 5) { my ($cool_sp, $heat_sp, $mode, $fan, $hold, $temp); ($cool_sp, $heat_sp, $mode, $fan, $hold, $temp) = $mbr_stat->read_group1(); # get fresh data, just in case. $house_output = $house_stat->get_stat_output; $mbr_output = $mbr_stat->get_stat_output; $status_message = "HVAC FIX to state" if ($mbr_stat->state_now ne "current_output_change"); $log_mesg = "MYLOG7: MBR Stat Fan turned on ($status_message $house_output): "; # bedroom has its own subzone that sends air anyway. Only turn on its booster fan if the # main house isn't being heated/cooled too. if ($mbr_output =~ /fan/) { if ($Save{cool_outside}) { print_log("MYLOG7: MBR Stat Fan turned on ($status_message $mbr_output) while outside cooling was on: Stop outside cooling."); $Save{cool_outside} = 0; } if ($hvac_damper ne "hvac") { print_log("MYLOG7: MBR Stat Fan turned on ($status_message $mbr_output): setting damper to hvac"); set_damper("hvac"); } if ($house_output !~ /fan/) { $log_mesg = "MYLOG7: MBR Stat Fan turned on with House Stat off ($status_message $mbr_output): "; $set_fan_mbr = "on"; # this is redundant, but can't hurt to reset. $set_fan_fmr = "off"; } else { $log_mesg = "MYLOG7: MBR Stat Fan turned on with House Stat on too ($status_message $mbr_output): "; $set_fan_mbr = "on"; } } elsif ($hvac_damper eq "hvac") { $log_mesg = "MYLOG7: MBR Stat Fan turned off ($status_message $mbr_output): "; $set_fan_mbr = "off"; } } if ($set_fan_fmr and $fan_fmr->state() ne $set_fan_fmr) { $fan_mesg .= "turned FMR Booster fan $set_fan_fmr (was ".$fan_fmr->state()."), "; $fan_fmr->set($set_fan_fmr); } if ($set_fan_mbr and $fan_mbr->state() ne $set_fan_mbr) { $fan_mesg .= "turned MBR Booster fan $set_fan_mbr (was ".$fan_mbr->state()."), "; $fan_mbr->set($set_fan_mbr); } print_log("$log_mesg$fan_mesg") if ($fan_mesg); # if both stats are off, see if one fan was turned on, and see if we should open/close the outside air if ($house_output eq "off" and $mbr_output eq "off") { if ($fan_fmr->state_now()) { if ($fan_fmr->state eq "on" and $hvac_damper ne "outside") { print_log("MYLOG7: FMR Fan turned on with HVAC off. Opening outside air."); set_damper("outside"); } elsif ($fan_mbr eq "off" and $hvac_damper ne "hvac") { print_log("MYLOG7: FMR Fan turned off with HVAC off and MBR Fan off too. Closing outside air."); set_damper("hvac"); } } elsif ($fan_mbr->state_now()) { if ($fan_mbr->state eq "on" and $hvac_damper ne "outside") { print_log("MYLOG7: MBR Fan turned on with HVAC off. Opening outside air."); set_damper("outside"); } elsif ($fan_fmr eq "off" and $hvac_damper ne "hvac") { print_log("MYLOG7: MBR Fan turned off with HVAC off and FMR Fan off too. Closing outside air."); set_damper("hvac"); } } } # outside temps is set in outside_temp.pl if ($New_Second and $Second == 1 and $Weather{TempIndoor} =~ /\d+/ and $Weather{TempOutdoor} =~ /\d+/) { my $mintemp = 60; my $tempdiff_start = $OUTCOOL_TEMPDIFF_START; my $tempdiff_stop = $OUTCOOL_TEMPDIFF_STOP; if ($Weather{TempIndoor} < $mintemp) { print_log("MYLOG7: Not cooling with outside air because indoors: ".$Weather{TempIndoor}." >> outdoors: ".$Weather{TempOutdoor}); } elsif (($Weather{TempIndoor} - $Weather{TempOutdoor} >= $tempdiff_start) and not $Save{cool_outside}) { print_log("MYLOG7: Cooling with outside air because indoors: ".$Weather{TempIndoor}." >> outdoors: ".$Weather{TempOutdoor}); $Save{cool_outside} = 1; set_damper("outside"); $fan_fmr->set(ON); #$fan_mbr->set(ON); } elsif ($Save{cool_outside} and ($Weather{TempIndoor} - $Weather{TempOutdoor} < $tempdiff_stop or $Weather{TempIndoor} < $mintemp)) { print_log("MYLOG7: Stopping Cooling with outside air because indoors: ".$Weather{TempIndoor}." close to outdoors: ".$Weather{TempOutdoor}); set_damper("hvac"); $Save{cool_outside} = 0; $fan_fmr->set(OFF); $fan_mbr->set(OFF); } elsif ($Minute % 10 == 0) { print_log("MYLOG7: No outside cooling to do, indoors is : ".$Weather{TempIndoor}." and outdoors is: ".$Weather{TempOutdoor}); } } sub set_damper { my ($state) = (@_); die "Can't only change dampers to hvac or outside (got $state)" if ($state ne "hvac" and $state ne "outside"); system("sudo /var/local/scr/hvac_damper $state"); $hvac_damper = $state; } #TODO: add single status line with bits # vim:sts=4:sw=4