// // G2 Solar Controller Function Calls - // int rawPanel12bit; int panelT; int dhwT; int storageT; int supplyT; int outsideT; float TempA; float TempB; float TempC; float TempD; float TempE; int pt1000; float DTemp1; float DTemp2; float DTemp3; float DTemp4; String timeDate; // define pins #define pt1000SensorInput A15 //Analog pin where pt1000 is connected #define A10kSensorInput A14 //Analog pin where 10k is connected #define B10kSensorInput A13 //Analog pin where 10k is connected #define C10kSensorInput A12 //Analog pin where 10k is connected #define D10kSensorInput A11 //Analog pin where 10k is connected #define E10kSensorInput A10 //Analog pin where 10k is connected // pump relay control pins #define PANEL_LEAD_PUMP_RELAY 39 #define PANEL_LAG_PUMP_RELAY 41 #define DHW_PUMP_RELAY 43 #define STORAGE_HEAT_RELAY 45 // system operational parameters // define differential levels #define PanelOnDifferential 12 // Panels must be this much warmer than sUpply to turn on pumps #define PanelLowDifferential 8 // If Panels are only this much warmer, run slower #define PanelOffDifferential 4 // If Panels are only this much warmer, turn off #define HotWaterOnDifferential 12 // Storage must be this much warmer than dhw to turn on pump #define HotWaterOffDifferential 8 // If Storage is only this much warmer than dhw, turn off pump #define StorageTooCold 80 // If Storage isn't hot enough, don't let heat exch pump run #define HIGHTEMP_LIMIT 150 // shut off when this temperature is reached #define FREEZE_LIMIT 20 // don't operate if outside temp is below this temperature // Alarm state values #define ALARM_OFF 0 #define ALARM_FREEZE 1 #define ALARM_HOT 2 int ALARM = ALARM_OFF; // Alarm value, set to off initially String alarmMessage1; // Alarm message in 2 lines to fit LCD String alarmMessage2; // pump state values #define PUMP_OFF 0 #define PUMP_ON 1 #define PUMP_AUTO 2 // pump state - 0 off, 1 on, 2 auto as controlled by ButtonControl or web page function int state_panel_lead = PUMP_AUTO; // default to auto allows temperature logic to control pumps int state_panel_lag = PUMP_AUTO; int state_dhw = PUMP_AUTO; int state_heat = PUMP_AUTO; // lcd button value int lcd_key = 0; // One Wire Bus Settings - plugged into pin 47 on the Arduino MEGA (was on 53 but ethernet calls were somehow stomping on that pin) const int ONE_WIRE_BUS = 47; const int TEMPERATURE_PRECISION = 12; // setup digital oneWire sensor addresses DeviceAddress DSensor1 = {0x28, 0xff, 0x32, 0x41, 0xb2, 0x15, 0x01, 0x9e}; DeviceAddress DSensor2 = {0x28, 0xff, 0x7e, 0x58, 0xb2, 0x15, 0x03, 0x41}; DeviceAddress DSensor3 = {0x28, 0xff, 0x7d, 0x39, 0xb2, 0x15, 0x01, 0xac}; DeviceAddress DSensor4 = {0x28, 0xff, 0x73, 0x74, 0xb2, 0x15, 0x03, 0xcf}; //DeviceAddress DSensor5 = {0x28, 0xff, 0x25, 0x01, 0xb2, 0x15, 0x01, 0x53}; // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs) OneWire oneWire(ONE_WIRE_BUS); // Pass our oneWire reference to Dallas Temperature. DallasTemperature sensors(&oneWire); // Functions /* Analog read of pt1000 RTD sensor */ void Readpt1000Temperature() { // read analog input rawPanel12bit = analogRead(pt1000SensorInput); //adjust raw value // int val = constrain(rawPanel12bit, 700, 1000); int val = constrain(rawPanel12bit, 300, 600); //map 12 bit digital values to temperature in degrees F // 12bitvalue of 775 = 35deg, 910 = 181deg - values from digital pin power and 2.56v ref // panelT = map(val, 775, 910, 35, 181); // 12bitvalue of 391 = 15deg, 472 = 186deg - values from analog reference to divider and default ref pt1000 = map(val, 392, 463, 17, 155); } /* Analog read of 10K sensors */ void Read10kTemperatures() { // read analog input rawPanel12bit = analogRead(A10kSensorInput); //convert raw value with natural log fit curve to temperature in degrees F //t=ln((Vout*R/(Vcc-Vout))/b)/a where //Vout = rawPanel12bit, Vcc = 1023, R = 10k, b = 56369, a = -0.022 double TenkTemp = log((rawPanel12bit * 10000.0 / (1023.0 - rawPanel12bit)) / 56369.0) / -0.022; //truncate natural log result TempA = trunc(TenkTemp); //do it 4 more times rawPanel12bit = analogRead(B10kSensorInput); TenkTemp = log((rawPanel12bit * 10000.0 / (1023.0 - rawPanel12bit)) / 56369.0) / -0.022; TempB = trunc(TenkTemp); rawPanel12bit = analogRead(C10kSensorInput); TenkTemp = log((rawPanel12bit * 10000.0 / (1023.0 - rawPanel12bit)) / 56369.0) / -0.022; TempC = trunc(TenkTemp); rawPanel12bit = analogRead(D10kSensorInput); TenkTemp = log((rawPanel12bit * 10000.0 / (1023.0 - rawPanel12bit)) / 56369.0) / -0.022; TempD = trunc(TenkTemp); rawPanel12bit = analogRead(E10kSensorInput); TenkTemp = log((rawPanel12bit * 10000.0 / (1023.0 - rawPanel12bit)) / 56369.0) / -0.022; TempE = trunc(TenkTemp); } /* Digital read of DS18B20 one-wire bus sensors */ void ReadDigitalTemperatures() { // call sensors.requestTemperatures() to issue a global temperature // request to all devices on the bus sensors.requestTemperatures(); // get temperatures from devices DTemp1 = sensors.getTempF(DSensor1); DTemp2 = sensors.getTempF(DSensor2); DTemp3 = sensors.getTempF(DSensor3); DTemp4 = sensors.getTempF(DSensor4); } /* build golbal timeDate text string with time and date for serial monitor and web reporting */ void readTimeDate() //builds timeDate string from RTC reads { String m; int t; tmElements_t tm; if (RTC.read(tm)) { timeDate ="Time: "; t=tm.Hour; //hours m="AM"; if ( t > 12) { t=t-12; m="PM"; } if (t < 10){ timeDate = timeDate + "0" + t + ":"; } else { timeDate = timeDate + t + ":"; } t = tm.Minute; //minutes if (t < 10){ timeDate = timeDate + "0" + t + ":"; } else { timeDate = timeDate + t + ":"; } t = tm.Second; //seconds if (t < 10){ timeDate = timeDate + "0" + t + " "; } else { timeDate = timeDate + t + " "; } timeDate = timeDate + m + ", Date: "; //append AM or PM t = tm.Month; //Month timeDate = timeDate + t + '/'; t = tm.Day; //Day timeDate = timeDate + t + '/'; t = tmYearToCalendar(tm.Year); timeDate = timeDate + t; } else { if (RTC.chipPresent()) { Serial.println("The DS1307 is stopped. Please run the SetTime"); Serial.println("example to initialize the time and begin running."); Serial.println(); } else { Serial.println("DS1307 read error! Please check the circuitry."); Serial.println(); } delay(9000); } } /* Report all time and values to the Serial Monitor */ void UpdateSerialMonitor() { //print time stamp Serial.println(timeDate); //show temps Serial.print("10k A Temp = "); Serial.println(TempA); Serial.print("10k B Temp = "); Serial.println(TempB); Serial.print("10k C Temp = "); Serial.println(TempC); Serial.print("10k D Temp = "); Serial.println(TempD); Serial.print("10k E Temp = "); Serial.println(TempE); Serial.println(); Serial.print("pt1000 Temp = "); Serial.println(pt1000); Serial.println(); Serial.print("D 1 Temp = "); Serial.println(DTemp1); Serial.print("D 2 Temp = "); Serial.println(DTemp2); Serial.print("D 3 Temp = "); Serial.println(DTemp3); Serial.print("D 4 Temp = "); Serial.println(DTemp4); Serial.println(); Serial.print("Panel Temperature = "); Serial.println(panelT); Serial.print("sUpply Temperature = "); Serial.println(supplyT); Serial.print("Outside Temperature = "); Serial.println(outsideT); Serial.print("Storage Temperature = "); Serial.println(storageT); Serial.print("Hot Water Temperature = "); Serial.println(dhwT); Serial.println(); Serial.print("Panel Pump Status Lag/Lead = "); if (digitalRead(PANEL_LAG_PUMP_RELAY)) Serial.print( "OFF"); else Serial.print("ON"); Serial.print(" , "); if (digitalRead(PANEL_LEAD_PUMP_RELAY)) Serial.println( "OFF"); else Serial.println("ON"); Serial.print("DHW Pump Status = "); if (digitalRead(DHW_PUMP_RELAY)) Serial.println( "OFF"); else Serial.println("ON"); Serial.print("Heat Exch Pump Status = "); if (digitalRead(STORAGE_HEAT_RELAY)) Serial.println( "OFF"); else Serial.println("ON"); Serial.print("Alarm state = "); if (ALARM != ALARM_OFF) { Serial.print(alarmMessage1); Serial.print(" "); Serial.println(alarmMessage2); } else Serial.println ("no Alarms"); Serial.println(); Serial.println(); } /* Write Temps to LCD. */ void UpdateLCDTemperatures() { lcd.clear(); lcd.setCursor (0, 0); lcd.print ("P="); lcd.print ((int) panelT); lcd.setCursor (6, 0); lcd.print ("U="); lcd.print ((int) supplyT); lcd.setCursor (12, 0); lcd.print ("O="); lcd.print ((int) outsideT); lcd.setCursor (0, 1); lcd.print (" S="); lcd.print ((int) storageT); lcd.setCursor (8, 1); lcd.print ("HW="); lcd.print ((int) dhwT); } /* Check for any Alarm conditions and if found, turn off panel pumps and set Alarm and Message */ void Alarm() { if (storageT >= HIGHTEMP_LIMIT) { ALARM = ALARM_HOT; alarmMessage1 = "Storage at"; alarmMessage2 = "High Limit"; // ensure panel pumps are off (they should be anyway) if (state_panel_lead == PUMP_AUTO) digitalWrite (PANEL_LEAD_PUMP_RELAY, HIGH); if (state_panel_lag == PUMP_AUTO) digitalWrite (PANEL_LAG_PUMP_RELAY, HIGH); } else if (outsideT <= FREEZE_LIMIT) { ALARM = ALARM_FREEZE; alarmMessage1 = "Freeze Protectn"; alarmMessage2 = "Too Cold Outsid"; // ensure panel pumps are off if (state_panel_lead == PUMP_AUTO) digitalWrite (PANEL_LEAD_PUMP_RELAY, HIGH); if (state_panel_lag == PUMP_AUTO) digitalWrite (PANEL_LAG_PUMP_RELAY, HIGH); } // add check for water level // else ALARM = ALARM_OFF; if (ALARM != ALARM_OFF) { // report to LCD display lcd.clear(); lcd.setCursor (0, 0); lcd.print (alarmMessage1); lcd.setCursor (0, 1); lcd.print (alarmMessage2); delay(1000); //delay so you can see alarm message } } /* DF Robot LCD shield Read Button routine */ int read_LCD_buttons() { // read the buttons int adc_key_in = 0; #define btnRIGHT 0 #define btnUP 1 #define btnDOWN 2 #define btnLEFT 3 #define btnSELECT 4 #define btnNONE 5 adc_key_in = analogRead(A0); // read the value from the button voltage divider if (adc_key_in > 1000) return btnNONE; // Set analog ranges for buttons if (adc_key_in < 50) return btnRIGHT; //DHW if (adc_key_in < 195) return btnUP; //Panel Lead if (adc_key_in < 380) return btnDOWN; //Panel Lag if (adc_key_in < 555) return btnLEFT; //Heat enable if (adc_key_in < 790) return btnSELECT; //All to Auto return btnNONE; // when all others fail, return this. } /* Read Buttons for User Control of Pumps */ void ButtonControl() { // set control pin to LOW to turn relay on, HIGH to turn relay off // check manual pump control from LCD button panel if (lcd_key != read_LCD_buttons()) // if not changed skip control { lcd_key = read_LCD_buttons(); // read the buttons if (lcd_key != btnNONE) { lcd.clear(); lcd.setCursor(0, 0); // put up the pump titles lcd.print("PN1 PN2 DWH HEAT"); } switch (lcd_key) { // depending on which button was pushed, we perform an action case btnRIGHT: { // push button "RIGHT" to toggle DHW pump lcd.setCursor(8, 1); switch (state_dhw) { case PUMP_AUTO: { state_dhw = PUMP_OFF; lcd.print("OFF "); return; } case PUMP_OFF: { state_dhw = PUMP_ON; lcd.print("ON "); return; } case PUMP_ON: { state_dhw = PUMP_AUTO; lcd.print("AUTO"); return; } break; } break; } case btnUP: { // push button "UP" to toggle lead panel pump lcd.setCursor(0, 1); switch (state_panel_lead) { case PUMP_AUTO: { state_panel_lead = PUMP_OFF; lcd.print("OFF "); return; } case PUMP_OFF: { state_panel_lead = PUMP_ON; lcd.print("ON "); return; } case PUMP_ON: { state_panel_lead = PUMP_AUTO; lcd.print("AUTO"); return; } break; } break; } case btnDOWN: { // push button "DOWN" to toggle lag panel pump lcd.setCursor(4, 1); switch (state_panel_lag) { case PUMP_AUTO: { state_panel_lag = PUMP_OFF; lcd.print("OFF "); return; } case PUMP_OFF: { state_panel_lag = PUMP_ON; lcd.print("ON "); return; } case PUMP_ON: { state_panel_lag = PUMP_AUTO; lcd.print("AUTO"); return; } break; } break; } case btnLEFT: { // push button "LEFT" to toggle heat relay lcd.setCursor(12, 1); switch (state_heat) { case PUMP_AUTO: { state_heat = PUMP_OFF; lcd.print("OFF "); return; } case PUMP_OFF: { state_heat = PUMP_ON; lcd.print("ON "); return; } case PUMP_ON: { state_heat = PUMP_AUTO; lcd.print("AUTO"); return; } break; } break; } case btnSELECT: { // push button "SELECT" to reset all pumps to AUTO lcd.setCursor(0, 1); lcd.print("AUTOAUTOAUTOAUTO"); // show AUTO's on the screen state_dhw = PUMP_AUTO; state_panel_lead = PUMP_AUTO; state_panel_lag = PUMP_AUTO; state_heat = PUMP_AUTO; break; } case btnNONE: { break; } } } } // Differential Temperature Pump Control void PumpControl() { // manual panel lead pump control: if (state_panel_lead == PUMP_ON) digitalWrite (PANEL_LEAD_PUMP_RELAY, LOW); else { if (state_panel_lead == PUMP_OFF) digitalWrite (PANEL_LEAD_PUMP_RELAY, HIGH); else { // auto panel lead pump control: // if no alarms // set control pin to LOW to turn relay on, HIGH to turn relay off // turn on if panel vs supply differential is greater than turnOnDifferential, checking for button override if (ALARM == ALARM_OFF) { if (panelT > (supplyT + PanelOnDifferential) ) { digitalWrite (PANEL_LEAD_PUMP_RELAY, LOW); digitalWrite (PANEL_LAG_PUMP_RELAY, LOW); } } }} // manual panel lag pump control: if (state_panel_lag == PUMP_ON) digitalWrite (PANEL_LAG_PUMP_RELAY, LOW); else { if (state_panel_lag == PUMP_OFF) digitalWrite (PANEL_LAG_PUMP_RELAY, HIGH); else { // auto panel lead pump control: //turn off lag pump if differential is down far enough or back on if risen enough if (!digitalRead(PANEL_LEAD_PUMP_RELAY)) //if the lead pump is running { if (panelT < (supplyT + PanelLowDifferential) ){ digitalWrite (PANEL_LAG_PUMP_RELAY, HIGH); } else { digitalWrite (PANEL_LAG_PUMP_RELAY, LOW); } } }} //turn off both pumps if differential is less than turnOffDifferential if (panelT < (supplyT + PanelOffDifferential) ){ if (state_panel_lead == PUMP_AUTO) digitalWrite (PANEL_LEAD_PUMP_RELAY, HIGH); if (state_panel_lag == PUMP_AUTO) digitalWrite (PANEL_LAG_PUMP_RELAY, HIGH); } // manual dhw pump control if (state_dhw == PUMP_ON) { digitalWrite (DHW_PUMP_RELAY, LOW); } else { if (state_dhw == PUMP_OFF) { digitalWrite (DHW_PUMP_RELAY, HIGH); } else { // auto control: turn on DHW Pump when storage enough warmer if (storageT > (dhwT + HotWaterOnDifferential)) { digitalWrite (DHW_PUMP_RELAY, LOW); } if (storageT < (dhwT + HotWaterOffDifferential)) { digitalWrite (DHW_PUMP_RELAY, HIGH); }}} // manual heat exchanger pump control if (state_heat == PUMP_ON) { digitalWrite (STORAGE_HEAT_RELAY, LOW); } else { if (state_heat == PUMP_OFF) { digitalWrite (STORAGE_HEAT_RELAY, HIGH); } else { // auto control: prevent forced air heat exchanger pump from coming on if storage is too low if (storageT > (StorageTooCold)) { digitalWrite (STORAGE_HEAT_RELAY, LOW); } if (storageT < (StorageTooCold)) { digitalWrite (STORAGE_HEAT_RELAY, HIGH); }} } }