//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; } //=========================================================================