Index: firmware/App/Modes/ModeHeatDisinfect.c =================================================================== diff -u -rfd5c3cff1d0beac03fb29c19f49f670568bc4178 -r263a8e5e9d7314f92def1b5701db2a92cf537542 --- firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision fd5c3cff1d0beac03fb29c19f49f670568bc4178) +++ firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 263a8e5e9d7314f92def1b5701db2a92cf537542) @@ -65,7 +65,7 @@ #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 -#define RSRVRS_FULL_VOL_ML 1800.0 ///< Reservoirs 1 & 2 full volume in mL. TODo original value was 1900 +#define RSRVRS_FULL_VOL_ML 1750.0 ///< Reservoirs 1 & 2 full volume in mL. TODo original value was 1900 #define RSRVRS_PARTIAL_FILL_VOL_ML 500.0 ///< Reservoirs 1 & 2 partial volume in mL. #define RSRVRS_FULL_STABLE_TIME_COUNT ( ( 4 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Reservoirs 1 & 2 full stable time in counts. #define RSRVRS_FILL_UP_TIMEOUT_MS ( 5 * 60 * MS_PER_SECOND ) ///< Reservoirs 1 & 2 full fill up timeout in ms. TODO original value was 5 mins @@ -74,7 +74,7 @@ // Fill and heat water #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 812.0 ///< Heat disinfect minimum acceptable temperature in C. TODO original temperature was 81.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.9 ///< Heat disinfect target RO flow rate in L/min. TODO original value was 0.8 @@ -86,6 +86,11 @@ #define RSRVRS_MAX_TARGET_VOL_CHANGE_ML 500.0 ///< Reservoirs 1 & 2 maximum allowed volume change when full during heat disinfect. TODO original value is 100 mL #define POST_HEAT_DISINFECT_WAIT_TIME_MS ( 3 * 60 * MS_PER_SECOND ) ///< Heat disinfect final wait time before flushing the system in milliseconds. +// Mix drain R1 and R2 +#define RSRVRS_MIX_DRAIN_TIMEOUT_MS ( 20 * 60 * MS_PER_SECOND ) ///< Reservoirs 1 & 2 mix drain timeout in ms. +#define DRAIN_PUMP_START_TIME_IN_MIX_DRAIN_MS ( 5 * MS_PER_SECOND ) ///< Time to start the drain pump at mix drain after directing the flow to drain in ms. +#define DRAIN_PUMP_RPM_IN_MIX_DRAIN 600 ///< The RPM that the drain pump should be run during mix drain. + // Rinse R1 to R2 #define ROF_MIN_LOW_PRESSURE_TEMPERATURE_C 45.0 ///< RO filter minimum temperature that the pressure must be no more than 30psi in C. TODO the actual value is 45.0 @@ -114,12 +119,11 @@ /// Heat disinfect status typedef enum Heat_disinfect_status { - HEAT_DISINFECT_IN_PROGRESS = 0, ///< Heat disinfect in progress. - HEAT_DISINFECT_RSRVRS_LEAK_TIMEOUT, ///< Heat disinfect reservoirs leak timeout. - HEAT_DISINFECT_HEAT_UP_TIMEOUT, ///< Heat disinfect heat up timeout. - HEAT_DISINFECT_POST_WAIT, ///< Heat disinfect post wait time state. - HEAT_DISINFECT_COMPLETE, ///< Heat disinfect complete. - NUM_OF_HEAT_DISINFECT_STATUS ///< Number of heat disinfect status. + HEAT_DISINFECT_IN_PROGRESS = 0, ///< Heat disinfect in progress. + HEAT_DISINFECT_RSRVRS_LEAK_TIMEOUT, ///< Heat disinfect reservoirs leak timeout. + HEAT_DISINFECT_HEAT_UP_TIMEOUT, ///< Heat disinfect heat up timeout. + HEAT_DISINFECT_COMPLETE, ///< Heat disinfect complete. + NUM_OF_HEAT_DISINFECT_STATUS ///< Number of heat disinfect status. } HEAT_DISINFECT_STATUS_T; // ********** private data ********** @@ -137,15 +141,14 @@ 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 isPartialDisinfectInProgress = FALSE; ///< Heat disinfect partial complete/ in progess flag. +static BOOL isPartialDisinfectInProgress = FALSE; ///< Heat disinfect partial complete/in progess flag. static U32 rsrvrsVolMonitorTimer = 0; ///< Reservoir 1 & 2 volume monitor timers during heat disinfect. static BOOL areRsrvrsLeaking = FALSE; ///< Reservoir 1 & 2 leak check flag during heat disinfect. -static BOOL hasPostDisinfectWaitStarted = FALSE; ///< Final delay at the end of heat disinfect and before flush flag. -static U32 heatDisinfectPostTimer = 0; ///< Heat disinfect post wait timer. static U32 dataPublishCounter = 0; ///< Heat Disinfect data publish counter. static CANCELLATION_MODES_T cancellationMode = CANCELLATION_MODE_NONE; ///< Cancellation mode. static U32 rsrvrFillStableTimeCounter = 0; ///< Reservoirs fill stable time counter. static ALARM_ID_T alarm; ///< Heat disinfect alarm to raise. +static BOOL isDrainPumpInMixDrainOn = FALSE; ///< Flag to show the drain pump is on during mix drain. // ********** private function prototypes ********** @@ -162,20 +165,21 @@ static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectDisinfectR1ToR2State( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectFillR2WithHotWaterState( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectDisinfectR2ToR1State( void ); +static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCoolDownHeatersState( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectMixDrainR1State( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectMixDrainR2State( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCoolDownROFilterState( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectRinseR1ToR2State( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectRinseR2ToR1AndDrainR1State( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectRinseCirculationState( void ); -static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCancelModeBasicPath( void ); -static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCancelModeWaterPath( void ); +static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCancelModeBasicPathState( void ); +static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCancelModeWaterPathState( void ); +static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCompleteState( void ); static void resetActuators( void ); static void setModeToFailed( void ); -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 RESERVOIRS_STATUS_T getRsrvrFillStatus( DG_RESERVOIR_ID_T r, F32 targetVol, U32 timeout ); +static RESERVOIRS_STATUS_T getRsrvrDrainStatus( DG_RESERVOIR_ID_T r, U32 drainSteadyStateTimeout, U32 timeout ); static HEAT_DISINFECT_STATUS_T getHeatDisinfectStatus( void ); static void publishHeatDisinfectData( void ); @@ -186,9 +190,9 @@ * @details Inputs: none * @details Outputs: heatDisinfectState, stateTimer, isThisLastDrain, * stateTrialCounter, areTempSensorsInRange, rsrvr1Status, rsrvr2Status, - * R1HeatDisinfectVol, R2HeatDisinfectVol, hasPostHeatDisinfectWaitStarted, - * overallHeatDisinfectTimer, cancellationMode, rsrvrFillStableTimeCounter, - * heatDisinfectPostTimer, isPartialDisinfectInProgress + * R1HeatDisinfectVol, R2HeatDisinfectVol, overallHeatDisinfectTimer, + * cancellationMode, rsrvrFillStableTimeCounter, isPartialDisinfectInProgress, + * isDrainPumpOnInMixDrain * @return none *************************************************************************/ void initHeatDisinfectMode( void ) @@ -203,12 +207,11 @@ rsrvr2Status = RESERVOIR_STATUS_UNKNOWN; R1HeatDisinfectVol = 0.0; R2HeatDisinfectVol = 0.0; - hasPostDisinfectWaitStarted = FALSE; overallHeatDisinfectTimer = 0; cancellationMode = CANCELLATION_MODE_NONE; rsrvrFillStableTimeCounter = 0; - heatDisinfectPostTimer = 0; isPartialDisinfectInProgress = FALSE; + isDrainPumpInMixDrainOn = FALSE; } /*********************************************************************//** @@ -288,6 +291,10 @@ heatDisinfectState = handleHeatDisinfectDisinfectR2ToR1State(); break; + case DG_HEAT_DISINFECT_STATE_COOL_DOWN_HEATERS: + heatDisinfectState = handleHeatDisinfectCoolDownHeatersState(); + break; + case DG_HEAT_DISINFECT_STATE_MIX_DRAIN_R1: heatDisinfectState = handleHeatDisinfectMixDrainR1State(); break; @@ -313,15 +320,15 @@ break; case DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH: - heatDisinfectState = handleHeatDisinfectCancelModeBasicPath(); + heatDisinfectState = handleHeatDisinfectCancelModeBasicPathState(); break; case DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH: - heatDisinfectState = handleHeatDisinfectCancelModeWaterPath(); + heatDisinfectState = handleHeatDisinfectCancelModeWaterPathState(); break; case DG_HEAT_DISINFECT_STATE_COMPLETE: - // Done with heat disinfect cycle, failed or not + heatDisinfectState = handleHeatDisinfectCompleteState(); break; default: @@ -357,8 +364,6 @@ *************************************************************************/ void stopDGHeatDisinfect( void ) { - heatDisinfectState = DG_HEAT_DISINFECT_STATE_COMPLETE; - // Reset all the actuators resetActuators(); @@ -441,8 +446,7 @@ 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_BASIC_PATH ); + rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS ); } else if ( rsrvr1Status == RESERVOIR_STATUS_EMPTY ) { @@ -503,8 +507,7 @@ 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_BASIC_PATH ); + rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS ); } else if ( rsrvr2Status == RESERVOIR_STATUS_EMPTY ) { @@ -669,14 +672,12 @@ // If R1 is not full, keep monitoring for R1 level and timeout if ( rsrvr1Status == RESERVOIR_STATUS_EMPTY ) { - rsrvr1Status = getRsrvrFillStatus( 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 ); } // Once R1 is full, keep monitoring for R2 level and timeout else if( rsrvr1Status == RESERVOIR_STATUS_FULL ) { - rsrvr2Status = getRsrvrFillStatus( 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 ); // Once R2 is full (to 500mL in this case), transition to the next state if ( rsrvr2Status == RESERVOIR_STATUS_FULL ) @@ -724,8 +725,7 @@ // If reservoir 1 is empty, turn off the drain pump 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_BASIC_PATH ); + rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS ); } else if ( rsrvr1Status == RESERVOIR_STATUS_EMPTY ) { @@ -736,14 +736,12 @@ // First reservoir 2 must be completely full if ( rsrvr2Status == RESERVOIR_STATUS_EMPTY ) { - rsrvr2Status = getRsrvrFillStatus( 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 ); } // Once R2 is full, R1 must be partially full else if( rsrvr2Status == RESERVOIR_STATUS_FULL ) { - rsrvr1Status = getRsrvrFillStatus( 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 ); // Once R1 is partially full, transition to the next state if ( rsrvr1Status == RESERVOIR_STATUS_FULL ) @@ -786,8 +784,7 @@ // If reservoir 2 is empty, set the drain valve to drain R1 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_BASIC_PATH ); + rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS ); } else if ( rsrvr2Status == RESERVOIR_STATUS_EMPTY ) { @@ -819,8 +816,7 @@ // If reservoir 1 is empty, set the state to fill water state 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_BASIC_PATH ); + rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS ); } else if ( rsrvr1Status == RESERVOIR_STATUS_EMPTY ) { @@ -872,14 +868,12 @@ // First reservoir 1 must be full if ( rsrvr1Status == RESERVOIR_STATUS_EMPTY ) { - rsrvr1Status = getRsrvrFillStatus( 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 ); } // Once reservoir 1 is full, check the status of reservoir 2 since the water overflows to reservoir 2 else if ( rsrvr1Status == RESERVOIR_STATUS_FULL ) { - rsrvr2Status = getRsrvrFillStatus( 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 ); // Once reservoir 2 is full, set the actuators for recirculation if ( rsrvr2Status == RESERVOIR_STATUS_FULL ) @@ -943,7 +937,6 @@ case HEAT_DISINFECT_COMPLETE: //TODO turn off CP1 and CP2 - // Set the valves to transfer hot water from R1 to R2 and fill up R2. setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); @@ -985,13 +978,11 @@ // First reservoir 1 must be partially full if ( rsrvr1Status == RESERVOIR_STATUS_EMPTY ) { - rsrvr1Status = getRsrvrFillStatus( 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 ); } else if ( rsrvr1Status == RESERVOIR_STATUS_FULL ) { - rsrvr2Status = getRsrvrFillStatus( 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 ); if ( rsrvr2Status == RESERVOIR_STATUS_FULL ) { @@ -1031,77 +1022,127 @@ state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; break; - case HEAT_DISINFECT_POST_WAIT: - if ( hasPostDisinfectWaitStarted != TRUE ) - { - // Turn off the pumps and heaters - // TODO turn off CP1 and CP2 - stopPrimaryHeater(); - stopTrimmerHeater(); - - hasPostDisinfectWaitStarted = TRUE; - } + case HEAT_DISINFECT_COMPLETE: + // Turn off the pumps and heaters + // TODO turn off CP1 and CP2 + stopPrimaryHeater(); + stopTrimmerHeater(); + stateTimer = getMSTimerCount(); + state = DG_HEAT_DISINFECT_STATE_COOL_DOWN_HEATERS; break; + } - case HEAT_DISINFECT_COMPLETE: - // Stop the drain pump and the RO pump to exit the closed loop - signalDrainPumpHardStop(); - signalROPumpHardStop(); + return state; +} - // De-energize all the valves that are not in the path anymore and set the other - // valves to drain the hot water - setValveState( VPI, VALVE_STATE_OPEN ); - setValveState( VBF, VALVE_STATE_CLOSED ); - setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); - setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); - setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); - setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); - setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); - setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); - setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NC ); +/*********************************************************************//** + * @brief + * The handleHeatDisinfectCoolDownHeatersState function handles the heat + * disinfect cool down heaters state. The state continues running the fluid + * while the heaters are off for a certain period of time. + * @details Inputs: stateTimer + * @details Outputs: stateTimer + * @return next state of the heat disinfect state machine + *************************************************************************/ +static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCoolDownHeatersState( void ) +{ + DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_COOL_DOWN_HEATERS; - // Turn on the drain pump to drain the reservoirs in open loop mode - setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); + if ( didTimeout( stateTimer, POST_HEAT_DISINFECT_WAIT_TIME_MS ) ) + { + // Stop the drain pump and the RO pump to exit the closed loop + signalDrainPumpHardStop(); + signalROPumpHardStop(); - rsrvr1Status = RESERVOIR_STATUS_FULL; - stateTimer = getMSTimerCount(); - hasPostDisinfectWaitStarted = FALSE; - R1HeatDisinfectVol = 0; - R2HeatDisinfectVol = 0; - state = DG_HEAT_DISINFECT_STATE_MIX_DRAIN_R1; - break; + // De-energize all the valves that are not in the path anymore + // and wait for the RO membrane to be cooled down. + // In this state, VPi and VPd must still be kept energized to make sure fresh + // water does not enter the circulation path the membrane is cooling down + setValveState( VPI, VALVE_STATE_CLOSED ); + setValveState( VBF, VALVE_STATE_CLOSED ); + setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NC ); + + stateTimer = getMSTimerCount(); + state = DG_HEAT_DISINFECT_STATE_COOL_DOWN_RO_FILTER; } return state; } /*********************************************************************//** * @brief + * The handleHeatDisinfectCoolDownROFilterState function handles the heat + * disinfect cool down RO filter state. The state monitors the temperature + * at THd and if it is less than 45 C, it transitions to the next state. + * @details Inputs: stateTimer, rsrvr1Status + * @details Outputs: stateTimer, rsrvr1Status + * @return next state of the heat disinfect state machine + *************************************************************************/ +static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCoolDownROFilterState( void ) +{ + DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_COOL_DOWN_RO_FILTER; + + F32 ThdTemp = getTemperatureValue( TEMPSENSORS_OUTLET_REDUNDANT ); //TODO change this to actual THd sensor later + + // Check if the coldest spot temperature is less than 45 C so the RO filter + // can safely run fluid through + if ( ThdTemp < ROF_MIN_LOW_PRESSURE_TEMPERATURE_C ) + { + setValveState( VPI, VALVE_STATE_OPEN ); + setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); + setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); + setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); + setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); + + rsrvr1Status = RESERVOIR_STATUS_FULL; + stateTimer = getMSTimerCount(); + state = DG_HEAT_DISINFECT_STATE_MIX_DRAIN_R1; + } + + return state; +} + +/*********************************************************************//** + * @brief * The handleHeatDisinfectMixDrainR1State function handles the heat * disinfect mix drain R1 state. The state drains reservoir 1 and if it * times out, it transitions to basic cancellation state. Otherwise, it * transitions to the next state. - * @details Inputs: stateTimer, rsrvr1Status, rsrvr2Status - * @details Outputs: stateTimer, rsrvr1Status, rsrvr2Status + * @details Inputs: stateTimer, rsrvr1Status, rsrvr2Status, + * isDrainPumpOnInMixDrain + * @details Outputs: stateTimer, rsrvr1Status, rsrvr2Status, + * isDrainPumpOnInMixDrain * @return next state of the heat disinfect state machine *************************************************************************/ static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectMixDrainR1State( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_MIX_DRAIN_R1; - if ( rsrvr1Status == RESERVOIR_STATUS_FULL ) + if ( didTimeout( stateTimer, DRAIN_PUMP_START_TIME_IN_MIX_DRAIN_MS ) && isDrainPumpInMixDrainOn == FALSE ) { - rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS, - DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH ); + isDrainPumpInMixDrainOn = TRUE; + + // Turn on the drain pump to drain the reservoirs in open loop mode + //setDrainPumpTargetRPM( DRAIN_PUMP_RPM_IN_MIX_DRAIN ); TODO if this is not needed remove the #define + setDrainPumpTargetOutletPressure( 5.0 ); //TODO if this is the method, add a #define } - else if ( rsrvr1Status == RESERVOIR_STATUS_EMPTY ) + else if ( isDrainPumpInMixDrainOn == TRUE ) { - // Set the drain valve to reservoir 2 - setValveState( VRD, VALVE_STATE_R2_C_TO_NO ); + if ( rsrvr1Status == RESERVOIR_STATUS_FULL ) + { + rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_MIX_DRAIN_TIMEOUT_MS ); + } + 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; + rsrvr2Status = RESERVOIR_STATUS_FULL; + stateTimer = getMSTimerCount(); + state = DG_HEAT_DISINFECT_STATE_MIX_DRAIN_R2; + } } return state; @@ -1123,41 +1164,15 @@ 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_BASIC_PATH ); + rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_MIX_DRAIN_TIMEOUT_MS ); } else if ( rsrvr2Status == RESERVOIR_STATUS_EMPTY ) { // Done with draining the reservoirs signalDrainPumpHardStop(); - stateTimer = getMSTimerCount(); - state = DG_HEAT_DISINFECT_STATE_COOL_DOWN_RO_FILTER; - } - - return state; -} - -/*********************************************************************//** - * @brief - * The handleHeatDisinfectCoolDownROFilterState function handles the heat - * disinfect cool down RO filter state. The state monitors the temperature - * at THd and if it is less than 45 C, it transitions to the next state. - * @details Inputs: stateTimer, rsrvr1Status, rsrvr2Status - * @details Outputs: stateTimer, rsrvr1Status, rsrvr2Status - * @return next state of the heat disinfect state machine - *************************************************************************/ -static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCoolDownROFilterState( void ) -{ - DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_COOL_DOWN_RO_FILTER; - - F32 ThdTemp = getTemperatureValue( TEMPSENSORS_OUTLET_REDUNDANT ); //TODO change this to actual THd sensor later - - // Check if the coldest spot temperature is less than 45 C so the RO filter - // can safely run fluid through - if ( ThdTemp < ROF_MIN_LOW_PRESSURE_TEMPERATURE_C ) - { // Set the valves to fill up R1 and overflow to R2 + setValveState( VPI, VALVE_STATE_OPEN ); setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); @@ -1169,8 +1184,8 @@ rsrvr1Status = RESERVOIR_STATUS_EMPTY; rsrvr2Status = RESERVOIR_STATUS_EMPTY; - stateTimer = getMSTimerCount(); + stateTimer = getMSTimerCount(); state = DG_HEAT_DISINFECT_STATE_RINSE_R1_TO_R2; } @@ -1193,13 +1208,11 @@ if ( rsrvr1Status == RESERVOIR_STATUS_EMPTY ) { - rsrvr1Status = getRsrvrFillStatus( 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 ); } else if ( rsrvr1Status == RESERVOIR_STATUS_FULL ) { - rsrvr2Status = getRsrvrFillStatus( 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 ); if ( rsrvr2Status == RESERVOIR_STATUS_FULL ) { @@ -1239,8 +1252,7 @@ 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_BASIC_PATH ); + rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS ); } else if ( rsrvr1Status == RESERVOIR_STATUS_EMPTY ) { @@ -1251,14 +1263,12 @@ // First reservoir 2 must be completely full if ( rsrvr2Status == RESERVOIR_STATUS_EMPTY ) { - rsrvr2Status = getRsrvrFillStatus( 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 ); } // Once reservoir 2 is completely full, monitor reservoir 1 else if ( rsrvr2Status == RESERVOIR_STATUS_FULL ) { - rsrvr1Status = getRsrvrFillStatus( 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 ); if ( rsrvr1Status == RESERVOIR_STATUS_FULL ) { @@ -1314,17 +1324,17 @@ /*********************************************************************//** * @brief - * The handleHeatDisinfectCancelModeBasicPath function handles the + * The handleHeatDisinfectCancelModeBasicPathState function handles the * heat disinfect cancel mode basic path state. The state sets the state * to complete and raises an alarm. * @details Inputs: cancellationMode * @details Outputs: cancellationMode * @return next state of the heat disinfect state machine *************************************************************************/ -static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCancelModeBasicPath( void ) +static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCancelModeBasicPathState( void ) { // Go to state complete, we are done - DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_COMPLETE; + DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH; // Set the cancellation mode cancellationMode = CANCELLATION_MODE_BASIC; @@ -1336,7 +1346,7 @@ /*********************************************************************//** * @brief - * The handleHeatDisinfectCancelModeWaterPath function handles the + * The handleHeatDisinfectCancelModeWaterPathState function handles the * heat disinfect cancel mode cold water path state. The state resets all * the actuators. If THd > 60 C, it runs a hot water cancellation to make sure * the water that is drained is below 60 C. Otherwise, it runs a cold water @@ -1347,7 +1357,7 @@ * @details Outputs: rsrvr1Status, rsrvr2Status, cancellationMode, stateTimer * @return next state of the heat disinfect state machine *************************************************************************/ -static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCancelModeWaterPath( void ) +static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCancelModeWaterPathState( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; @@ -1390,8 +1400,7 @@ if ( rsrvr2Status == RESERVOIR_STATUS_FULL ) { // If the cancellation water path cannot be done, got to basic cancellation path - rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS, - DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH ); + rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS ); if ( rsrvr2Status == RESERVOIR_STATUS_EMPTY ) { @@ -1404,14 +1413,10 @@ if ( ( rsrvr2Status == RESERVOIR_STATUS_EMPTY ) && ( rsrvr1Status == RESERVOIR_STATUS_FULL ) ) { // If the cancellation water path cannot be done, got to basic cancellation path - rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS, - DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH ); + rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS ); if ( rsrvr1Status == RESERVOIR_STATUS_EMPTY ) { - // Done with heat disinfect mode - state = DG_HEAT_DISINFECT_STATE_COMPLETE; - setModeToFailed(); } } @@ -1421,6 +1426,24 @@ /*********************************************************************//** * @brief + * The handleHeatDisinfectCompleteState function handles the + * heat disinfect complete state. The state stops heat disinfect and + * requests transition to mode standby. + * @details Inputs: none + * @details Outputs: none + * @return next state of the heat disinfect state machine + *************************************************************************/ +static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCompleteState( void ) +{ + DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_COMPLETE; + + stopDGHeatDisinfect(); + + return state; +} + +/*********************************************************************//** + * @brief * The resetActuators function sets all the actuators to reset and * de-energized state. * @details Inputs: none @@ -1481,7 +1504,7 @@ * the operation timed out. * @return the status of the reservoirs during filling *************************************************************************/ -static RESERVOIRS_STATUS_T getRsrvrFillStatus( 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 ) { RESERVOIRS_STATUS_T status = RESERVOIR_STATUS_EMPTY; F32 volume = 0.0; @@ -1529,7 +1552,7 @@ * the operation timed out. * @return the status of the reservoirs during draining *************************************************************************/ -static RESERVOIRS_STATUS_T getRsrvrDrainStatus( 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 ) { RESERVOIRS_STATUS_T status = RESERVOIR_STATUS_FULL; @@ -1541,13 +1564,12 @@ stateTimer = getMSTimerCount(); status = RESERVOIR_STATUS_EMPTY; } - else if ( didTimeout( stateTimer, RSRVRS_DRAIN_TIMEOUT_MS ) ) + else if ( didTimeout( stateTimer, timeout ) ) { // Failed to drain ontime. Update the previous heat disinfect state and transition to basic cancellation - prevHeatDisinfectState = heatDisinfectState; - heatDisinfectState = cancellationState; - alarm = ALARM_ID_DG_RESERVOIR_DRAIN_TIMEOUT; - status = RESERVOIR_STATUS_UNKNOWN; + //prevHeatDisinfectState = heatDisinfectState; + //alarm = ALARM_ID_DG_RESERVOIR_DRAIN_TIMEOUT; + //status = RESERVOIR_STATUS_UNKNOWN; } return status; @@ -1624,31 +1646,9 @@ // If the flag is TRUE, check if this stage of heat disinfect is done if ( isPartialDisinfectInProgress && didTimeout( heatDisinfectTimer, HEAT_DISINFECT_TIME_MS ) ) { - // If the state is disinfect R2 to R1 but post wait time has not started, set the post disinfect timer - if ( heatDisinfectState == DG_HEAT_DISINFECT_STATE_DISINFECT_R2_TO_R1 && hasPostDisinfectWaitStarted != TRUE ) - { - heatDisinfectPostTimer = getMSTimerCount(); - status = HEAT_DISINFECT_POST_WAIT; - } - // If the state is disinfect R2 to R1 but post wait time has started - else if ( heatDisinfectState == DG_HEAT_DISINFECT_STATE_DISINFECT_R2_TO_R1 && hasPostDisinfectWaitStarted == TRUE ) - { - // Check if the post disinfect wait has timed out - if ( didTimeout( heatDisinfectPostTimer, POST_HEAT_DISINFECT_WAIT_TIME_MS ) ) - { - status = HEAT_DISINFECT_COMPLETE; - } - else - { - status = HEAT_DISINFECT_POST_WAIT; - } - } - else - { - // Done with this stage of heat disnfect. Reset the variables - status = HEAT_DISINFECT_COMPLETE; - isPartialDisinfectInProgress = FALSE; - } + // Done with this stage of heat disnfect. Reset the variables + status = HEAT_DISINFECT_COMPLETE; + isPartialDisinfectInProgress = FALSE; } return status; Index: firmware/App/Modes/ModeHeatDisinfect.h =================================================================== diff -u -r73796a0e50450e4958407c4ce42337e257277faa -r263a8e5e9d7314f92def1b5701db2a92cf537542 --- firmware/App/Modes/ModeHeatDisinfect.h (.../ModeHeatDisinfect.h) (revision 73796a0e50450e4958407c4ce42337e257277faa) +++ firmware/App/Modes/ModeHeatDisinfect.h (.../ModeHeatDisinfect.h) (revision 263a8e5e9d7314f92def1b5701db2a92cf537542) @@ -23,7 +23,7 @@ /** * @defgroup DGHeatDisinfectMode DGHeatDisinfectMode - * @brief Heat disinfection mode module. Manages the state machine for the heat disinfection mode. + * @brief Heat disinfection mode module. Manages the state machine for the heat disinfect mode. * * @addtogroup DGHeatDisinfectMode * @{ @@ -49,7 +49,7 @@ void transitionToHeatDisinfectMode( void ); // Prepares for transition to heat disinfect mode U32 execHeatDisinfectMode( void ); // Execute the heat disinfect mode state machine (call from OperationModes) -DG_HEAT_DISINFECT_STATE_T getCurrentHeatDisinfectState( void ); // get the current state of the heat disinfect mode. +DG_HEAT_DISINFECT_STATE_T getCurrentHeatDisinfectState( void ); // get the current state of the heat disinfect mode void stopDGHeatDisinfect( void ); // Stop DG heat disinfect