/********************************************************************/
//
// All digital pins must have 4K7 ohm pullup resistors to the suppy voltage.
// All digital pins must have a 100nF capacitor as close to the board to ground (0v).
// Power supply must be ground (0v) to earth.
// 100nF capacitor across the 5V & 3v3 supply line to ground (0V).
// 100Nf capacitor across the relay input pins and 5v pins to ground (0V).
//
// First we include the libraries
#include <OneWire.h>
#include <DallasTemperature.h>
#include <SPI.h>
#include <LiquidCrystal_I2C.h> // includes the LiquidCrystal Library
#include <avr/wdt.h> // Watchdog library
/********************************************************************/
// Data wire is plugged into pin 2 on the Arduino
#define ONE_WIRE_BUS 2
/********************************************************************/
// 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);
/********************************************************************/
//Set up relay first output
int relay8 = 8; // Pump Relay module IN1
int relay9 = 9; // Ball Valve Relay module IN1
volatile byte relayState = HIGH;
int flushPump = 0; // Initialize flushpump variable
int flushLoop = 8; // Initialize flushLoop variable
int panelFlush = 0; // Initialize panelFlush timer variable
int ballValveCycleTime = 15000; // Initialize the ballValvecycleTime variable
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 20, 4);
// Solar Panel Flush value 5 seconds
int SensorDifferential = 5; // Initialize SensorDifferential variable. Difference between in/out sensors
int ldrPin = A0; // select the input pin for LDR
int ldrValue = 0; // variable to store the value coming from the ldr sensor
int maxLdrValue = 600 ; // variable to enable pumping to start
int overRidePin = A1; // If this pin is low, then we can pump
int overRideValue = 0;
int lastSensor0 = 0;
int lastSensor1 = 0;
unsigned long time_now;
int programDelayTime = 1000;
int RESET_PIN = 3;
int BV_STAT = 0 ;
void setup(void)
{
// Configure auto reset
//digitalWrite(RESET_PIN, HIGH);
//pinMode(RESET_PIN, OUTPUT);
// Initializes the interface to the LCD screen, and specifies the dimensions (width and height) of the display }
// Start up the library
sensors.begin();
lcd.init();
lcd.backlight();
wdt_disable(); //Disable WDT
// start serial port
Serial.begin(115200);
Serial.println("Goodwitch Systems - Solar Pump Control - 2.8.0");
// Start up the library
pinMode(LED_BUILTIN, OUTPUT);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Goodwitch Systems");
lcd.setCursor(0,1);
lcd.print("Solar Pump Control");
lcd.setCursor(0,2);
lcd.print("Version: 2.8.0");
delay(2000);
lcd.clear();
delay(3000);
wdt_enable(WDTO_8S); // options: WDTO_1S, WDTO_2S, WDTO_4S, WDTO_8S }
// Force the ball valve to close regardless, as the previous state may have left the valve open.
// The default relay state is the ball valve to close, so it may reset to the closed state
// Serial.println("started 8 second Watchdog timer");
pumpOff();
ballValveClose();
}
void loop(void)
{
wdt_reset(); // confirm to watchdog timer that all is well
//Serial.println("Reset Watchdog Timer - 0");
digitalWrite(LED_BUILTIN, HIGH); // turn the LED On
// call sensors.requestTemperatures() to issue a global temperature
// request to all devices on the bus
/********************************************************************/
//Serial.print(" Requesting temperatures...");
sensors.requestTemperatures(); // Send the command to get temperature readings
// Serial.println("DONE");
/********************************************************************/
//Sensor1 is the COLD sensor Inlet
int Sensor1 = round(sensors.getTempCByIndex(1));
//int lastSensor1 = Sensor1;
// Take the output sensor and add the differntial value as the switch on value.
// Sensor0 is the HOT sensor Outlet
//int lastSensor0 = Sensor0;
int Sensor0 = round(sensors.getTempCByIndex(0)) + SensorDifferential;
//int Sensor0 = round(sensors.getTempCByIndex(0));
// You can have more than one DS18B20 on the same bus.
// 0 refers to the first IC on the wire
// Check for the sensor failure
// This section tests the sensors continously.
// Should a sensor fail, then the system will shutdown the pump immediately
// This section is a problem when a sensor does not respond and invokes the watchdog.
// Better to use the existing value
// If the sensor returns a value of -127, then the read failed.
// We take the last sensor reading and use that as it does not matter
// if the sensor value stays the same, as long as we have a reasonable value
if ( Sensor0 == -127 ) {
Sensor0 = lastSensor0 ;
} else {
lastSensor0 = Sensor0;
}
// If the sensor returns a value of -127, then the read failed.
// We take the last sensor reading and use that as it does not matter
// if the sensor value stays the same, as long as we have a reasonable value
if ( Sensor1 == -127 ) {
lastSensor1 ;
Sensor1 = lastSensor1;
} else {
lastSensor0 = Sensor0 ;
}
//Serial.println("Temperature sensor has failed");
//lcd.clear();
//lcd.setCursor(0,0);
//lcd.print("Temperature Sensor");
//lcd.setCursor(0,1);
//lcd.print("Failure!!");
//flushPump=0; // Reset flushPump back to zero
//pumpOff();
//digitalWrite(relay9, HIGH); // We directy shutdown the ball valve instead of going to the function.
//while (true) {
// Flash diagnostics. 2 x 2 second flashes, sensor failure
//digitalWrite(LED_BUILTIN,LOW);delay(500);
//digitalWrite(LED_BUILTIN,HIGH);delay(2000);
//digitalWrite(LED_BUILTIN,LOW);delay(500);
//digitalWrite(LED_BUILTIN,HIGH);delay(2000);
//digitalWrite(LED_BUILTIN,LOW);delay(5000);
//}
lcd.setCursor(0,0);
lcd.print("Temp Out: ");
lcd.print(sensors.getTempCByIndex(1));
lcd.print(" ");
//lcd.print(Sensor1);
lcd.setCursor(0,1);
lcd.print("Temp In: ");
lcd.print(sensors.getTempCByIndex(0));
lcd.print(" ");
//lcd.print(Sensor0);
lcd.setCursor(0,2);
lcd.print("Differential: ");
lcd.print(SensorDifferential);
lcd.setCursor(19,2); //Heart Beat
lcd.print("*"); //Heart beat character
ldrValue = analogRead(ldrPin); // read the value from the sensor
//Serial.println(ldrValue); //prints the values coming from the sensor on the screen
//Serial.print("Sensor Out: ");
// Serial.print(round(sensors.getTempCByIndex(1))); // Why "byIndex"?
// Serial.print(" / In: ");
// Serial.println(round(sensors.getTempCByIndex(0))); // Why "byIndex"?
//Serial.print("Sensor Differential: ");
//Serial.println(SensorDifferential); // Why "byIndex"?
//Serial.print("Flush pump: ");
//Serial.println(flushPump); // Why "byIndex"?
display_ldr();
overRideValue = analogRead(overRidePin);
// Serial.print("Overide: ");
// Serial.println(overRideValue);
// Here we provide for an override button to switch the pump on manually.
if ( overRideValue < 10 ) {
ballValveOpen();
pumpOn();
ballValveClose();
} else {
// Here we check the light level as we don't want the pump to run at night.
if ( ldrValue > maxLdrValue ) {
//Serial.print("LDR Enable: ");
//Serial.println(ldrValue);
// Enable ball valve
ballValveOpen();
if ( Sensor1 > Sensor0 ) {
display_ldr();
pumpOn();
flushPump = 1;
} else if (Sensor1 <= Sensor0 ) {
display_ldr();
pumpOff();
} else {
display_ldr();
pumpOff();
} // End nested if
} else {
display_ldr();
pumpOff();
//Serial.println("Pump Off ");
// Close ball valve
ballValveClose();
} // End if
//delay(250);
time_now = millis();
while(millis() < time_now + programDelayTime){
//wait approx. [period] ms
}
}
wdt_reset(); //Reset the watchdog
//Serial.println("Reset Watchdog Timer - 1");
// while(1); //Watchdog timer should get triggered here
digitalWrite(LED_BUILTIN, LOW);
lcd.setCursor(19,2); //Heart beat
lcd.print(" "); //Heart Beat field clear
} // End loop
//////////////////////////////////////////////////////////////////////////////////////////
void pumpOn() {
// Pin for relay module set as output
pinMode(relay8, OUTPUT);
digitalWrite(relay8, LOW);
digitalWrite(LED_BUILTIN, LOW); // turn the LED off
lcd.setCursor(0,3);
lcd.print("Pump: On ");
//Serial.println("Pump On ");
wdt_reset(); //Reset the watchdog
//Serial.println("Reset Watchdog Timer - 2");
}
void pumpOff() {
// Pin for relay module set as output
pinMode(relay8, OUTPUT);
digitalWrite(relay8, HIGH);
digitalWrite(LED_BUILTIN, LOW); // turn the LED off
lcd.setCursor(0,3);
lcd.print("Pump: Off ");
//Serial.println("Pump Off ");
wdt_reset(); //Reset the watchdog
//Serial.println("Reset Watchdog Timer - 3");
}
void flushPipe() {
if( flushPump == 1 ){
// Once we get the signal to power off the pump we sleep for 10 seconds to give the panel time to flush any residual hot water from the pipes.
//Serial.println("Panel Flush Delay: ");
//Serial.println(panelFlush);
//while (flushLoop < panelFlush ) {
//flushLoop = flushLoop + 1;
while (flushLoop > panelFlush ) {
flushLoop = flushLoop - 1;
lcd.setCursor(0,0);
lcd.print("Temp Out: ");
lcd.print(sensors.getTempCByIndex(1));
lcd.setCursor(0,1);
lcd.print("Temp In: ");
lcd.print(sensors.getTempCByIndex(0));
lcd.setCursor(10,3);
lcd.print(" Flush: ");
lcd.setCursor(18,3);
lcd.print(flushLoop);
//Serial.print("Pump Off in: " );
//Serial.println( flushLoop );
time_now = millis();
while(millis() < time_now + programDelayTime){
//wait approx. [period] ms
wdt_reset(); //Reset the watchdog
//Serial.println("Reset Watchdog Timer - 4");
}
} // End while loop
flushPump=0; // Reset flushPump back to zero
flushLoop=8; // Reset flushLoop back to 8
lcd.clear();
} // End If statement
pumpOff();
}
void display_ldr() {
//Serial.println(ldrValue);
lcd.setCursor(10,3);
lcd.print("Light: ");
lcd.setCursor(17,3);
lcd.print(ldrValue);
wdt_reset(); //Reset the watchdog
//Serial.println("Reset Watchdog Timer - 5");
}
void ballValveOpen() {
//Serial.println(BV_STAT);
pinMode(relay9, OUTPUT);
digitalWrite(relay9, LOW);
if ( BV_STAT == 1) {
BV_STAT = 2;
lcd.clear();
lcd.print("Ball Valve Opening");
time_now = millis();
while(millis() < time_now + ballValveCycleTime){
//wait approx. [period] ms
lcd.setCursor(0,1);
lcd.print((time_now + ballValveCycleTime) - millis());
lcd.print(" ");
wdt_reset(); //Reset the watchdog
//Serial.println("Reset Watchdog Timer - 6");
}
//Serial.println(BV_STAT);
lcd.clear();
}
lcd.setCursor(17,1);
lcd.print("V:O");
BV_STAT = 2;
}
void ballValveClose() {
//Serial.println(BV_STAT);
if ( BV_STAT == 0 or BV_STAT == 2 ) {
BV_STAT = 1;
//Serial.println(BV_STAT);
pinMode(relay9, OUTPUT);
digitalWrite(relay9, HIGH);
lcd.clear();
lcd.print("Ball Valve Closing");
time_now = millis();
while(millis() < time_now + ballValveCycleTime) {
lcd.setCursor(0,1);
lcd.print((time_now + ballValveCycleTime) - millis());
lcd.print(" ");
wdt_reset(); //Reset the watchdog
//Serial.println("Reset Watchdog Timer - 7");
}
lcd.setCursor(17,0);
lcd.print(" ");
lcd.clear();
lcd.setCursor(17,1);
lcd.print("V:X");
} else if ( BV_STAT == 1 ) {
lcd.setCursor(17,1);
lcd.print("V:X");
}
}