#include <EEPROM.h>
#include <EncoderButton.h>
#include <LiquidCrystal_I2C.h>
#include <UniversalTimer.h>
#define analogPin A0
#define relayPin 13
#define DEFAULT_DISPLAY 0
#define DISPLAY_PSTART 1
#define DISPLAY_PSTOP 3
#define DISPLAY_TSTART 2
#define DISPLAY_TSTOP 4
#define MENU_MAX_STEP 5
#define MODIFY_PSTOP DISPLAY_PSTOP*10
#define MODIFY_PSTART DISPLAY_PSTART*10
#define MODIFY_TSTART DISPLAY_TSTART*10
#define MODIFY_TSTOP DISPLAY_TSTOP*10
#define pLow_Min 1.5
#define pLow_Max 2.5
#define pHigh_Min 2.6
#define pHigh_Max 3.5
#define tStart_Min (unsigned int) 1
#define tStart_Max (unsigned int) 30
#define tStop_Min (unsigned int) 10
#define tStop_Max (unsigned int) 45
EncoderButton eb1(4, 5, 6);
LiquidCrystal_I2C lcd(0x27, 20, 4); // set the LCD address to 0x27 for a 16 chars and 2 line display
UniversalTimer startTimer(1000, false);
UniversalTimer stopTimer(1000, false);
const int startAddress = EEPROM.length() - 5;
boolean state, oldState;
int step = DEFAULT_DISPLAY;
int old_step = -1;
unsigned int tStart;
unsigned int tStop;
unsigned long timeOut = 30000L;
float value, pressure, oldPressure;
float offset = 0.5;
float pLow;
float pHigh;
float delta;
void onEb1Clicked(EncoderButton& eb)
{
eb1.resetPressedPosition();
switch (step)
{
case DISPLAY_PSTART:
step = MODIFY_PSTART;
eb1.resetPosition();
lcd.clear();
lcd.blink();
lcd.print("Start Pressure :");
lcd.setCursor(0, 1);
lcd.print(pLow);
lcd.print(" bar");
lcd.setCursor(4, 1);
Serial.println(eb1.position());
break;
case DISPLAY_PSTOP:
step = MODIFY_PSTOP;
eb1.resetPosition();
lcd.clear();
lcd.blink();
lcd.print("Stop Pressure :");
lcd.setCursor(0, 1);
lcd.print(pHigh);
lcd.print(" bar");
lcd.setCursor(4, 1);
break;
case DISPLAY_TSTART:
step = MODIFY_TSTART;
eb1.resetPosition();
lcd.clear();
lcd.blink();
lcd.print("Start Delay :");
lcd.setCursor(0, 1);
if (tStart < 10) lcd.print(" ");
lcd.print(tStart);
lcd.print(" sec");
lcd.setCursor(2, 1);
break;
case DISPLAY_TSTOP:
step = MODIFY_TSTOP;
eb1.resetPosition();
lcd.clear();
lcd.blink();
lcd.print("Stop Delay :");
lcd.setCursor(0, 1);
if (tStop < 10) lcd.print(" ");
lcd.print(tStop);
lcd.print(" sec");
lcd.setCursor(2, 1);
break;
case MODIFY_PSTART:
EEPROM.put(0, pLow);
eb1.resetPosition();
step = DISPLAY_PSTOP;
old_step = -1;
lcd.noCursor();
break;
case MODIFY_PSTOP:
EEPROM.put(8, pHigh);
eb1.resetPosition();
step = DISPLAY_TSTART;
old_step = -1;
lcd.noCursor();
break;
case MODIFY_TSTART:
EEPROM.put(16, tStart);
eb1.resetPosition();
step = DISPLAY_TSTOP;
old_step = -1;
lcd.noCursor();
break;
case MODIFY_TSTOP:
EEPROM.put(24, tStop);
eb1.resetPosition();
step = DISPLAY_PSTART;
old_step = -1;
lcd.noCursor();
break;
}
}
void onButton1LongPress(EncoderButton & eb)
{
step = DEFAULT_DISPLAY;
eb1.resetPosition();
}
void onEb1Encoder(EncoderButton & eb)
{
switch (step)
{
case DEFAULT_DISPLAY:
case DISPLAY_PSTART:
case DISPLAY_PSTOP:
case DISPLAY_TSTART:
case DISPLAY_TSTOP:
step = eb1.position();
break;
case MENU_MAX_STEP:
break;
case MODIFY_PSTART:
delta = (eb1.position() / 10.0);
eb1.resetPosition();
pLow = pLow + delta;
pLow = constrain(pLow, pLow_Min, pLow_Max);
lcd.setCursor(0, 1);
lcd.print(pLow);
lcd.blink();
break;
case MODIFY_PSTOP:
delta = (eb1.position() / 10.0);
eb1.resetPosition();
pHigh = pHigh + delta;
pHigh = constrain(pHigh, pHigh_Min, pHigh_Max);
lcd.setCursor(0, 1);
lcd.print(pHigh);
lcd.blink();
break;
case MODIFY_TSTART:
delta = (eb1.position());
eb1.resetPosition();
tStart = tStart + delta;
tStart = constrain(tStart, tStart_Min, tStart_Max);
lcd.setCursor(0, 1);
if (tStart < 10) lcd.print(" ");
lcd.print(tStart);
lcd.blink();
break;
case MODIFY_TSTOP:
delta = (eb1.position());
eb1.resetPosition();
tStop = tStop + delta;
tStop = constrain(tStop, tStop_Min, tStop_Max);
lcd.setCursor(0, 1);
if (tStop < 10) lcd.print(" ");
lcd.print(tStop);
lcd.blink();
break;
default:
eb1.resetPosition();
break;
}
}
byte calculateCRC(byte data[], byte len)
{
byte crc = 0;
for (byte i = 0; i < len; i++) crc ^= data[i];
return (crc);
}
void setEeprom(void)
{
byte data[4] = {0x55, 0xAA, 0xAA, 0x55};
byte crc = calculateCRC(data, 4);
for (int i = 0 ; i < EEPROM.length() ; i++) EEPROM.write(i, 0);
for (byte i = 0; i < 4; i++) EEPROM.write(startAddress + i, data[i]);
EEPROM.write(startAddress + 4, crc);
}
bool checkEeprom(void)
{
byte data[4];
for (byte i = 0; i < 4; i++) data[i] = EEPROM.read(startAddress + i);
byte storedCRC = EEPROM.read(startAddress + 4);
byte calculatedCRC = calculateCRC(data, 4);
if (storedCRC != calculatedCRC)
{
return (false);
}
else
{
return (true);
}
}
void setup() {
eb1.setClickHandler(onEb1Clicked);
eb1.setEncoderHandler(onEb1Encoder);
eb1.setLongPressHandler(onButton1LongPress, false);
pinMode(relayPin, OUTPUT);
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Rain Water Pump");
lcd.setCursor(0, 1);
lcd.print("V1.0 -- 04/2024");
delay(3000);
lcd.clear();
lcd.print("Check EEprom ..." );
if (checkEeprom() == true)
{
lcd.setCursor(0, 1);
lcd.print("EEprom OK !" );
EEPROM.get(0, pLow);
EEPROM.get(8, pHigh);
EEPROM.get(16, tStart);
EEPROM.get(24, tStop);
}
else
{
setEeprom();
pLow = 2.00;
pHigh = 3.00;
tStart = 5;
tStop = 30;
EEPROM.put(0, pLow);
EEPROM.put(8, pHigh);
EEPROM.put(16, tStart);
EEPROM.put(24, tStop);
lcd.setCursor(0, 1);
lcd.print("Re-initialized !" );
}
delay(1500);
lcd.clear();
lcd.print("P Start:");
lcd.print(pLow);
lcd.print(" bar");
lcd.setCursor(0, 1);
lcd.print("T Start:");
lcd.print(tStart);
lcd.print(" sec");
delay(1500);
lcd.clear();
lcd.print("P Stop :");
lcd.print(pHigh);
lcd.print(" bar");
lcd.setCursor(0, 1);
lcd.print("T Stop :");
lcd.print(tStop);
lcd.print(" sec");
delay(1500);
lcd.clear();
startTimer.setInterval(tStart * 1000L);
stopTimer.setInterval(tStop * 1000L);
}
void loop() {
eb1.update();
if (((eb1.msSinceLastEvent() > timeOut) and step != DEFAULT_DISPLAY) or (step == MENU_MAX_STEP) or (eb1.position() < 0 ))
{
eb1.resetPosition();
step = DEFAULT_DISPLAY;
}
value = analogRead(analogPin);
if (value < 103) value = 103;
if (value > 921) value = 921;
value *= 0.00488759;
pressure = (value - offset) * 1.37892995;
if (pressure < pLow)
{
if (!startTimer.isRunning()) {
startTimer.resetTimerValue();
startTimer.start(); // Start the timer
}
else if (startTimer.check())
{
state = true;
digitalWrite(relayPin, HIGH);
}
}
else if (pressure >= pLow)
{
startTimer.stop(); // Stop and reset the timer when myVariable is 1
}
if (pressure > pHigh)
{
if (!stopTimer.isRunning()) {
stopTimer.resetTimerValue();
stopTimer.start(); // Start the timer
}
else if (stopTimer.check())
{
state = false;
digitalWrite(relayPin, LOW);
}
}
else if (pressure <= pHigh)
{
stopTimer.stop(); // Stop and reset the timer when myVariable is 1
}
if (oldPressure != pressure)
{
oldPressure = pressure;
old_step = -1;
}
if (oldState != state)
{
oldState = state;
old_step = -1;
}
if (step > 9)
{
old_step = -1;
}
if (step != old_step)
{
old_step = step;
switch (step)
{
case DEFAULT_DISPLAY:
lcd.clear();
lcd.print("Pressure=");
lcd.print(pressure);
lcd.print("bar");
lcd.setCursor(0, 1);
lcd.print("Pump ");
lcd.print(state ? "running" : "stopped");
lcd.noBlink();
break;
case DISPLAY_PSTART:
lcd.clear();
lcd.print("Start Pressure :");
lcd.setCursor(0, 1);
lcd.print(pLow);
lcd.print(" bar");
lcd.noBlink();
break;
case DISPLAY_PSTOP:
lcd.clear();
lcd.print("Stop Pressure :");
lcd.setCursor(0, 1);
lcd.print(pHigh);
lcd.print(" bar");
lcd.noBlink();
break;
case DISPLAY_TSTART:
lcd.clear();
lcd.print("Start Delay :");
lcd.setCursor(0, 1);
if (tStart < 10) lcd.print(" ");
lcd.print(tStart);
lcd.print(" sec");
lcd.noBlink();
break;
case DISPLAY_TSTOP:
lcd.clear();
lcd.print("Stop Delay :");
lcd.setCursor(0, 1);
if (tStop < 10) lcd.print(" ");
lcd.print(tStop);
lcd.print(" sec");
lcd.noBlink();
break;
default:
break;
}
}
}