312 lines
13 KiB
C
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;
|
|
}
|
|
//=========================================================================
|
|
|