TKK_E32222388/WaterBankHandler.h

312 lines
13 KiB
C

//Water Bank => Tank 3, used for unsterilized water storage
// -> Handle the Refill Water Bank Pump
// -> Dependency: water bank's float switch Low and High
//STERILIZATION Bank => Tank 2, used for sterilizing the water
//PURED Bank => Tank 3, used for store sterilized water
#define WATER_BANK_STATE_NONE 0
#define WATER_BANK_STATE_IDLE 1
#define WATER_BANK_STATE_START_FILLING 2
#define WATER_BANK_STATE_CHECK_FILLING_TO_LOWER 3
#define WATER_BANK_STATE_CHECK_FILLING_TO_UPPER 4
uint32_t waterBankExpectedTimeToFilledLower = 1*60*1000;//in mulliseconds
uint32_t waterBankExpectedTimeToFilledUpper = 3*60*1000;//in mulliseconds
uint32_t waterBankTick = 0;
bool waterBankSterilizationFloatSwitchStatePrevious = false;
bool waterBankSterilizationFloatSwitchStateCurrent = false;
bool waterBankSterilizedFloatSwitchStatePrevious = false;
bool waterBankSterilizedFloatSwitchStateCurrent = false;
bool waterBankFloatSwitchStatePrevious = false;
bool waterBankFloatSwitchStateCurrent = false;
bool waterBankSterilizationUpperFloatSwitchStatePrevious = false;
bool waterBankSterilizationUpperFloatSwitchStateCurrent = false;
//bool waterBankSystemIsRunning = false;//if true, water bank is starting once
//bool waterBankSystemIsAutomatic = false; //if true, it will keep check float switch for water refill
int waterBankState = WATER_BANK_STATE_NONE;
bool waterBankAutomatic = false;
#define WATER_BANK_ERROR_NONE 0
#define WATER_BANK_ERROR_LOWER_FLOAT_SWITCH 1 //lower switch error
#define WATER_BANK_ERROR_UPPER_FLOAT_SWITCH 2 //upper switch error
#define WATER_BANK_ERROR_UPPER_FLOAT_SWITCH_OR_NO_WATER 3
#define WATER_BANK_ERROR_LOWER_FLOAT_SWITCH_OR_NO_WATER 4
bool waterBankError = false;
byte waterBankErrorCode = WATER_BANK_ERROR_NONE;
String waterBankErrorString = "";
bool IsWaterBankError(){
return waterBankError;
}
String WaterBankErrorString(){
if (waterBankError) return waterBankErrorString;
return "";
}
bool IsWaterBankSystemRunning(){
if (!waterBankAutomatic) return (waterBankState!=WATER_BANK_STATE_NONE);
return (waterBankState>WATER_BANK_STATE_IDLE);
}
void ClearWaterBankError(){
waterBankError = false;
waterBankErrorCode = WATER_BANK_ERROR_NONE;
waterBankErrorString = "";
}
//system running state =====================================================
void WaterBankSystemRoutine(){
switch(waterBankState){
case WATER_BANK_STATE_NONE:{
//do nothing but make sure the pump is off
if (GetSwitchState(WATER_BANK_FILL_PUMP_SWITCH)){
Serial.println("WaterBank: TURN OFF PUMP SWITCH");
SetSwitchState(WATER_BANK_FILL_PUMP_SWITCH, false);
}
};
break;
case WATER_BANK_STATE_IDLE:{
if (waterBankAutomatic){
//make sure the pump is off first
if (GetSwitchState(WATER_BANK_FILL_PUMP_SWITCH)){
Serial.println("WaterBank: TURN OFF PUMP SWITCH");
SetSwitchState(WATER_BANK_FILL_PUMP_SWITCH, false);
}
//trigger condition:
// state => WATER_BANK_STATE_CHECK_IF_EMPTY: sterilization bank is empty or sterilized bank is empty or water bank is empty
waterBankFloatSwitchStateCurrent = GetInSwitchState(WATER_BANK_FLOAT_SWITCH_LOWER);
waterBankSterilizationFloatSwitchStateCurrent = GetInSwitchState(STERILIZATION_CHAMBER_FLOAT_SWITCH_LOWER);
waterBankSterilizedFloatSwitchStateCurrent = GetInSwitchState(STERILIZED_CHAMBER_FLOAT_SWITCH_LOWER);
waterBankSterilizationUpperFloatSwitchStateCurrent = GetInSwitchState(STERILIZATION_CHAMBER_FLOAT_SWITCH_UPPER);
bool intoFillingWaterBank = false;
//check if water bank empty
if ((waterBankFloatSwitchStateCurrent!=waterBankFloatSwitchStatePrevious) && (!waterBankFloatSwitchStatePrevious)){
intoFillingWaterBank = true;
Serial.println("WaterBank -> Trigger reason: Water Bank empty");
}
//check if sterilization chamber empty
if ((waterBankSterilizationFloatSwitchStateCurrent!=waterBankSterilizationFloatSwitchStatePrevious) && (!waterBankSterilizationFloatSwitchStateCurrent)){
intoFillingWaterBank = true;
Serial.println("WaterBank -> Trigger reason: Sterilization chamber empty");
}
//check if sterilized chamber empty
if ((waterBankSterilizedFloatSwitchStateCurrent!=waterBankSterilizedFloatSwitchStatePrevious) && (!waterBankSterilizedFloatSwitchStatePrevious)){
intoFillingWaterBank = true;
Serial.println("WaterBank -> Trigger reason: Sterilized chamber empty");
}
//check if sterilization chamber just full lower switch 1, and upper switch from 1 to 0 (indicate begin to unload)
if (waterBankSterilizationFloatSwitchStateCurrent && (waterBankSterilizationUpperFloatSwitchStateCurrent!=waterBankSterilizationUpperFloatSwitchStatePrevious) && (!waterBankSterilizationUpperFloatSwitchStateCurrent)){
intoFillingWaterBank = true;
Serial.println("WaterBank -> Trigger reason: Sterilized chamber unload");
}
//update state
waterBankFloatSwitchStatePrevious = waterBankFloatSwitchStateCurrent;
waterBankSterilizationFloatSwitchStatePrevious = waterBankSterilizationFloatSwitchStateCurrent;
waterBankSterilizedFloatSwitchStatePrevious = waterBankSterilizedFloatSwitchStateCurrent;
waterBankSterilizationUpperFloatSwitchStatePrevious = waterBankSterilizationUpperFloatSwitchStateCurrent;
if (intoFillingWaterBank){
ClearWaterBankError();
waterBankState = WATER_BANK_STATE_START_FILLING;
Serial.println("WaterBank -> WATER_BANK_STATE_START_FILLING");
}
}else{
waterBankState = WATER_BANK_STATE_NONE;
Serial.println("WaterBank -> WATER_BANK_STATE_NONE");
}
};
break;
case WATER_BANK_STATE_START_FILLING:{
//call to this state to check if water is fully empty or lower level is filled
bool lowerSwitchState = GetInSwitchState(WATER_BANK_FLOAT_SWITCH_LOWER);
bool upperSwitchState = GetInSwitchState(WATER_BANK_FLOAT_SWITCH_UPPER);
if (lowerSwitchState && (!upperSwitchState)){
//try to fill till full
ClearWaterBankError();
waterBankTick = millis();
waterBankState = WATER_BANK_STATE_CHECK_FILLING_TO_UPPER;
Serial.println("WaterBank -> WATER_BANK_STATE_CHECK_FILLING_TO_UPPER");
}else if ((!lowerSwitchState) && (!upperSwitchState)){
//try to fill to lower first
ClearWaterBankError();
waterBankTick = millis();
waterBankState = WATER_BANK_STATE_CHECK_FILLING_TO_LOWER;
Serial.println("WaterBank -> WATER_BANK_STATE_CHECK_FILLING_TO_LOWER");
}else if (!lowerSwitchState && upperSwitchState){
//float switch error! Cancel the action
waterBankError = true;
waterBankErrorCode = WATER_BANK_ERROR_LOWER_FLOAT_SWITCH;
//waterBankErrorString = "Tank 1 lower float switch error.";
waterBankErrorString = "Tangki 3 float switch bawah error.";
Serial.println("WaterBank Error -> WATER_BANK_ERROR_LOWER_FLOAT_SWITCH");
if (waterBankAutomatic){
waterBankState = WATER_BANK_STATE_IDLE;
Serial.println("WaterBank -> WATER_BANK_STATE_IDLE");
}else{
waterBankState = WATER_BANK_STATE_NONE;
Serial.println("WaterBank -> WATER_BANK_STATE_NONE");
}
}
};
break;
case WATER_BANK_STATE_CHECK_FILLING_TO_LOWER:{
//waiting for filling into lower level, or stop when timeout
//switch on the pump
if (!GetSwitchState(WATER_BANK_FILL_PUMP_SWITCH)){
Serial.println("WaterBank: TURN ON PUMP SWITCH");
SetSwitchState(WATER_BANK_FILL_PUMP_SWITCH, true);
}
bool lowerSwitchState = GetInSwitchState(WATER_BANK_FLOAT_SWITCH_LOWER);
bool upperSwitchState = GetInSwitchState(WATER_BANK_FLOAT_SWITCH_UPPER);
if (lowerSwitchState || upperSwitchState){
//check if lower float switch on
//try to fill till full
ClearWaterBankError();
waterBankTick = millis();
waterBankState = WATER_BANK_STATE_CHECK_FILLING_TO_UPPER;
Serial.println("WaterBank -> WATER_BANK_STATE_CHECK_FILLING_TO_UPPER");
}else{
//check if timed out
if (millis()-waterBankTick>=waterBankExpectedTimeToFilledLower){
//error
waterBankError = true;
waterBankErrorCode = WATER_BANK_ERROR_LOWER_FLOAT_SWITCH_OR_NO_WATER;
//waterBankErrorString = "Tank 1 insufficient input water, or lower float switch error, or input pump error.";
waterBankErrorString = "Tidak ada air untuk mengisi tangki 3, atau float switch error, atau pompa rusak.";
Serial.println("WaterBank Error -> WATER_BANK_ERROR_LOWER_FLOAT_SWITCH");
if (waterBankAutomatic){
waterBankState = WATER_BANK_STATE_IDLE;
Serial.println("WaterBank -> WATER_BANK_STATE_IDLE");
}else{
waterBankState = WATER_BANK_STATE_NONE;
Serial.println("WaterBank -> WATER_BANK_STATE_NONE");
}
}
}
};
break;
case WATER_BANK_STATE_CHECK_FILLING_TO_UPPER:{
//waiting for filling into upper level, or stop when timeout
//switch on the pump
if (!GetSwitchState(WATER_BANK_FILL_PUMP_SWITCH)){
Serial.println("WaterBank: TURN ON PUMP SWITCH");
SetSwitchState(WATER_BANK_FILL_PUMP_SWITCH, true);
}
bool upperSwitchState = GetInSwitchState(WATER_BANK_FLOAT_SWITCH_UPPER);
bool stopFill = false;
if (upperSwitchState){
//check if upper float switch on
ClearWaterBankError();
stopFill = true;
Serial.println("WaterBank -> Full");
}else{
//check if timed out
if (millis()-waterBankTick>=waterBankExpectedTimeToFilledUpper){
//error
stopFill = true;
waterBankError = true;
waterBankErrorCode = WATER_BANK_ERROR_UPPER_FLOAT_SWITCH_OR_NO_WATER;
waterBankErrorString = "Tank 3 insufficient input water, or upper float switch error, or input pump error.";
Serial.println("WaterBank Error -> WATER_BANK_ERROR_UPPER_FLOAT_SWITCH_OR_NO_WATER");
}
}
if (stopFill){
SetSwitchState(WATER_BANK_FILL_PUMP_SWITCH, false); //matiin pompa
if (waterBankAutomatic){
waterBankState = WATER_BANK_STATE_IDLE;
Serial.println("WaterBank -> WATER_BANK_STATE_IDLE");
}else{
waterBankState = WATER_BANK_STATE_NONE;
Serial.println("WaterBank -> WATER_BANK_STATE_NONE");
}
}
};
break;
}
}
void StartWaterBankSystem(bool automatic, bool forceRunIfAutomatic = false){
RefreshInSwitchState();
ClearWaterBankError();
waterBankAutomatic = automatic;
bool runNow = false;
if (waterBankAutomatic){
waterBankState = WATER_BANK_STATE_IDLE;
runNow = forceRunIfAutomatic;
if (!runNow) Serial.println("StartWaterBankSystem -> WATER_BANK_STATE_IDLE");
}else{
runNow = true;
}
if (runNow){
waterBankState = WATER_BANK_STATE_START_FILLING;
Serial.println("StartWaterBankSystem -> WATER_BANK_STATE_START_FILLING");
}
}
void StopWaterBankSystem(){
waterBankState = WATER_BANK_STATE_NONE;
ClearWaterBankError();
WaterBankSystemRoutine(); //call it once to stop the switch
}
//=========================================================================
//Test unit for WaterBankSystemRoutine
bool WaterBankTestUnit(){
bool testA = false;
bool testB = false;
bool testC = false;
bool testD = false;
bool testE = false;
//normal test with automatic mode
ClearInSwitch(); //clear floating switch state
StopWaterBankSystem();
StartWaterBankSystem(true, false);
WaterBankSystemRoutine();
testA = waterBankState==WATER_BANK_STATE_IDLE;
Serial.println("Test idle state " + (String) (testA?"OK":"FAIL"));
//simulate float switching
SetInSwitchState(WATER_BANK_FLOAT_SWITCH_LOWER, true);
WaterBankSystemRoutine();
SetInSwitchState(WATER_BANK_FLOAT_SWITCH_LOWER, false); //simulate trigger to fill water
WaterBankSystemRoutine();
testB = (waterBankState==WATER_BANK_STATE_START_FILLING) || (waterBankState==WATER_BANK_STATE_CHECK_FILLING_TO_LOWER);
Serial.println("Test start filling " + (String) (testB?"OK":"FAIL"));
WaterBankSystemRoutine();
testC = waterBankState==WATER_BANK_STATE_CHECK_FILLING_TO_LOWER;
Serial.println("Test filling to lower " + (String) (testC?"OK":"FAIL"));
//simulate water on lower
SetInSwitchState(WATER_BANK_FLOAT_SWITCH_LOWER, true);
WaterBankSystemRoutine();
testD = waterBankState==WATER_BANK_STATE_CHECK_FILLING_TO_UPPER;
Serial.println("Test filling to upper " + (String) (testD?"OK":"FAIL"));
//simulate tank full
SetInSwitchState(WATER_BANK_FLOAT_SWITCH_UPPER, true);
WaterBankSystemRoutine();
testE = waterBankState==WATER_BANK_STATE_IDLE;
Serial.println("Test filling to full " + (String) (testE?"OK":"FAIL"));
StopWaterBankSystem();
bool passNormalTest = testA && testB && testC && testD && testE;
Serial.println("All Normal Test: " + (String) (passNormalTest?"OK":"FAIL"));
//bool passFloatSwitchErrorTest = false;
//bool passFillLowerTimeoutTest = false;
//bool passFillUpperTimeoutTest = false;
// return passNormalTest;
//cleanup test
ClearInSwitch(); //clear floating switch state
StopWaterBankSystem();
return true;
}
//=========================================================================