Hello.
I am writing a program to fill a hot tub with water, and empty it on a timer. The pump is connected to relayThree, which empties twice a day. This works fine.
The solenoid to fill it back up (relayOne) connected to a Combi boiler also works and fills with hot water to 980 litres, stopping when the sensor placed at 980 litres detects water. This is also working.
The problem is that every time a bit of water is lost due to evaporation or someone getting out and taking a bit of water with, relayOne is activated and turns on for a second or two. This is problematic as aside for the mechanical wear and tear on the relay and solenoid, the water comes in cold as it does not have time to be heated (like when you turn the hot tap, for the first few seconds the water is cold). So what I'm trying to do is add a second sensor at the 930 litre mark. So when filling up, it should fill to 980, but then should not keep topping itself up until it goes below the 930 litre mark, when it should top itself up to 980 litres.
I suspect that I'd need to record the time the pool is full using millis and the time it passed the 930 mark and see which came first, but I am struggling to do this.
Below is my code. The relevant function is waterCheck .
#include <LiquidCrystal.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <RTClib.h>
#include <Wire.h>
RTC_DS3231 RTC;
byte relayOne = 3;
byte relayTwo = 0;
byte relayThree = 11;
byte waterSensorHigh = 9;
byte waterSensorLow = 12;
byte led = 13;
int waterLevelHigh;
int waterLevelLow;
float temp;
unsigned long delayStart = 0; // time delay started
unsigned long delayTime = 60000; // wait 1 minute before turning on
bool delayRunning = false; // true if still waiting for delay to finish
byte onhour1=3; //------First Timer
byte onmin1=30; //hour= 0-23
byte onsec1=0; //minutes,seconds= 0-59
byte offhour1=3;
byte offmin1=45;
byte offsec1=0;
//boolean Sun1=1; //I haven't set this up yet
//boolean Mon1=1; //0= day disabled
//boolean Tue1=1; //1= day enabled
//boolean Wed1=1;
//boolean Thu1=1;
//boolean Fri1=1;
//boolean Sat1=1;
byte onhour2=14; //-----Second Timer
byte onmin2=0;
byte onsec2=0;
byte offhour2=14;
byte offmin2=15;
byte offsec2=0;
//boolean Sun2=0; //0= day disabled
//boolean Mon2=0; //1= day enabled
//boolean Tue2=0;
//boolean Wed2=0;
//boolean Thu2=0;
//boolean Fri2=1;
//boolean Sat2=1;
//-------To convert clock into single number
unsigned long Time;
unsigned long Hour;
unsigned long Min;
unsigned long Sec;
//------To convert first timer into Single number
unsigned long on_Time1;
unsigned long on_hour1;
unsigned long on_min1;
unsigned long on_sec1;
unsigned long off_Time1;
unsigned long off_hour1;
unsigned long off_min1;
unsigned long off_sec1;
//------To convert second timer into Single number
unsigned long on_Time2;
unsigned long on_hour2;
unsigned long on_min2;
unsigned long on_sec2;
unsigned long off_Time2;
unsigned long off_hour2;
unsigned long off_min2;
unsigned long off_sec2;
boolean RelayState1;
boolean RelayState2;
#define ONE_WIRE_BUS 8 // Data wire of temp probe is plugged into pin 8 on the Arduino
OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with a OneWire devices
DallasTemperature sensors(&oneWire); // Pass oneWire reference to Dallas Temperature.
LiquidCrystal lcd(1, 2, 4, 5, 6, 7); // Creates an LC object. Parameters: (rs, enable, d4, d5, d6, d7)
byte degreeSign[8] = { //create degree sign
0b00110,
0b01001,
0b01001,
0b00110,
0b00000,
0b00000,
0b00000,
0b00000
};
void setup() {
lcd.begin(16, 2);
lcd.createChar(1, degreeSign);
sensors.begin();
pinMode(relayOne, OUTPUT);
pinMode(relayTwo, OUTPUT);
pinMode(relayThree, OUTPUT);
pinMode(waterSensorHigh, INPUT);
pinMode(led, OUTPUT);
//digitalWrite(led,LOW);
digitalWrite(relayOne,HIGH);
digitalWrite(relayThree,HIGH);
// Serial.begin(9600);
Wire.begin();
RTC.begin();
}
void loop() {
lcdDisplay();
// heater();
waterCheck();
// errorCheck();
timeSwitch();
}
//===================timeswitch for pump=========================
void timeSwitch() {
DateTime now = RTC.now(); // Clock call
now = RTC.now();
//-------------Conversion----------//
//---------Converting clock time into single number
Hour = now.hour();
Min = now.minute();
Sec = now.second();
Time = (Hour*10000+ Min*100 +Sec*1);
//--------Converting firt timer on/off into single number
on_hour1=onhour1;
on_min1=onmin1;
on_sec1=onsec1;
on_Time1=(on_hour1*10000 + on_min1*100 + on_sec1);
off_hour1=offhour1;
off_min1=offmin1;
off_sec1=offsec1;
off_Time1=(off_hour1*10000 + off_min1*100 + off_sec1);
//--------Converting second timer on/off into single number
on_hour2=onhour2;
on_min2=onmin2;
on_sec2=onsec2;
on_Time2=(on_hour2*10000 + on_min2*100 + on_sec2);
off_hour2=offhour2;
off_min2=offmin2;
off_sec2=offsec2;
off_Time2=(off_hour2*10000 + off_min2*100 + off_sec2);
//----RelayState1 Function----//
if(onhour1 == offhour1 && onmin1==offmin1 && onsec1==offsec1){
RelayState1=LOW;
}
if(on_Time1 < off_Time1){
if(Time >= on_Time1 && Time < off_Time1){ //Start
RelayState1= HIGH;
}
else if(Time >= off_Time1) {
RelayState1= LOW;
}
else{
RelayState1= LOW;
}
}
if (on_Time1 > off_Time1){
if(Time >= on_Time1 && Time <= 235959){ //Start
RelayState1= HIGH;
}
else if(Time < off_Time1 ){
RelayState1= HIGH;
}
else if(Time >= off_Time1 && Time < on_Time1){
RelayState1= LOW;
}
}
//----RelayState2 Function----//
if(onhour2 == offhour2 && onmin2==offmin2 && onsec2==offsec2){
RelayState2=LOW;
}
if(on_Time2 < off_Time2){
if(Time >= on_Time2 && Time < off_Time2){ //Start
RelayState2= HIGH;
}
else if(Time >= off_Time2) {
RelayState2= LOW;
}
else{
RelayState2= LOW;
}
}
if (on_Time2 > off_Time2){
if(Time >= on_Time2 && Time <= 235959){ //Start
RelayState2= HIGH;
}
else if(Time < off_Time2 ){
RelayState2= HIGH;
}
else if(Time >= off_Time2 && Time < on_Time2){
RelayState2= LOW;
}
}
//-------Relay function
if(RelayState1 ==HIGH || RelayState2==HIGH){
digitalWrite(relayThree,LOW);
}
else{
digitalWrite(relayThree,HIGH);
}
}
//===================serial read for error checking=========================
void errorCheck() {
Serial.print(delayStart);
Serial.print(" ");
Serial.print(delayRunning);
Serial.print(" ");
Serial.print(waterLevelHigh);
Serial.print(" ");
Serial.print(millis());
Serial.print(" ");
Serial.println(relayOne);
}
//===========This module checks the water level and fills it up if necessary======================
void waterCheck() {
waterLevelHigh = digitalRead(waterSensorHigh);
delay(100);
if (waterLevelHigh == LOW && !delayRunning && RelayState1 == LOW && RelayState2 == LOW) // check if the water level is too low, if yes, turn on the relay after set time
{
delayStart = millis();
delayRunning = true;
}
else
{
digitalWrite(relayOne, HIGH);
}
if (delayRunning && ((millis() - delayStart) >= delayTime))
{
digitalWrite(relayOne, LOW);
if (waterLevelHigh == HIGH) {
delayRunning = false;
}
}
}
//===========this code shows temperature on the LCD======================
void lcdDisplay() {
sensors.requestTemperatures(); // Send the command to get temperatures
temp = sensors.getTempCByIndex(0); // write the temperature into the temp float
lcd.setCursor(0, 0);
lcd.print(" Mikve Temp. is:");
lcd.setCursor(1, 1); // Sets the location at which subsequent text written to the LCD will be displayed
lcd.print(temp);
lcd.write(1); //degree sign
lcd.print("C ");
lcd.print(sensors.getTempFByIndex(0));
lcd.write(1); //degree sign
lcd.print("F");
delay(250);
}
//===========this code turns on the heater======================
void heater() {
if (temp < 40 && temp >= 15 && waterLevelHigh == HIGH) // check if the water temp is in the right range, and water is detected. If so, turn on heater
{
digitalWrite(relayTwo, LOW);
}
else
{
digitalWrite(relayTwo, HIGH);
}
}