07-27-14, 11:24 PM | #141 |
Master EcoRenovator
Join Date: Mar 2014
Location: Florissant, Colorado
Posts: 599
Thanks: 814
Thanked 59 Times in 55 Posts
|
Setup:
Code:
#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 // 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 6 // D6 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 //These 12 have been tested good #define SOLAR_tank_sensor 0 #define COMP_DISCHARGE_sensor 1 #define DSH_H2O_IN_sensor 2 #define DSH_H2O_OUT_sensor 3 #define INPUT_DEAD1 4 #define INPUT_DEAD2 5 #define IHX_HI_IN_sensor 6 #define IHX_HI_OUT_sensor 7 #define IHX_LO_IN_sensor 8 #define IHX_LO_OUT_sensor 9 #define SOURCE_IN_sensor 10 #define INPUT_DEAD3 11 #define INPUT_DEAD4 12 #define SOURCE_OUT_sensor 13 #define LOAD_IN_sensor 14 #define LOAD_OUT_sensor 15 unsigned long T1; unsigned long T2; unsigned long TT; int i; int Sensor_Data; 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 digitalWrite ( ALIVE_RLY_R1, HIGH); //OFF digitalWrite ( HP_RLY_R2, 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); 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("BBP_HP_SLAVE")); delay(5000); // Warer pumps not started yet, so can't use custom delay beep(50); beep(50); beep(50); delay(1000); lcd.clear(); lcd.home (); // go home lcd.print(F("HP DELAY 20Sec")); lcd.setCursor(0,1); lcd.print(F("BEFORE STARTING")); for (i=0; i< 4; i++) //delay 20 sec. { custom_delay(); //Delay 5 sec. & Checks SRC OUT Temp & GAS } digitalWrite (HP_RLY_R2, LOW); //Power HP lcd.clear(); lcd.home (); // go home lcd.print(F("HP R2 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; 09-10-14 at 05:36 PM.. |
The Following User Says Thank You to buffalobillpatrick For This Useful Post: | AC_Hacker (07-28-14) |
07-27-14, 11:26 PM | #142 |
Master EcoRenovator
Join Date: Mar 2014
Location: Florissant, Colorado
Posts: 599
Thanks: 814
Thanked 59 Times in 55 Posts
|
Forever Loop & functions:
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 (DSH_H2O_IN_sensor)); lcd.clear(); lcd.home (); // go home lcd.print(F("DSH_H2O_IN=")); lcd.print(Sensor_Data); custom_delay(); //Delay 5 sec. & Checks Water SRC OUT Sensor_Data = (Read_10K_NTC (DSH_H2O_OUT_sensor)); lcd.clear(); lcd.home (); // go home lcd.print(F("DSH_H2O_OUT=")); lcd.print(Sensor_Data); custom_delay(); //Delay 5 sec. & Checks Water SRC OUT Sensor_Data = (Read_10K_NTC (IHX_HI_IN_sensor)); lcd.clear(); lcd.home (); // go home lcd.print(F("IHX_HI_IN=")); lcd.print(Sensor_Data); custom_delay(); //Delay 5 sec. & Checks Water SRC OUT Sensor_Data = (Read_10K_NTC (IHX_HI_OUT_sensor)); lcd.clear(); lcd.home (); // go home lcd.print(F("IHX_HI_OUT=")); lcd.print(Sensor_Data); custom_delay(); //Delay 5 sec. & Checks Water SRC OUT Sensor_Data = (Read_10K_NTC (IHX_LO_IN_sensor)); lcd.clear(); lcd.home (); // go home lcd.print(F("IHX_LO_IN=")); lcd.print(Sensor_Data); custom_delay(); //Delay 5 sec. & Checks Water SRC OUT Sensor_Data = (Read_10K_NTC (IHX_LO_OUT_sensor)); lcd.clear(); lcd.home (); // go home lcd.print(F("IHX_LO_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 /* 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 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 34 #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) { digitalWrite (ALIVE_RLY_R1, HIGH); //OFF digitalWrite (HP_RLY_R2, HIGH); //OFF lcd.clear(); lcd.home (); // go home lcd.print(F("GAS LIMIT MET")); lcd.setCursor(0,1); lcd.print(F("TurnOff all Rlys")); delay(5000); 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 (ALIVE_RLY_R1, HIGH); //OFF digitalWrite (HP_RLY_R2, HIGH); //OFF lcd.clear(); lcd.home (); // go home lcd.print(F("HANG FOREVER 2")); 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 Last edited by buffalobillpatrick; 08-06-14 at 01:59 PM.. |
The Following User Says Thank You to buffalobillpatrick For This Useful Post: | AC_Hacker (07-28-14) |
07-28-14, 04:29 AM | #143 |
Helper EcoRenovator
Join Date: Jul 2014
Location: Hungary
Posts: 34
Thanks: 0
Thanked 16 Times in 10 Posts
|
buffalobillpatrick,
Nice, simple code. If you don't mind, I would share with you my complains strictly from remidial intent. - As you handle strings, you will exhaust RAM very fast. All strings are copied from flash to RAM at startup. you should use F() macro to keep strings in flash. Like this. lcd.print(F("COMP_TEMP = ")); look here for details - With temperature displaying, you block the program for 90secs. It's enough time to freeze your BPHX if you are not lucky. I would recommend you to modify the code to have non blocking delays in your code. Or make a custom delay function, which continously measure temperatures and evaluates critical conditions. Much nicer averaging can be done by doing AD conversion repeatedly like below logic: tempX=tempX+(K*(readSensor_F(X)-tempX)) where K<1. By changing the value of K you can control, how much averaging you want. K=1 no averaging, smaller and smaller K means bigger and bigger averaging. For on/off control I would recommend to control Arduino's reset pin, not the supply voltage. This way you can detect short interruptions in the control signal too. T. |
The Following 2 Users Say Thank You to takyka For This Useful Post: |
07-28-14, 09:54 AM | #144 |
Master EcoRenovator
Join Date: Mar 2014
Location: Florissant, Colorado
Posts: 599
Thanks: 814
Thanked 59 Times in 55 Posts
|
Thanks takyka, that dropped my RAM use by 21%
With these 10K NTC Thermisters the readings don't bounce around, that averaging is really not needed. I need to study on "tempX=tempX+(K*(readSensor_F(X)-tempX)) where K<1" On the Reset pin vs. Power on/off The Master Heat System controller would have to hold the Slave reset pin LOW for months at a time, While Slave is wasting power. Also if I need to reset the Master then the Slave would start running HP when not needed. Good Point on "- With temperature displaying, you block the program for 90secs. It's enough time to freeze your BPHX if you are not lucky." In my case I'm using 4 Ton Coax HX's Last edited by buffalobillpatrick; 07-31-14 at 12:43 PM.. |
07-28-14, 02:36 PM | #145 |
Master EcoRenovator
Join Date: Mar 2014
Location: Florissant, Colorado
Posts: 599
Thanks: 814
Thanked 59 Times in 55 Posts
|
takkyka, GREAT idea on the "custom delay"
custom_delay(); //function call example Code:
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 34 #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) { digitalWrite (ALIVE_RLY_R1, HIGH); //OFF digitalWrite (HP_RLY_R2, HIGH); //OFF lcd.clear(); lcd.home (); // go home lcd.print(F("GAS LIMIT MET")); lcd.setCursor(0,1); lcd.print(F("TurnOff all Rlys")); delay(5000); 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 (ALIVE_RLY_R1, HIGH); //OFF digitalWrite (HP_RLY_R2, HIGH); //OFF lcd.clear(); lcd.home (); // go home lcd.print(F("HANG FOREVER 2")); 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 } Last edited by buffalobillpatrick; 08-06-14 at 01:47 PM.. |
07-28-14, 08:20 PM | #146 |
Master EcoRenovator
Join Date: Mar 2014
Location: Florissant, Colorado
Posts: 599
Thanks: 814
Thanked 59 Times in 55 Posts
|
On my much larger & more complicated HEAT_SYS_MASTER program,
takyka's advice to use F() syntax to keep fixed character strings in Flash saved 50% of dynamic memory at a cost of 1% of program storage space. Why don't Arduino IDE do this automatically??? |
07-28-14, 08:41 PM | #147 | |
Supreme EcoRenovator
Join Date: Mar 2009
Location: Portland, OR
Posts: 4,004
Thanks: 303
Thanked 723 Times in 534 Posts
|
Quote:
Need I say more? -AC
__________________
I'm not an HVAC technician. In fact, I'm barely even a hacker... |
|
07-29-14, 08:56 AM | #148 |
Supreme EcoRenovator
Join Date: Mar 2009
Location: Portland, OR
Posts: 4,004
Thanks: 303
Thanked 723 Times in 534 Posts
|
LCD Display!!
My LCD display arrived yesterday. I have even gotten the spec sheets and wiki sources & Arduino library resources bookmarked. Looks pretty nice! I can see why jeff5may would go for this one. I did notice that according to notes on the DFRobot page, there still seem to be some lingering issues with the LED light. Am I correct that we are still going with the Uno, and the 4-way relay shield board? In my heart of hearts, I would prefer to use SSRs instead of mechanical relays, but relays are cheap & good for now. jeff5may, soon as I hear from you, I'll go ahead and order the processor board and relay shield. It'll be great fun to build a test bed and start running various program versions. Best, -AC
__________________
I'm not an HVAC technician. In fact, I'm barely even a hacker... Last edited by AC_Hacker; 07-29-14 at 09:01 AM.. |
07-29-14, 10:25 AM | #149 |
Supreme EcoRenovator
Join Date: Mar 2009
Location: Portland, OR
Posts: 4,004
Thanks: 303
Thanked 723 Times in 534 Posts
|
Digging About un the Parts Box...
After carefully appreciating the new LCD display, I went upstairs and dug about in my parts box and found an Arduino duemilanove, which looks to be functionally identical to the Uno R3... correct me if I'm wrong.
Then I fit the LCD display to the Arduino... everything lined up nicely. This is a pretty nice looking combo!. I noticed that there was one hole that both boards share in common, apparently to put a screw through so their mechanical connection is a little more secure. Two holes would make me happier. So, jeff5may... is your LCD sketch ready to see daylight?? Also, I just ordered the afore mentioned relay shield from amazon... they ship pretty fast. Best, -AC
__________________
I'm not an HVAC technician. In fact, I'm barely even a hacker... Last edited by AC_Hacker; 07-29-14 at 10:31 AM.. |
07-29-14, 11:00 AM | #150 | |
Supreme EcoRenovator
|
Quote:
|
|
The Following User Says Thank You to jeff5may For This Useful Post: | AC_Hacker (07-29-14) |
|
|