Index: firmware/App/Modes/ModeHeatDisinfect.c =================================================================== diff -u -ra8d919375cdb830f52e82e2d1c72c8153f5f58ca -r73796a0e50450e4958407c4ce42337e257277faa --- firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision a8d919375cdb830f52e82e2d1c72c8153f5f58ca) +++ firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 73796a0e50450e4958407c4ce42337e257277faa) @@ -49,10 +49,10 @@ // Drain R1 & R2 states defines #define DRAIN_PUMP_TARGET_RPM 1800 ///< Drain pump target RPM during drain. #define RSRVRS_INITIAL_DRAIN_TIME_OUT_MS ( 60 * MS_PER_SECOND ) ///< Reservoirs 1 & 2 initial drain time out in milliseconds. -#define DRAIN_WEIGHT_UNCHANGE_TIMEOUT ( 2 * MS_PER_SECOND ) ///< Time period of unchanged weight during draining before timeout. +#define DRAIN_WEIGHT_UNCHANGE_TIMEOUT ( 6 * MS_PER_SECOND ) ///< Time period of unchanged weight during draining before timeout. // Flush drain path state defines -#define FLUSH_DRAIN_WAIT_TIME_MS ( 1 * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. TODo original time was 60 seconds +#define FLUSH_DRAIN_WAIT_TIME_MS ( 3 * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. TODo original time was 60 seconds #define MIN_INLET_TEMPERATURE_C 15.0 ///< Minimum water inlet temperature in C. TODO original temperature was 25 C #define MIN_INLET_CONDUCTIVITY_US_PER_CM 0.0 ///< Minimum water inlet conductivity in uS/cm #define MAX_INLET_CONDUCTIVITY_US_PER_CM 2000.0 ///< Maximum water inlet conductivity in us/cm @@ -61,7 +61,7 @@ #define RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM 0.8 ///< RO pump target flow rate during flush/fill in L/min. TODO original flow was 0.8 #define MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI 130 ///< Maximum RO pump pressure during flush/fill states in psi. #define FLUSH_CICRCULATION_WAIT_TIME_MS ( 1 * MS_PER_SECOND ) ///< Flush/rinse circulation path wait time in milliseconds. TODO original time was 30 seconds -#define MAX_FLUSH_CIRC_TEMP_SENSOR_DIFF_C 3.0 ///< Maximum flush circulation temperature difference tolerance in C. +#define MAX_FLUSH_CIRC_TEMP_SENSOR_DIFF_C 30.0 ///< Maximum flush circulation temperature difference tolerance in C. TODO original difference was 3.0 degrees #define NUM_OF_TEMP_SENSORS_TO_AVG 4.0 ///< Number of temperature sensors to average to check the difference. // Flush and drain R1 and R2 @@ -72,16 +72,16 @@ #define RSRVRS_DRAIN_TIMEOUT_MS ( 2 * 60 * MS_PER_SECOND ) ///< Reservoirs 1 & 2 drain timeout in ms. // Fill and heat water -#define HEAT_DISINFECT_TARGET_TEMPERATURE_C 60.0 ///< Heat disinfect target water temperature in C. TODO original temperature was 85.0 -#define HEAT_DISINFECT_START_TEMPERATURE_C 58.0 ///< Heat disinfect minimum acceptable temperature in C. TODO original temperature was 81.0 +#define HEAT_DISINFECT_TARGET_TEMPERATURE_C 85.0 ///< Heat disinfect target water temperature in C. TODO original temperature was 85.0 +#define HEAT_DISINFECT_START_TEMPERATURE_C 81.0 ///< Heat disinfect minimum acceptable temperature in C. TODO original temperature was 81.0 // R1 to R2 & R2 to R1 heat disinfect circulation -#define HEAT_DISINFECT_TARGET_RO_FLOW_LPM 0.6 ///< Heat disinfect target RO flow rate in L/min. TODO original value was 0.8 +#define HEAT_DISINFECT_TARGET_RO_FLOW_LPM 0.9 ///< Heat disinfect target RO flow rate in L/min. TODO original value was 0.8 #define HEAT_DISINFECT_MAX_RO_PRESSURE_PSI 30 ///< Heat disinfect maximum RO pressure in psi. -#define HEAT_DISINFECT_TARGET_DRAIN_PRES_PSI 1.0 ///< Heat disinfect target drain outlet pressure in psi. +#define HEAT_DISINFECT_TARGET_DRAIN_PRES_PSI 5.0 ///< Heat disinfect target drain outlet pressure in psi. #define HEAT_DISINFECT_TIME_MS ( 3 * 60 * MS_PER_SECOND ) ///< Heat disinfect time for each section in milliseconds. TODO original time was 10 minutes #define HEAT_DISINFECT_START_TEMP_TIMOUT_MS ( 3 * 60 * 60 * MS_PER_SECOND ) ///< Heat disinfect reaching to minimum temperature timeout in milliseconds. TODO figure out this timeout -#define RSRVRS_TARGET_VOL_OUT_TIMEOUT_MS ( 2 * 60 * MS_PER_SECOND ) ///< Reservoirs 1 & 2 maximum volume out of range timeout during heat disnfect. +#define RSRVRS_TARGET_VOL_OUT_TIMEOUT_MS ( 0.5 * 60 * MS_PER_SECOND ) ///< Reservoirs 1 & 2 maximum volume out of range timeout during heat disnfect. #define RSRVRS_MAX_TARGET_VOL_CHANGE_ML 100.0 ///< Reservoirs 1 & 2 maximum allowed volume change when full during heat disinfect. #define POST_HEAT_DISINFECT_WAIT_TIME_MS ( 1 * 60 * MS_PER_SECOND ) ///< Heat disinfect final wait time before flushing the system in milliseconds. @@ -130,12 +130,10 @@ static BOOL areTempSensorsInRange = FALSE; ///< Heat disinfect temperature sensors in/out range flag. /// Boolean flag to check whether draining R1 and R2 is at the end of the heat disinfect cycle or in the beginning. So the drain states can be reused. static BOOL isThisLastDrain = FALSE; -static BOOL isR1Full = FALSE; ///< Reservoir 1 full/empty flag. TODO REMOVE -static BOOL isR2Full = FALSE; ///< Reservoir 2 full/empty flag. TODO REMOVE static RESERVOIRS_STATUS_T rsrvr1Status = RESERVOIR_STATUS_UNKNOWN; ///< Reservoir 1 status. static RESERVOIRS_STATUS_T rsrvr2Status = RESERVOIR_STATUS_UNKNOWN; ///< Reservoir 2 status. -static U32 R1HeatDisinfectVol = 0; ///< Reservoir 1 full volume during heat disinfect. -static U32 R2HeatDisinfectVol = 0; ///< Reservoir 2 full volume during heat disinfect. +static F32 R1HeatDisinfectVol = 0.0; ///< Reservoir 1 full volume during heat disinfect. +static F32 R2HeatDisinfectVol = 0.0; ///< Reservoir 2 full volume during heat disinfect. static U32 heatDisinfectTimer = 0; ///< Heat disinfect timer. static BOOL hasHeatDisinfectStarted = FALSE; ///< Heat disinfect start/not start flag. static U32 rsrvrsVolMonitorTimer = 0; ///< Reservoir 1 & 2 volume monitor timers during heat disinfect. @@ -170,8 +168,8 @@ static void resetActuators( void ); static void setModeToFailed( DG_HEAT_DISINFECT_STATE_T state ); -static BOOL isRsrvrFull( DG_RESERVOIR_ID_T r, F32 targetVol, U32 timeout, DG_HEAT_DISINFECT_STATE_T cancellationState ); -static BOOL isRsrvrEmpty( DG_RESERVOIR_ID_T r, U32 drainSteadyStateTimeout, U32 timeout, DG_HEAT_DISINFECT_STATE_T cancellationState ); +static RESERVOIRS_STATUS_T getRsrvrFillStatus( DG_RESERVOIR_ID_T r, F32 targetVol, U32 timeout, DG_HEAT_DISINFECT_STATE_T cancellationState ); +static RESERVOIRS_STATUS_T getRsrvrDrainStatus( DG_RESERVOIR_ID_T r, U32 drainSteadyStateTimeout, U32 timeout, DG_HEAT_DISINFECT_STATE_T cancellationState ); static HEAT_DISINFECT_STATUS_T getHeatDisinfectStatus( void ); static void publishHeatDisinfectData( void ); @@ -196,8 +194,8 @@ areTempSensorsInRange = FALSE; rsrvr1Status = RESERVOIR_STATUS_UNKNOWN; rsrvr2Status = RESERVOIR_STATUS_UNKNOWN; - R1HeatDisinfectVol = 0; - R2HeatDisinfectVol = 0; + R1HeatDisinfectVol = 0.0; + R2HeatDisinfectVol = 0.0; hasPostHeatDisinfectWaitStarted = FALSE; overallHeatDisinfectTimer = 0; cancellationMode = CANCELLATION_MODE_NONE; @@ -403,7 +401,10 @@ // Set the actuators to drain R1 setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); - stateTimer = getMSTimerCount(); + + // Assume reservoir 1 is full and drain it + rsrvr1Status = RESERVOIR_STATUS_FULL; + stateTimer = getMSTimerCount(); } return state; @@ -413,18 +414,21 @@ * @brief * The handleHeatDisinfectDrainR1State function handles the heat disinfect * drain R1 state. - * @details Inputs: stateTimer, isR1Full, isThisLastDrain - * @details Outputs: stateTimer, isR1Full + * @details Inputs: stateTimer, rsrvr1Status, rsrvr2Status, isThisLastDrain + * @details Outputs: stateTimer, rsrvr1Status, rsrvr2Status * @return next state of the heat disinfect state machine *************************************************************************/ static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectDrainR1State( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_DRAIN_R1; - if ( isRsrvrEmpty( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS, DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH ) ) + if ( rsrvr1Status == RESERVOIR_STATUS_FULL ) { - isR1Full = FALSE; - + rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS, + DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH ); + } + else if ( rsrvr1Status == RESERVOIR_STATUS_EMPTY ) + { if ( isThisLastDrain ) { // Done with draining @@ -448,6 +452,8 @@ } else { + // Assume reservoir 2 is full and drain it + rsrvr2Status = RESERVOIR_STATUS_FULL; // Set the actuators to drain R2. // Request a tare for reservoir 2 tareReservoir(); @@ -467,28 +473,32 @@ * @brief * The handleHeatDisinfectDrainR2State function handles the heat disinfect * drain R2 state. - * @details Inputs: stateTimer, isR2Full, isThisLastDrain - * @details Outputs: stateTimer, isR2Full + * @details Inputs: stateTimer, rsrvr2Status, isThisLastDrain + * @details Outputs: stateTimer, rsrvr2Status * @return next state of the heat disinfect state machine *************************************************************************/ static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectDrainR2State( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_DRAIN_R2; - if ( isRsrvrEmpty( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS, DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH ) ) + if ( rsrvr2Status == RESERVOIR_STATUS_FULL ) { - isR2Full = FALSE; - + rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS, + DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH ); + } + else if ( rsrvr2Status == RESERVOIR_STATUS_EMPTY ) + { if ( isThisLastDrain ) { setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); + rsrvr1Status = RESERVOIR_STATUS_FULL; state = DG_HEAT_DISINFECT_STATE_DRAIN_R1; } else { - stateTrialCounter = 0; signalDrainPumpHardStop(); setValveState( VPI, VALVE_STATE_OPEN ); + stateTrialCounter = 0; stateTimer = getMSTimerCount(); state = DG_HEAT_DISINFECT_STATE_FLUSH_DRAIN; } @@ -553,7 +563,6 @@ // Check if the flush circulation time has elapsed and the temperature sensors are not in range yet if ( didTimeout( stateTimer, FLUSH_CICRCULATION_WAIT_TIME_MS ) && FALSE == areTempSensorsInRange ) { - F32 ThdTemp = getTemperatureValue( TEMPSENSORS_OUTLET_REDUNDANT ); // TODO add TPm later. This is the new temp sensor of the coldest spot. It is temporarily TDi. F32 TPoTemp = getTemperatureValue( TEMPSENSORS_OUTLET_PRIMARY_HEATER ); F32 TD1Temp = getTemperatureValue( TEMPSENSORS_CONDUCTIVITY_SENSOR_1 ); @@ -595,8 +604,9 @@ //if ( didTimeout( stateTimer, FLUSH_CICRCULATION_WAIT_TIME_MS ) ) if ( TRUE ) { - isR1Full = FALSE; - isR2Full = FALSE; + rsrvr1Status = RESERVOIR_STATUS_EMPTY; + rsrvr2Status = RESERVOIR_STATUS_EMPTY; + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); @@ -621,17 +631,18 @@ DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_FLUSH_R1_AND_R2; // If R1 is not full, keep monitoring for R1 level and timeout - if ( isR1Full != TRUE ) + if ( rsrvr1Status == RESERVOIR_STATUS_EMPTY ) { - isR1Full = isRsrvrFull( DG_RESERVOIR_1, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS, DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ); + rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_1, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS, DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ); } // Once R1 is full, keep monitoring for R2 level and timeout - if( isR1Full ) + else if( rsrvr1Status == RESERVOIR_STATUS_FULL ) { - isR2Full = isRsrvrFull( DG_RESERVOIR_2, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_500ML_FILL_UP_TIMEOUT_MS, DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ); + rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_500ML_FILL_UP_TIMEOUT_MS, + DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ); // Once R2 is full (to 500mL in this case), transition to the next state - if ( isR2Full ) + if ( rsrvr2Status == RESERVOIR_STATUS_FULL ) { // Set the actuators to flush R2 and drain R1 state setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); @@ -640,9 +651,10 @@ setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); stateTimer = getMSTimerCount(); - // Set both reservoirs to full status to FALSE - isR2Full = FALSE; - isR1Full = FALSE; + + // Set both reservoirs status + rsrvr1Status = RESERVOIR_STATUS_FULL; + rsrvr2Status = RESERVOIR_STATUS_EMPTY; state = DG_HEAT_DISINFECT_STATE_FLUSH_R2_AND_DRAIN_R1; } } @@ -663,25 +675,30 @@ DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_FLUSH_R2_AND_DRAIN_R1; // If reservoir 1 is empty, turn off the drain pump - if ( isRsrvrEmpty( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS, DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ) ) + if ( rsrvr1Status == RESERVOIR_STATUS_FULL ) { - isR1Full = FALSE; + rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS, + DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ); + } + else if ( rsrvr1Status == RESERVOIR_STATUS_EMPTY ) + { // Done with draining R1 signalDrainPumpHardStop(); } // First reservoir 2 must be completely full - if ( isR2Full != TRUE ) + if ( rsrvr2Status == RESERVOIR_STATUS_EMPTY ) { - isR2Full = isRsrvrFull( DG_RESERVOIR_2, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS, DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ); + rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS, DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ); } // Once R2 is full, R1 must be partially full - if( isR2Full ) + else if( rsrvr2Status == RESERVOIR_STATUS_FULL ) { - isR1Full = isRsrvrFull( DG_RESERVOIR_1, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_500ML_FILL_UP_TIMEOUT_MS, DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ); + rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_1, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_500ML_FILL_UP_TIMEOUT_MS, + DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ); // Once R1 is partially full, transition to the next state - if ( isR1Full ) + if ( rsrvr1Status == RESERVOIR_STATUS_FULL ) { // Done with filing turn off the RO pump signalROPumpHardStop(); @@ -695,6 +712,7 @@ setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); // Start the timer for drain timeout stateTimer = getMSTimerCount(); + rsrvr2Status = RESERVOIR_STATUS_FULL; state = DG_HEAT_DISINFECT_STATE_FLUSH_DRAIN_R2; } } @@ -715,11 +733,17 @@ DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_FLUSH_DRAIN_R2; // If reservoir 2 is empty, set the drain valve to drain R1 - if ( isRsrvrEmpty( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS, DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ) ) + if ( rsrvr2Status == RESERVOIR_STATUS_FULL ) { + rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS, + DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ); + } + else if ( rsrvr2Status == RESERVOIR_STATUS_EMPTY ) + { setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); // Start the timer for drain timeout stateTimer = getMSTimerCount(); + rsrvr1Status = RESERVOIR_STATUS_FULL; state = DG_HEAT_DISINFECT_STATE_FLUSH_DRAIN_R1; } @@ -739,8 +763,13 @@ DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_FLUSH_DRAIN_R1; // If reservoir 1 is empty, set the state to fill water state - if ( isRsrvrEmpty( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS, DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ) ) + if ( rsrvr1Status == RESERVOIR_STATUS_FULL ) { + rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS, + DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ); + } + else if ( rsrvr1Status == RESERVOIR_STATUS_EMPTY ) + { // Done with draining the reservoirs signalDrainPumpHardStop(); @@ -780,17 +809,18 @@ DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_FILL_WITH_WATER; // First reservoir 1 must be full - if ( isRsrvrFull( DG_RESERVOIR_1, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS, DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ) ) + if ( rsrvr1Status == RESERVOIR_STATUS_EMPTY ) { - isR1Full = TRUE; + rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_1, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS, DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ); } // Once reservoir 1 is full, check the status of reservoir 2 since the water overflows to reservoir 2 - if ( isR1Full ) + else if ( rsrvr1Status == RESERVOIR_STATUS_FULL ) { - isR2Full = isRsrvrFull( DG_RESERVOIR_2, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_500ML_FILL_UP_TIMEOUT_MS, DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ); + rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_500ML_FILL_UP_TIMEOUT_MS, + DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ); // Once reservoir 2 is full, set the actuators for recirculation - if ( isR2Full ) + if ( rsrvr2Status == RESERVOIR_STATUS_FULL ) { // Set the valves to drain R2 and no fill setValveState( VPI, VALVE_STATE_CLOSED ); @@ -854,7 +884,7 @@ setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); - + rsrvr2Status = RESERVOIR_STATUS_EMPTY; stateTimer = getMSTimerCount(); state = DG_HEAT_DISINFECT_STATE_FILL_R2_WITH_HOT_WATER; break; @@ -880,7 +910,9 @@ BOOL isR1PartiallyFull = fabs( getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ) - RSRVRS_PARTIAL_FILL_VOL_ML ) < RSRVRS_MAX_TARGET_VOL_CHANGE_ML; - if ( isRsrvrFull( DG_RESERVOIR_2, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS, DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ) && isR1PartiallyFull ) + rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS, DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ); + + if ( rsrvr2Status == RESERVOIR_STATUS_FULL && isR1PartiallyFull ) { // Get the current volumes to be monitored during R2 to R1 heat disinfect state R1HeatDisinfectVol = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); @@ -918,7 +950,7 @@ if ( hasPostHeatDisinfectWaitStarted != TRUE ) { // Turn off the pumps and heaters - //TODO turn off CP1 and CP2 + // TODO turn off CP1 and CP2 stopPrimaryHeater(); stopTrimmerHeater(); @@ -946,8 +978,11 @@ // Turn on the drain pump to drain the reservoirs in open loop mode setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); + rsrvr1Status = RESERVOIR_STATUS_FULL; stateTimer = getMSTimerCount(); hasPostHeatDisinfectWaitStarted = FALSE; + R1HeatDisinfectVol = 0; + R2HeatDisinfectVol = 0; state = DG_HEAT_DISINFECT_STATE_MIX_DRAIN_R1; } break; @@ -968,13 +1003,17 @@ { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_MIX_DRAIN_R1; - if ( isRsrvrEmpty( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS, DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ) ) + if ( rsrvr1Status == RESERVOIR_STATUS_FULL ) { - isR1Full = FALSE; - + rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS, + DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ); + } + else if ( rsrvr1Status == RESERVOIR_STATUS_EMPTY ) + { // Set the drain valve to reservoir 2 setValveState( VRD, VALVE_STATE_R2_C_TO_NO ); + rsrvr2Status = RESERVOIR_STATUS_FULL; stateTimer = getMSTimerCount(); state = DG_HEAT_DISINFECT_STATE_MIX_DRAIN_R2; } @@ -994,10 +1033,13 @@ { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_MIX_DRAIN_R2; - if ( isRsrvrEmpty( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS, DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ) ) + if ( rsrvr2Status == RESERVOIR_STATUS_FULL ) { - isR2Full = FALSE; - + rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS, + DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ); + } + else if ( rsrvr2Status == RESERVOIR_STATUS_EMPTY ) + { // Done with draining the reservoirs signalDrainPumpHardStop(); @@ -1035,9 +1077,9 @@ setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); setROPumpTargetFlowRate( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); - // Set both reservoirs status to FLASE - isR1Full = FALSE; - isR2Full = FALSE; + + rsrvr1Status = RESERVOIR_STATUS_EMPTY; + rsrvr2Status = RESERVOIR_STATUS_EMPTY; stateTimer = getMSTimerCount(); state = DG_HEAT_DISINFECT_STATE_RINSE_R1_TO_R2; @@ -1058,15 +1100,16 @@ { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_RINSE_R1_TO_R2; - if ( isR1Full != TRUE ) + if ( rsrvr1Status == RESERVOIR_STATUS_EMPTY ) { - isR1Full = isRsrvrFull( DG_RESERVOIR_1, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS, DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ); + rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_1, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS, DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ); } - if ( isR1Full ) + else if ( rsrvr1Status == RESERVOIR_STATUS_FULL ) { - isR2Full = isRsrvrFull( DG_RESERVOIR_2, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_500ML_FILL_UP_TIMEOUT_MS, DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ); + rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_500ML_FILL_UP_TIMEOUT_MS, + DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ); - if ( isR2Full ) + if ( rsrvr2Status == RESERVOIR_STATUS_FULL ) { // Set the valves to rinse R2 to R1 and drain R1 setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); @@ -1075,9 +1118,8 @@ setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); - // Set both reservoirs status to FLASE - isR1Full = FALSE; - isR2Full = FALSE; + rsrvr1Status = RESERVOIR_STATUS_FULL; + rsrvr2Status = RESERVOIR_STATUS_EMPTY; stateTimer = getMSTimerCount(); state = DG_HEAT_DISINFECT_STATE_RINSE_R2_TO_R1_AND_DRAIN_R1; } @@ -1098,23 +1140,29 @@ { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_RINSE_R2_TO_R1_AND_DRAIN_R1; - if ( isRsrvrEmpty( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS, DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ) ) + if ( rsrvr1Status == RESERVOIR_STATUS_FULL ) { + rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS, + DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ); + } + else if ( rsrvr1Status == RESERVOIR_STATUS_EMPTY ) + { // Done with draining R1 signalDrainPumpHardStop(); } // First reservoir 2 must be completely full - if ( isR2Full != TRUE ) + if ( rsrvr2Status == RESERVOIR_STATUS_EMPTY ) { - isR2Full = isRsrvrFull( DG_RESERVOIR_2, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS, DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ); + rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS, DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ); } // Once reservoir 2 is completely full, monitor reservoir 1 - if ( isR2Full ) + else if ( rsrvr2Status == RESERVOIR_STATUS_FULL ) { - isR1Full = isRsrvrFull( DG_RESERVOIR_1, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_500ML_FILL_UP_TIMEOUT_MS, DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ); + rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_1, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_500ML_FILL_UP_TIMEOUT_MS, + DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ); - if ( isR1Full ) + if ( rsrvr1Status == RESERVOIR_STATUS_FULL ) { // Done with filling, turn off the RO pump signalROPumpHardStop(); @@ -1210,19 +1258,18 @@ // The two sensors must be less than a threshold to decide if mix drain is needed to normal drain if ( TDi < MIX_DRAIN_TEMPERATURE_THRESHOLD_C && TRo < MIX_DRAIN_TEMPERATURE_THRESHOLD_C ) { - // Set the reservoirs status to FALSE - isR1Full = TRUE; - isR2Full = TRUE; + rsrvr1Status = RESERVOIR_STATUS_FULL; + rsrvr2Status = RESERVOIR_STATUS_FULL; cancellationMode = CANCELLATION_MODE_COLD; } else { - // Set the reservoirs status to FALSE - isR1Full = TRUE; - isR2Full = TRUE; // The fluid is hot so this is a mix drain. Set the VPd to direct the cold inlet fluid to drain setValveState( VPI, VALVE_STATE_OPEN ); setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NC ); + + rsrvr1Status = RESERVOIR_STATUS_FULL; + rsrvr2Status = RESERVOIR_STATUS_FULL; cancellationMode = CANCELLATION_MODE_HOT; } @@ -1235,19 +1282,24 @@ } // If reservoir 2 is empty, set to drain reservoir 1 - if ( isRsrvrEmpty( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS, state ) ) + if ( rsrvr2Status == RESERVOIR_STATUS_FULL ) { - // Set the drain valve to reservoir 1 - setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); - isR2Full = FALSE; + rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS, state ); + + if ( rsrvr2Status == RESERVOIR_STATUS_EMPTY ) + { + // Set the drain valve to reservoir 1 + setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); + } } // If reservoir 2 has already been drained and reservoir 1 is empty, reset and switch to complete - if ( ( isR2Full != TRUE ) && ( isR1Full == TRUE ) ) + if ( ( rsrvr2Status == RESERVOIR_STATUS_EMPTY ) && ( rsrvr1Status == RESERVOIR_STATUS_FULL ) ) { - if ( isRsrvrEmpty( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS, state ) ) + rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS, state ); + + if ( rsrvr1Status == RESERVOIR_STATUS_EMPTY ) { - isR1Full = FALSE; // Done with heat disinfect mode state = DG_HEAT_DISINFECT_STATE_COMPLETE; @@ -1322,9 +1374,9 @@ * the operation timed out. * @return none *************************************************************************/ -static BOOL isRsrvrFull( DG_RESERVOIR_ID_T r, F32 targetVol, U32 timeout, DG_HEAT_DISINFECT_STATE_T cancellationState ) +static RESERVOIRS_STATUS_T getRsrvrFillStatus( DG_RESERVOIR_ID_T r, F32 targetVol, U32 timeout, DG_HEAT_DISINFECT_STATE_T cancellationState ) { - BOOL rsrvrStatus = FALSE; + RESERVOIRS_STATUS_T status = RESERVOIR_STATUS_EMPTY; F32 volume = 0.0; if ( r == DG_RESERVOIR_1 ) @@ -1339,7 +1391,7 @@ // Check the volume of the reservoir against the target volume if ( volume >= targetVol ) { - rsrvrStatus = TRUE; + status = RESERVOIR_STATUS_FULL; // Set the state timer in case it needs to be used for another timeout check stateTimer = getMSTimerCount(); } @@ -1348,42 +1400,43 @@ // Failed to fill ontime. Update the previous heat disinfect state and transition to basic cancellation prevHeatDisinfectState = heatDisinfectState; heatDisinfectState = cancellationState; + status = RESERVOIR_STATUS_UNKNOWN; } - return rsrvrStatus; + return status; } /*********************************************************************//** * @brief - * The isRsrvrEmpty function checks whether the target reservoir is empty - * or not. If the fill times out, it sets the state machine to complete and - * exits the heat disinfect mode. - * @details Inputs: none - * @details Outputs: none - * @param r is R1 or R2 + * The getRsrvrDrainStatus function returns the status of + * @details Inputs: stateTimer, prevHeatDisinfectState, heatDisinfectState + * @details Outputs: stateTimer, heatDisinfectState + * @param r is DG_RESERVOIR_1 or DG_RESERVOIR_2 * @param cancellationState is the cancellation state to be called in case * the operation timed out. - * @return none + * @return TRUE if the reservoir is empty otherwise, FALSE *************************************************************************/ -static BOOL isRsrvrEmpty( DG_RESERVOIR_ID_T r, U32 drainSteadyStateTimeout, U32 timeout, DG_HEAT_DISINFECT_STATE_T cancellationState ) +static RESERVOIRS_STATUS_T getRsrvrDrainStatus( DG_RESERVOIR_ID_T r, U32 drainSteadyStateTimeout, U32 timeout, DG_HEAT_DISINFECT_STATE_T cancellationState ) { - BOOL isDrainComplete = FALSE; + RESERVOIRS_STATUS_T status = RESERVOIR_STATUS_FULL; - isDrainComplete = hasTargetDrainVolumeBeenReached( r, drainSteadyStateTimeout ); + BOOL isDrainComplete = hasTargetDrainVolumeBeenReached( r, drainSteadyStateTimeout ); if ( TRUE == isDrainComplete ) { // Set the state timer in case it needs to be used for another timeout check stateTimer = getMSTimerCount(); + status = RESERVOIR_STATUS_EMPTY; } else if ( didTimeout( stateTimer, RSRVRS_DRAIN_TIMEOUT_MS ) ) { // Failed to drain ontime. Update the previous heat disinfect state and transition to basic cancellation prevHeatDisinfectState = heatDisinfectState; heatDisinfectState = cancellationState; + status = RESERVOIR_STATUS_UNKNOWN; } - return isDrainComplete; + return status; } /*********************************************************************//** @@ -1480,7 +1533,8 @@ data.overallElapsedTime = calcTimeSince( overallHeatDisinfectTimer ); data.stateElapsedTime = calcTimeSince( stateTimer ); data.cancellationMode = (U32)cancellationMode; - + data.R1FillLevel = R1HeatDisinfectVol; + data.R2FillLevel = R2HeatDisinfectVol; // If the mode is in the actual heat disinfect states, publish the elapsed time, otherwise publish 0 to avoid confusion if ( heatDisinfectState == DG_HEAT_DISINFECT_STATE_DISINFECT_R1_TO_R2 || heatDisinfectState == DG_HEAT_DISINFECT_STATE_DISINFECT_R2_TO_R1 ) {