EcoRenovator  

Go Back   EcoRenovator > Improvements > Geothermal & Heat Pumps
Advanced Search
 


Blog 60+ Home Energy Saving Tips Recent Posts


Reply
 
Thread Tools Display Modes
Old 09-11-14, 01:10 PM   #251
buffalobillpatrick
Master EcoRenovator
 
Join Date: Mar 2014
Location: Florissant, Colorado
Posts: 599
Thanks: 814
Thanked 59 Times in 55 Posts
Default

A somewhat easier method where you choose your heat loss rate:

Code:
// Choose your House Heat loss Rate
#define insulation_level_1.00    1.00      //VERY Poor insulation
#define insulation_level_0.95    0.95      //A bit better insulation
#define insulation_level_0.90    0.90      //A bit better insulation
#define insulation_level_0.85    0.85      //A bit better insulation
#define insulation_level_0.80    0.80      //A bit better insulation
#define insulation_level_0.75    0.75      //A bit better insulation
#define insulation_level_0.70    0.70      //A bit better insulation
#define insulation_level_0.65    0.65      //A bit better insulation
#define insulation_level_0.60    0.60      //A bit better insulation
#define insulation_level_0.55    0.55      //A bit better insulation
#define insulation_level_0.50    0.50      //A bit better insulation
#define insulation_level_0.45    0.45      //A bit better insulation
#define insulation_level_0.40    0.40      //A bit better insulation
#define insulation_level_0.35    0.35      //A bit better insulation
#define insulation_level_0.30    0.30      //A bit better insulation
#define insulation_level_0.25    0.25      //A bit better insulation
#define insulation_level_0.20    0.20      //A bit better insulation
#define insulation_level_0.15    0.15      //A bit better insulation
#define insulation_level_0.10    0.10      //Excellent insulation


//OutDoor Reset parameters
#define OUTDOOR_hi_control_temp  62.0  //OD Temp. that House don't require heat
#define BUFFER_tank_lo_limit     85.0  //Minimum BT temp, find through testing

#define BUFFER_tank_delta         5.0  // find through testing

float ODR_ratio;

int OUTDOOR_temp;  
int BUFFER_tank_temp;
int BUFFER_tank_target_temp;  


void setup() {
  
 // Choose your House Heat loss Rate
  ODR_ratio = define insulation_level_0.45;
}



void loop() {
  // OUTDOOR_temp = (readSensor_F (OUTDOOR_sensor));

  // Calculate Buffer Tank Target Temp based on ODR parameters
  BUFFER_tank_target_temp = 
  ( BUFFER_tank_lo_limit +
  (( OUTDOOR_hi_control_temp - OUTDOOR_temp ) * ODR_ratio ));
  
 //  BUFFER_tank_temp = (readSensor_F (BUFFER_tank_sensor));
  
  //Test if BT needs to start heating
  if ( BUFFER_tank_temp < ( BUFFER_tank_target_temp - BUFFER_tank_delta )) 
  { 
    
  do 
  {
   // run HP 
   //BUFFER_tank_temp = (readSensor_F (BUFFER_tank_sensor));
  } while ( BUFFER_tank_temp < BUFFER_tank_target_temp ); 

  }
}


Last edited by buffalobillpatrick; 10-25-14 at 11:08 AM..
buffalobillpatrick is offline   Reply With Quote
The Following User Says Thank You to buffalobillpatrick For This Useful Post:
AC_Hacker (09-11-14)
Old 09-11-14, 02:18 PM   #252
AC_Hacker
Supreme EcoRenovator
 
AC_Hacker's Avatar
 
Join Date: Mar 2009
Location: Portland, OR
Posts: 4,004
Thanks: 303
Thanked 724 Times in 534 Posts
Default

Thanks BBP,

Good clear explanation & code sample.

-AC
__________________
I'm not an HVAC technician. In fact, I'm barely even a hacker...
AC_Hacker is offline   Reply With Quote
The Following User Says Thank You to AC_Hacker For This Useful Post:
buffalobillpatrick (09-11-14)
Old 09-12-14, 08:20 PM   #253
buffalobillpatrick
Master EcoRenovator
 
Join Date: Mar 2014
Location: Florissant, Colorado
Posts: 599
Thanks: 814
Thanked 59 Times in 55 Posts
Default

In my code above the

// run HP comment in the do while loop is where your start & run heat pump code would be inserted
buffalobillpatrick is offline   Reply With Quote
Old 10-11-14, 10:43 AM   #254
jeff5may
Supreme EcoRenovator
 
Join Date: Jan 2010
Location: elizabethtown, ky, USA
Posts: 2,431
Thanks: 431
Thanked 619 Times in 517 Posts
Send a message via Yahoo to jeff5may
Default cheap limit switches

Quote:
Originally Posted by takyka View Post
If you decided to have a control more sophisticated than few timer relays, you should consider some safety functions!

To a W2WHP without antifreeze in primary loop I would add flow sensor to evaporator water. To continously monitor water outlet temperature is not enough. If water stops to flow, temperature drops so fast, and continues fallaing after you stop the compressor, it turns your HX into solid block of ice.

Another and more dangerous thing you have to protect against is the excessive pressure on condenser side. It can happen if heating system can't take away heat for any reason. The compressor can bloat the HX and pipes to failure. A friend of mine had such situation, luckily he could shut it off before explosion, but one HX bloated and connections started to leak.

Third thing to consider is to detect short electric outages. Controller can hold back breath for couple of second and if mains suply is back, it still driving the compressor. However compressor is stopped, and can't start because the high pressure difference. Result, you can imagine.

Both are critical I think.

For flow sensor I use like this:
Durable 1 60L MIN G1" Pipeline Water Flow Sensor Switch Meter Flowmeter | eBay

To detect too high condenser pressure, you should use a pressostat or a pressure sensor connected to Arduino. For condenser pressure measurement I use an industrial pressure transducer. Unfortunately I don't know cheap source for it.

To detect AC outage you could use an opto coupler with antiparalel leds.

T.
A cheap, common source for the high and low pressure cutout switches exists. This common source is your local junkyard. If you go to a u-pull yard, you can literally unscrew the sensors from where they live in the vehicle and chop off the pigtail and connector at the harness. They are made for easy replacement, so in 99 out of 100 vehicles, they are all pretty much the same: 1/4 inch flare fittings are common, low pressure cutout around 30 psig, high pressure cutout around 300 psig. Some switch assemblies do both high and low pressure sensing in one device!

Common female flare sensors hook straight up to access valves and most have a built-in Schraeder valve depressor:

binary (go/no-go)


trinary (low/operate/high)


Other common male flare sensors may or may not have built-in Schraeder valve:


EDIT: For clarification, these sensors are for measuring refrigerant pressures, not water pressures. BBP has identified the appropriate fuel pressure sensors that can be bought in the lower pressure ranges the water loops operate within.

Last edited by jeff5may; 12-28-14 at 09:36 PM..
jeff5may is offline   Reply With Quote
The Following User Says Thank You to jeff5may For This Useful Post:
buffalobillpatrick (10-22-14)
Old 10-22-14, 07:39 PM   #255
buffalobillpatrick
Master EcoRenovator
 
Join Date: Mar 2014
Location: Florissant, Colorado
Posts: 599
Thanks: 814
Thanked 59 Times in 55 Posts
Default

Here is my Latest HP Slave code 2_0

Implemented Pressure sensors to verify Pump flows
Implemented economic Balance Point COP: Electricity NG vs 85% Boiler
Implemented Estimated running COP based on: ESWT & ELWT
see:
http://www.climatemaster.com/downloads/RP881.pdf
p19 graph for model TMW036 W/W

It runs on my Arduino Uno

Code:
/********************************************************
 *
 * ARDUINO SLAVE HP Controller.
 *
 * The MASTER Heating System controller powers this ARDUINO
 * ON or OFF as Heat Pump is needed.
 *
 * This code controls 3 Relays and reads/displays 9x 10K NTC Thermisters
 * and 1x MQ-2 GAS sensor
 *
 * IN SETUP:
 *
 * STEP #1
 * Tells HEAT_SYS_MASTER Arduino that SLAVE "IS NOT HUNG"  via ALIVE_RLY_R1
 *
 * STEP #2
 * The NG vs Electric cost Balance Point is calculated using input pots
 *
 * STEP #3
 * The Source & Load pump OFF output pressure is read.
 *
 * STEP #4
 * The Source & Load pumps are started
 *
 * STEP #5
 * The Source & Load pump ON output pressure is read again.
 * Good flow is verified by correct pressure increase
 *
 * STEP #6
 * HP COP is estimated see http://www.climatemaster.com/downloads/RP881.pdf
 * p19 graph for model TMW036 W/W
 *
 * STEP #7
 * If the Estimated COP is less than the Cost Balance Point
 * then the pumps are turned off & code hangs 
 * until the MASTER powers OFF this SLAVE Arduino
 * This indicate to Master Controller that the NG Boiler should be used.
 *
 * STEP #8
 * The Compressor is started
 *
 * End Setup
 *
 *
 *
 * In the Main Loop, 9x temperature sensors
 * are read & displayed, continuously
 *
 * Each time through the main loop 
 * the Source & Load pump ON output pressure is read.
 * Good flow is verified by correct pressure
 *  
 * Each time through the main loop
 * HP COP is estimated 
 * If the Estimated COP is less than the Cost Balance Point
 * then the pumps are turned off & code hangs 
 * until the MASTER powers OFF this SLAVE Arduino
 * This indicate to Master Controller that the NG Boiler should be used.
 *
 * Main Loop takes about 70 Sec
 *
 * In the custom_delay function, 
 * The Source OUT water tempereature and the MQ-2 GAS Sensor are checked. 
 * If either are out of range, then code turns off all relays,   
 * & hangs until the MASTER powers OFF this SLAVE Arduino
 *
 *
 *
 * NG Mcf = 1,000 ft3
 * Therm = 100,000 BTU = 29.3Kwh
 * $Therms = $Mcf / 10.25
 *
 * Over the past several winters my average delivered NG $8.00/Mcf = $.78/Therm
 * & delivered Electricity rate about $.16 / Kwh
 *
 * Easy to use online Heat Cost calculator:
 * Electric Heat vs. Gas/Oil Heat Cost Calculator/Comparator
 *
 * My Cost of heat (per 100,000 BTU)
 * $.16 / Kwh Electricity = $4.69
 * $.78 / Therm with 85% Efficiency NG boiler = $0.92
 *
 * Convert to Balance point: 4.69 / .92 = 5.0978 COP
 *
 * Change History:
 * 07/30/14 Changed POT Heater over to hardware control & 
 *          implemented new sample averaging method.
 * 08/02/14 Added Custom_delay & MQ-2 GAS sensor
 * 10/22/14 Complete rewrite
 *
 ********************************************************/

#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>


#define I2C_ADDR    0x3F // <<----- Add your address here.  Find it from I2C Scanner

#define BACKLIGHT_PIN     3  //define LCD digital pins
#define En_pin  2
#define Rw_pin  1             //can't use D0 Tx & D1 Rx
#define Rs_pin  0
#define D4_pin  4
#define D5_pin  5              //can use 2 -> 12 below in code
#define D6_pin  6
#define D7_pin  7

LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);

#define SDA                           A4  //RESERVE I2C for LCD           
#define SCL                           A5  

#define mux_analog_in                 A0  //multiplexer to Arduino analog in pin       

#define MQ2_GAS_sensor                A1     

#define SRC_pump_pressure_sensor           A2
#define LOAD_pump_pressure_sensor          A3


                             // D0 = RX, D1 = TX, reserved
                                     // relays Digital output pins
#define  ALIVE_RLY_R1             4  //  D4                        Songle 10A
                                     //Split R1 & R2 into seperate groups
                                     //as songle relay coil = 90ma
                                     //each group can source 150 mA. max
                                     //group 1 ends with D4
                                     //group 2 starts with D5
#define  HP_RLY_R2                5  //  D5  Pumps In & Out OPTO 480D15-12  15A
#define  HP_RLY_R3                6  //  D6  Compressor     CRYDOM H12D4850 50A

                                 //define Digital output pins for MUX D7 -> D11
                                 // multiplexer address select lines (A/B/C/D)
const byte mux_address_A       = 7;
const byte mux_address_B       = 8; 
const byte mux_address_C       = 9; 
const byte mux_address_D       = 10; 
const byte mux_enable          = 13;  // multiplexer enable


#define ALARM                   11  // D11 PWM OUTPUT to Audible Alarm

                        


              //analog signals into MUX, these are NOT analog pins on Arduino
#define Kwh_cost_pot                 0
#define Mcf_cost_pot                 1


#define SOLAR_tank_sensor            7  

#define COMP_DISCHARGE_sensor        8 
#define COND_OUT_sensor              9 

#define EVAP_IN_sensor              10                        
#define EVAP_OUT_sensor             11                        

#define SOURCE_IN_sensor            12              
#define SOURCE_OUT_sensor           13  

#define LOAD_IN_sensor              14                
#define LOAD_OUT_sensor             15




#define Boiler_Eff      .85

#define SRC_pump          2
#define LOAD_pump         3
#define MIN_PSI_DELTA     1



int HP_Source_IN_temp;                  
int HP_Source_OUT_temp;               
int HP_Load_IN_temp;                        
int HP_Load_OUT_temp;        

int SRC_pump_on_pressure;
int SRC_pump_off_pressure;
int LOAD_pump_on_pressure;
int LOAD_pump_off_pressure;

int SRC_Delta_PSI;
int LOAD_Delta_PSI;
int ESWT;
int ELWT;


unsigned long T1;
unsigned long T2;
unsigned long TT;


int i;
int Sensor_Data;

float BP;
float Estimate_COP;
float Kwh_cost;
float Mcf_cost;

Last edited by buffalobillpatrick; 10-22-14 at 07:47 PM..
buffalobillpatrick is offline   Reply With Quote
Old 10-22-14, 07:40 PM   #256
buffalobillpatrick
Master EcoRenovator
 
Join Date: Mar 2014
Location: Florissant, Colorado
Posts: 599
Thanks: 814
Thanked 59 Times in 55 Posts
Default

Part#2 Setup
Code:
void setup(void)       //Start Setup
  {
        
  pinMode (mux_analog_in, INPUT);  //MUX DATA INPUT
  pinMode (mux_address_A, OUTPUT); // multiplexer address select lines (A/B/C/D)
  pinMode (mux_address_B, OUTPUT); 
  pinMode (mux_address_C, OUTPUT); 
  pinMode (mux_address_D, OUTPUT); 
  pinMode (mux_enable,    OUTPUT); // multiplexer enable

 
  pinMode( ALARM,                       OUTPUT); //digital output to relays

  pinMode( ALIVE_RLY_R1,                OUTPUT); //digital output to relays
  pinMode( HP_RLY_R2,                   OUTPUT); //digital output to relays
  pinMode( HP_RLY_R3,                   OUTPUT); //digital output to relays

  digitalWrite ( ALIVE_RLY_R1,          HIGH); //OFF
  digitalWrite ( HP_RLY_R2,             HIGH); //OFF
  digitalWrite ( HP_RLY_R3,             HIGH); //OFF
 
 
 // Serial.begin(9600); // start serial communication

 // delay(10000);      //time to enable monitor window
 
  
 // Serial.println(F("........Hello world!......."));
 // delay(100); 
  
  lcd.begin (16,2); //  <<----- My LCD is 16x2
  lcd.clear();
 
  //Switch on the backlight
  lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
  lcd.setBacklight(HIGH);
    

    // (IRQ1 is on Digital Pin 3) Pin 3 going high (+) sets Interrupt 1
    // This is Master signal to STOP HP Compressor, by denergizing R3
    // with a short power cycle to Solar pump, which picks a relay
    // N/O point connects Arduino +5v to Digital Pin 3
    // This allows the water pumps to continue after Compressor is off	     
    // After a delay the master will power off this Slave Arduino	
    
   attachInterrupt(1, Stop_Compressor_ISR, RISING);// Attach Interrupt 
    // never detach

  digitalWrite (ALIVE_RLY_R1,   LOW);   //ON 

  lcd.clear();
  lcd.home (); // go home
  lcd.print(F("ALIVE SIGNAL TO"));
  lcd.setCursor(0,1);
  lcd.print(F("MASTER, R1 ON"));
  delay(5000);
  // Warer pumps not started yet, so can't use custom delay 

 
  lcd.clear();
  lcd.home (); // go home
  lcd.print(F("HP_SLAVE_2_0"));
  delay(5000);
  // Water pumps not started yet, so can't use custom delay 


  beep(50);
  beep(50);
  beep(50);
  delay(1000);

    //read the Kwh & Mcf cost input pots. 
    //Pots don't work well close to end thus the need for center of range values
  Kwh_cost =    (Read_10K_NTC (Kwh_cost_pot));
  Kwh_cost = 160;  //debug
  
  Mcf_cost =    (Read_10K_NTC (Mcf_cost_pot));
  Mcf_cost =  800;  //debug
  
  Kwh_cost /= 1000.0;
  Mcf_cost /= 100.0;
  
  lcd.clear();  
  lcd.home (); // go home
  lcd.print(F("Kwh Cost = "));
  lcd.print(Kwh_cost);
  lcd.setCursor(0,1);  
  lcd.print(F("Mcf Cost = "));
  lcd.print(Mcf_cost);
  delay(5000);
  

     //Balance Point Formula:
  BP =  ((Kwh_cost) / ((Mcf_cost / 10.25) * (1.0 / Boiler_Eff)) * 29.3); 
          
//BP = ( .16  / (( 8.00  / 10.25) *  (1 / .85)) * 29.3);

  lcd.clear();  
  lcd.home (); // go home
  lcd.print(F("BALANCECOP="));
  lcd.print(BP);
  delay(5000);
 


  SRC_pump_off_pressure = read_pump_PSI (SRC_pump);
  SRC_pump_off_pressure = 5;    //debug
  
  LOAD_pump_off_pressure = read_pump_PSI (LOAD_pump);
  LOAD_pump_off_pressure = 6;    //debug

  lcd.clear();  
  lcd.home (); // go home
  lcd.print(F("SRC_OFF_PSI= "));
  lcd.print(SRC_pump_off_pressure);
  lcd.setCursor(0,1);  
  lcd.print(F("LOAD_OFF_PSI= "));
  lcd.print(LOAD_pump_off_pressure);
  delay(5000);
 
 
  digitalWrite (HP_RLY_R2,          LOW);  //Power Pumps  
  lcd.clear();
  lcd.home (); // go home
  lcd.print(F("HP H2O PUMPS ON"));
  delay(10000);


  SRC_pump_on_pressure = read_pump_PSI (SRC_pump);
  SRC_pump_on_pressure = 10;    //debug
  
  LOAD_pump_on_pressure = read_pump_PSI (LOAD_pump);
  LOAD_pump_on_pressure = 11;    //debug

  lcd.clear();  
  lcd.home (); // go home
  lcd.print(F("SRC_ON_PSI= "));
  lcd.print(SRC_pump_on_pressure);
  lcd.setCursor(0,1);  
  lcd.print(F("LOAD_ON_PSI= "));
  lcd.print(LOAD_pump_on_pressure);
  delay(5000);
 
  SRC_Delta_PSI    = SRC_pump_on_pressure  -  SRC_pump_off_pressure;
  LOAD_Delta_PSI   = LOAD_pump_on_pressure - LOAD_pump_off_pressure;
  
  if ((SRC_Delta_PSI < MIN_PSI_DELTA) or (LOAD_Delta_PSI < MIN_PSI_DELTA))
  { STOP(); }
  
 //  delay(120000);
 
  
  Estimate_COP = estimate_COP();  //Estimate COP See Function

  lcd.clear();  
  lcd.home (); // go home
  lcd.print(F("ESTIMATECOP="));
  lcd.print(Estimate_COP);
  delay(5000);

  if(Estimate_COP < BP) { STOP(); }   //Quit
  
  
  
  digitalWrite (HP_RLY_R3,          LOW);  //Power Compressor 
  
  lcd.clear();
  lcd.home (); // go home
  lcd.print(F("HP COMPRESSOR ON"));  
  lcd.setCursor(0,1);
  lcd.print(F("END SETUP"));   
  custom_delay();     //Delay 5 sec. & Checks Water SRC OUT 
                      // FOR BEING TOO COLD, RESETS RLYS & HANGS FOREVER IF SO

  }    //end setup

Last edited by buffalobillpatrick; 10-23-14 at 11:34 AM..
buffalobillpatrick is offline   Reply With Quote
Old 10-22-14, 07:42 PM   #257
buffalobillpatrick
Master EcoRenovator
 
Join Date: Mar 2014
Location: Florissant, Colorado
Posts: 599
Thanks: 814
Thanked 59 Times in 55 Posts
Default

Part #3 Main Loop
Code:
  void loop ()
{ 
  
//  T1 = millis();
 
  Sensor_Data         =  (Read_10K_NTC (SOLAR_tank_sensor));                  
  lcd.clear();
  lcd.home (); // go home
  lcd.print(F("SOLAR TANK= "));
  lcd.print(Sensor_Data);  
  custom_delay();     //Delay 5 sec. & Checks Water SRC OUT 
         
  
  Sensor_Data         =  (Read_10K_NTC (COMP_DISCHARGE_sensor));                  
  lcd.clear();
  lcd.home (); // go home
  lcd.print(F("COMP_DISCHAR="));
  lcd.print(Sensor_Data);
  custom_delay();     //Delay 5 sec. & Checks Water SRC OUT 
         

  Sensor_Data          =  (Read_10K_NTC (COND_OUT_sensor));                  
  lcd.clear();
  lcd.home (); // go home
  lcd.print(F("COND_OUT="));
  lcd.print(Sensor_Data);
  custom_delay();     //Delay 5 sec. & Checks Water SRC OUT 
  

  Sensor_Data          =  (Read_10K_NTC (EVAP_IN_sensor));
  lcd.clear();
  lcd.home (); // go home
  lcd.print(F("EVAP_IN="));
  lcd.print(Sensor_Data);
  custom_delay();     //Delay 5 sec. & Checks Water SRC OUT 
  

  Sensor_Data        =  (Read_10K_NTC (EVAP_OUT_sensor));
  lcd.clear();
  lcd.home (); // go home
  lcd.print(F("EVAP_OUT="));
  lcd.print(Sensor_Data);
  custom_delay();     //Delay 5 sec. & Checks Water SRC OUT 


  Sensor_Data       =  (Read_10K_NTC (SOURCE_IN_sensor));
  lcd.clear();
  lcd.home (); // go home
  lcd.print(F("SRC_IN="));
  lcd.print(Sensor_Data);
  custom_delay();     //Delay 5 sec. & Checks Water SRC OUT 
        
 
  Sensor_Data      =  (Read_10K_NTC (SOURCE_OUT_sensor));
  lcd.clear();
  lcd.home (); // go home
  lcd.print(F("SRC_OUT="));
  lcd.print(Sensor_Data);
  custom_delay();     //Delay 5 sec. & Checks Water SRC OUT 
        
  
  Sensor_Data       =  (Read_10K_NTC (LOAD_IN_sensor));
  lcd.clear();
  lcd.home (); // go home
  lcd.print(F("LOAD_IN="));
  lcd.print(Sensor_Data);
  custom_delay();     //Delay 5 sec. & Checks Water SRC OUT 
        
 
  Sensor_Data       =  (Read_10K_NTC (LOAD_OUT_sensor));
  lcd.clear();
  lcd.home (); // go home
  lcd.print(F("LOAD_OUT="));
  lcd.print(Sensor_Data);
  custom_delay();     //Delay 5 sec. & Checks Water SRC OUT 
 
 
   
  Estimate_COP = estimate_COP();  //Estimate COP see function

  lcd.clear();  
  lcd.home (); // go home
  lcd.print(F("ESTIMATECOP="));
  lcd.print(Estimate_COP);
  delay(5000);

  if(Estimate_COP < BP) { STOP(); }   //Quit if under Balance Point


  //Verify pump pressures
  SRC_pump_on_pressure = read_pump_PSI (SRC_pump);
  SRC_pump_on_pressure = 10;    //debug
  
  LOAD_pump_on_pressure = read_pump_PSI (LOAD_pump);
  LOAD_pump_on_pressure = 11;    //debug

  lcd.clear();  
  lcd.home (); // go home
  lcd.print(F("SRC_ON_PSI= "));
  lcd.print(SRC_pump_on_pressure);
  lcd.setCursor(0,1);  
  lcd.print(F("LOAD_ON_PSI= "));
  lcd.print(LOAD_pump_on_pressure);
  delay(5000);
 
  SRC_Delta_PSI    = SRC_pump_on_pressure  -  SRC_pump_off_pressure;
  LOAD_Delta_PSI   = LOAD_pump_on_pressure - LOAD_pump_off_pressure;
  
  if ((SRC_Delta_PSI < MIN_PSI_DELTA) or (LOAD_Delta_PSI < MIN_PSI_DELTA))
  { STOP(); }    //Quit if under pressure
  
         
/*
  T2 = millis();

  TT = T2 - T1;

  lcd.clear();
  lcd.home (); // go home
  lcd.print(TT);   //about 69 sec. per loop
  
  custom_delay();     //Delay 5 sec. & Checks Water SRC OUT 
                      // FOR BEING TOO COLD, RESETS RLYS & HANGS FOREVER IF SO          

*/

}  //end forever loop
buffalobillpatrick is offline   Reply With Quote
Old 10-22-14, 07:43 PM   #258
buffalobillpatrick
Master EcoRenovator
 
Join Date: Mar 2014
Location: Florissant, Colorado
Posts: 599
Thanks: 814
Thanked 59 Times in 55 Posts
Default

Part #4 functions
Code:
    // (IRQ1 is on Digital Pin 3) Pin 3 going high (+) sets Interrupt 1
    // This is Master signal to STOP HP Compressor, by denergizing R3
    // with a short power cycle to Solar pump, which picks a relay
    // N/O point connects Arduino +5v to Digital Pin 3
    // Digital Pin 3 has a 10K pulldown resistor to Gnd.
    // This allows the water pumps to continue after Compressor is off	     
    // After a delay the master will power off this Slave Arduino
    //	This would be a normal ending sequence for HP satisfying Load    
void Stop_Compressor_ISR()	     
{			
  digitalWrite (HP_RLY_R3,                  HIGH); //Compressor OFF
}


 
  // COP estimation
  // http://www.climatemaster.com/downloads/RP881.pdf
  // p19 graph for model TMW036 W/W

float estimate_COP (void) 
{  
  int   Dt; 
  int   ESWT;
  int   ELWT;
  float COP;
  float DELTA;
  
  
  ESWT       =  (Read_10K_NTC (SOURCE_IN_sensor));
  lcd.clear();
  lcd.home (); // go home
  lcd.print(F("ESWT="));
  lcd.print(ESWT);
  custom_delay();     //Delay 5 sec. & Checks Water SRC OUT 
  
  ELWT       =  (Read_10K_NTC (LOAD_IN_sensor));
  lcd.clear();
  lcd.home (); // go home
  lcd.print(F("ELWT="));
  lcd.print(ELWT);
  custom_delay();     //Delay 5 sec. & Checks Water SRC OUT 
          
  Dt = ELWT - ESWT;
 
  if (ELWT <= 80)
  {
  Dt  =  map(Dt, 20, 60, 65, 38);
  }
  else if (ELWT <= 85)
  {
  Dt  =  map(Dt, 25, 65, 61, 36);
  }  
  else if (ELWT <= 90)
  {
  Dt  =  map(Dt, 30, 70, 57, 33);
  }
  else if (ELWT <= 95)
  {
  Dt  =  map(Dt, 35, 75, 53, 30);
  }  
  else if (ELWT <= 100) 
  {
  Dt  =  map(Dt, 40, 80, 49, 28);
  }    
  else if (ELWT <= 105) 
  {
  Dt  =  map(Dt, 45, 85, 46, 26);
  }      
  else if (ELWT <= 110) 
  {
  Dt  =  map(Dt, 50, 90, 43, 25);
  }
  else if (ELWT <= 115) 
  {
  Dt  =  map(Dt, 55, 95, 40, 23);
  }   
  else if (ELWT <= 120) 
  {
  Dt  =  map(Dt, 60, 100, 37, 22);
  }    
  else if (ELWT <= 125) 
  {
  Dt  =  map(Dt, 65, 105, 34, 21);
  }   
  else {STOP();}
  
  COP = Dt / 10,0;

  return (COP);
  }





int read_pump_PSI (int which_pump)
{
  #define sample_cnt 23                    //takes 254 MS  
  int Sensor_Data;  
  int I;  
  float alpha =   0.9;     // factor to tune
  float average = 0.0;
  
  
  for (I=0; I< sample_cnt; I++) 
  {  
  average =  alpha * analogRead(which_pump) + (1-alpha) * average;
  delay(10);
  }
  
  Sensor_Data  =  average;      //convert float to int for map
 
 // pressure transducer .5v = 0PSI  & 4.5v = 30PSI 
  Sensor_Data  =  map(Sensor_Data, 102, 921, 0, 30);

  return (Sensor_Data);
}




void custom_delay (void) //Delay 5 sec. & Checks Water SRC OUT & GAS
{  
  #define GAS_LIMIT               100   //TBD To Be Determined with testing
  #define SOURCE_OUT_LOW_LIMIT    15    //with 30% PG
  #define sample_cnt 23                    //takes 254 MS  
  int I;  
  float alpha =   0.9;     // factor to tune
  float average = 0.0;
  
//  T1 = millis(); 
  
  delay(4513); 
  
  for (I=0; I< sample_cnt; I++) 
  {  
  average =  alpha * analogRead(MQ2_GAS_sensor) + (1-alpha) * average;
  delay(10);
  }
  
 //Test if GAS LIMIT EXCEEDED
  Sensor_Data  =  average;      //convert float to int
  
  Sensor_Data  =  map(Sensor_Data, 0, 1023, 0, 100);

/*
  lcd.clear();
  lcd.home (); // go home
  lcd.print(F("GAS SENSOR="));
  lcd.print(Sensor_Data);  
  delay(10000);
*/  
  
   if (Sensor_Data > GAS_LIMIT)     
  {  
  lcd.clear();
  lcd.home (); // go home
  lcd.print(F("GAS LIMIT MET"));
  lcd.setCursor(0,1);  
  lcd.print(F("TurnOff all Rlys"));  
  
  digitalWrite (HP_RLY_R3,                  HIGH); //Compressor OFF
  delay(120000);
  digitalWrite (HP_RLY_R2,                  HIGH); //Pumps OFF  
  digitalWrite (ALIVE_RLY_R1,               HIGH); //Alive OFF
  
  lcd.clear();
  lcd.home (); // go home
  lcd.print(F("HANG FOREVER 1"));

  do{ beep(200);} while (I == I);  //hang  
  }  //end if GAS LIMIT 


  //Test if Source out is too cold to run HP  
  if ((Read_10K_NTC (SOURCE_OUT_sensor) <= SOURCE_OUT_LOW_LIMIT))     
  { 
  lcd.clear();
  lcd.home (); // go home
  lcd.print(F("HP SRC OUT COLD"));
  lcd.setCursor(0,1);  
  lcd.print(F("RESET ALL RELAYS"));  
  delay(5000);
   
  digitalWrite (HP_RLY_R3,                  HIGH); //Compressor OFF
  delay(120000);
  digitalWrite (HP_RLY_R2,                  HIGH); //Pumps OFF  
  digitalWrite (ALIVE_RLY_R1,               HIGH); //Alive OFF

  do{I = I;} while (I == I);  //hang
  
  }  //end if SOURCE_OUT is too cold 

  
/*
  T2 = millis();

  TT = T2 - T1;
  
  lcd.clear();
  lcd.home (); // go home
  lcd.print(TT);    // 5 sec
  delay(10000); 
*/

  }  //end custom_delay function  




void beep(unsigned char delayms)
{
  analogWrite(ALARM, 255);     // Almost any value can be used except 0 
                           // experiment to get the best tone
  delay(delayms);          // wait for a delayms ms
  analogWrite(ALARM, 0);       // 0 turns it off
  delay(delayms);          // wait for a delayms ms   
} 




int Read_10K_NTC (const byte which_sensor)
  {   
  #define sample_cnt 23                    //takes 254 MS
  
  float alpha =   0.9;     // factor to tune
  float average = 0.0;
  
  int I;
 
  float steinhart;

// resistance at 25 degrees C
#define THERMISTORNOMINAL 10000

// temp. for nominal resistance (almost always 25 C)
#define TEMPERATURENOMINAL 25

// The beta coefficient of the thermistor (usually 3000-4000)
#define BCOEFFICIENT 3892

// the value of the series resistor
#define SERIESRESISTOR 10000



//  T1 = millis();



  digitalWrite (mux_enable, HIGH); //disable
  delay(10);

  // select correct MUX channel
  digitalWrite (mux_address_A, (which_sensor & 1) ? HIGH : LOW);
  digitalWrite (mux_address_B, (which_sensor & 2) ? HIGH : LOW);
  digitalWrite (mux_address_C, (which_sensor & 4) ? HIGH : LOW);
  digitalWrite (mux_address_D, (which_sensor & 8) ? HIGH : LOW);

  digitalWrite (mux_enable, LOW); //enable
  delay(10);


  
  for (I=0; I< sample_cnt; I++) 
  {  
  average =  alpha * analogRead(mux_analog_in) + (1-alpha) * average;
  delay(10);
  }
  
  // convert the value to resistance
  average = 1023 / average - 1;
  average = SERIESRESISTOR / average;
  steinhart = average / THERMISTORNOMINAL;     // (R/Ro)
  steinhart = log(steinhart);                  // ln(R/Ro)
  steinhart /= BCOEFFICIENT;                   // 1/B * ln(R/Ro)
  steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)
  steinhart = 1.0 / steinhart;                 // Invert
  steinhart -= 273.15;                         // convert to C
  
  return (round(steinhart * 1.8) + 32);       // round to whole number 
                                              // & convert to F            

/*
  T2 = millis();

  TT = T2 - T1;
  
  lcd.clear();
  lcd.home (); // go home
  lcd.print(TT);    // 5 sec
  delay(10000); 
*/           
  }  // end of Read_10K_NTC
  


  void STOP (void)
  {
  int I;
  
  lcd.clear();
  lcd.home (); // go home
  lcd.print(F("STOP"));
  lcd.setCursor(0,1);  
  lcd.print(F("RESET ALL RELAYS"));  
  delay(5000);

  digitalWrite (HP_RLY_R3,                  HIGH); //Compressor OFF
  delay(120000);
  digitalWrite (HP_RLY_R2,                  HIGH); //Pumps OFF  
  digitalWrite (ALIVE_RLY_R1,               HIGH); //Alive OFF

  lcd.clear();
  lcd.home (); // go home
  lcd.print(F("HANG FOREVER 2"));

  do{I = I;} while (I == I);  //hang
  
  }  //end STOP

Last edited by buffalobillpatrick; 10-23-14 at 01:59 PM..
buffalobillpatrick is offline   Reply With Quote
The Following User Says Thank You to buffalobillpatrick For This Useful Post:
AC_Hacker (10-23-14)
Old 10-23-14, 12:35 PM   #259
AC_Hacker
Supreme EcoRenovator
 
AC_Hacker's Avatar
 
Join Date: Mar 2009
Location: Portland, OR
Posts: 4,004
Thanks: 303
Thanked 724 Times in 534 Posts
Default

BBP,

Nice job.

I noticed that you did an edit after you first posted this code. It could be useful to put some kind of revision statement in the header to simplify and clarify communication, so that we are literally 'on the same page'.

(* NOTE: Never mind, I just saw your "Change History" section. *)

It's interesting that you are using pots for NG vs Electric cost. I suppose that for simplicity and cost of implementation for this early unit, it makes perfect sense. Maybe once you get the whole beast working, and you are whiling away your snug winter months, you might be able to develop a routine that could reach out through the Internet and automatically gather that information for your Balance Point calculation.


Code:
.
.
.
#define MQ2_GAS_sensor                A1     
#define SRC_pump_pressure_sensor           A2
#define LOAD_pump_pressure_sensor          A3
.
.
.
The integrated MQ-2 GAS Sensor is brilliant.

What pressure measuring devices have you settled on? I looked at the wrecking yard sensors (great idea) that jeff5may suggested, but I think that their range is way too high for flow verification.

Great job!

-AC
__________________
I'm not an HVAC technician. In fact, I'm barely even a hacker...
AC_Hacker is offline   Reply With Quote
The Following User Says Thank You to AC_Hacker For This Useful Post:
buffalobillpatrick (10-23-14)
Old 10-23-14, 01:54 PM   #260
buffalobillpatrick
Master EcoRenovator
 
Join Date: Mar 2014
Location: Florissant, Colorado
Posts: 599
Thanks: 814
Thanked 59 Times in 55 Posts
Default

Thanks A/C

30PSI Pressure Transducer or Sender for Oil Fuel Diesel Gas Water Air | eBay

Having trouble with ISR,
When I force an Interrupt 1 by jumpering D3 to +5v
Arduino hangs ?

I tried detaching interrupt right away but still hangs?

Possibly lcd.print don't work in ISR?

Code:
    // (IRQ1 is on Digital Pin 3) Pin 3 going high (+) sets Interrupt 1
    // This is Master signal to STOP HP Compressor, by denergizing R3
    // with a short power cycle to Solar pump, which picks a relay
    // N/O point connects Arduino +5v to Digital Pin 3
    // Digital Pin 3 has a 10K pulldown resistor to Gnd.
    // This allows the water pumps to continue after Compressor is off	     
    // After a delay the master will power off this Slave Arduino
    //	This would be a normal ending sequence for HP satisfying Load    	     
void Stop_Compressor_ISR()	     
{			
  int I;
  detachInterrupt(1);   
  
  digitalWrite (HP_RLY_R3,                  HIGH); //Compressor OFF
  lcd.print(F("COMPRESSOR OFF"));
  delay(30000);
  digitalWrite (HP_RLY_R2,                  HIGH); //Pumps OFF  
  digitalWrite (ALIVE_RLY_R1,               HIGH); //Alive OFF

  lcd.clear();
  lcd.home (); // go home
  lcd.print(F("HANG FOREVER"));

  do{I = I;} while (I == I);  //hang
}
http://www.engblaze.com/we-interrupt...no-interrupts/

"There are a few final things to keep in mind when implementing interrupts.

First, keep in mind that whatever you use your ISR for, it’s good practice to keep it short, because while the ISR is executing, it’s holding up the rest of your program. If you have lots of interrupts, this can slow things to a crawl. Also, by “the rest of your program”, we do mean everything: Arduino functions like millis() won’t increment, and delay() won’t work within an ISR.

Next, if you want to modify any variables within your ISR, you’ll need to make them global variables and mark them as volatile to ensure that your ISR has proper access to them. For example, instead of globally declaring
1

int myInterruptVar;

you would declare
1

volatile int myInterruptVar;

Finally, interrupts are normally globally disabled inside of any ISR (this is why delay() and millis() don’t work). This means that if more interrupt events occur before your ISR has completed, your program won’t catch them. This is another reason to keep ISRs short."


Last edited by buffalobillpatrick; 10-23-14 at 02:36 PM..
buffalobillpatrick is offline   Reply With Quote
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -5. The time now is 02:30 AM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Ad Management by RedTyger
Inactive Reminders By Icora Web Design