Index: firmware/App/Modes/ModeHeatDisinfect.c =================================================================== diff -u -ra49d0f9d8954ae57c0e8ba779e7ab378bb837147 -rab9597daa82d8e4575a8bb1fd8438ac301b85d44 --- firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision a49d0f9d8954ae57c0e8ba779e7ab378bb837147) +++ firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision ab9597daa82d8e4575a8bb1fd8438ac301b85d44) @@ -117,11 +117,9 @@ #define MIX_DRAIN_WEIGHT_UNCHANGE_TIMEOUT ( 15 * MS_PER_SECOND ) ///< Time period of unchanged weight during mix draining before timeout. #define MIX_DRAIN_TEMPERATURE_THRESHOLD_C 60.0F ///< Temperature threshold for performing mix drain or normal drain. -// Nocturnal cool defines -#define NOCTURNAL_COOL_IDLE_TIME_MS ( 10 * SEC_PER_MIN * MS_PER_SECOND ) ///< Nocturnal cool idle time in milliseconds. -#define NOCTURNAL_COOL_RUN_TIME_PRIOR_TEMP_AVG_MS ( 40 * MS_PER_SECOND ) ///< Nocturnal cool run the fluid before averaging temperature in milliseconds. -#define NOCTURNAL_COOL_RUN_TIME_TO_TEMP_AVG_MS ( 20 * MS_PER_SECOND ) ///< Nocturnal cool run time to average the temperature in milliseconds. -#define NOCTURNAL_COOL_TEMP_THRESHOLD_TO_DRAIN_C 58.0F ///< Nocturnal cool threshold temperature to drain in C. +// Passive cool defines +#define PASSIVE_COOL_TIME_TO_DRAIN_MS ( 20 * MS_PER_SECOND ) ///< Passive cool time needed to be below temperature range in milliseconds. +#define PASSIVE_COOL_TEMP_THRESHOLD_TO_DRAIN_C 59.0F ///< Passive cool threshold temperature to drain in C. #ifndef _RELEASE_ #define NELSON_SUPPORT_TARGET_TEMP_C 6.0F // Nelson support heat disinfect target temperature in C. @@ -168,14 +166,13 @@ F32 stopTempC; ///< Heat disinfect temperature to stop disinfect in C. } HEAT_DISINFECT_TIME_STATUS_T; -/// Nocturnal heat disinfect status +/// Passive heat disinfect status typedef struct { - BOOL isNocturnalHeatDisRqustd; ///< Boolean flag to indicate the status of nocturnal heat disinfect. - F32 TDiRunningSumC; ///< TDi running sum temperature in C. - F32 THdRunninSumC; ///< THd running sum temperature in C. - U32 sampleCount; ///< Temperature sample count. -} NOCTURNAL_HEAT_DISINFECT_STATUS_T; + BOOL isPassiveHeatDisRqustd; ///< Boolean flag to indicate the status of passive heat disinfect. + BOOL isTempBelowRange; ///< Boolean flag to indicate whether the temperature is below range. + U32 tempsCheckStartTimeMS; ///< Temperatures below range start time in milliseconds. +} PASSIVE_COOL_HEAT_DISINFECT_STATUS_T; // ********** private data ********** @@ -207,7 +204,7 @@ static BOOL isRODisinfectDone; ///< Heat disinfect is RO disinfect done flag. static OVERRIDE_U32_T targetTimer77C = { HEAT_DISINFECT_AT_77_C_TIME_MS, 0, 0, 0 }; ///< Heat disinfection override target timer at 77 C. static OVERRIDE_U32_T targetTimer82C = { HEAT_DISINFECT_AT_82_C_TIME_MS, 0, 0, 0 }; ///< Heat disinfection override target timer at 82 C. -static NOCTURNAL_HEAT_DISINFECT_STATUS_T noctHeatDisStatus; ///< Nocturnal heat disinfect status. +static PASSIVE_COOL_HEAT_DISINFECT_STATUS_T passiveCoolHeatDisStatus; ///< Passive cool heat disinfect status. #ifndef _RELEASE_ /* Nelson Labs is in charge of testing the efficacy of the disinfects (heat and chem). The codes that contain the name Nelson are used to @@ -234,10 +231,6 @@ 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 handleHeatDisinfectNocturnalCoolIdleState( void ); -static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectNocturnalCoolCheckWaterTempState( void ); -static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectNocturnalCoolDrainR1State( void ); -static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectNocturnalCoolDrainR2State( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectMixDrainR1State( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectMixDrainR2State( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCancelModeBasicPathState( void ); @@ -252,8 +245,6 @@ static void publishHeatDisinfectData( void ); static void monitorModeHeatDisinfect( void ); static void writeDisinfectDataToNV( DG_USAGE_INFO_ITEMS_T info ); -static void setHeatDisinfectActuators( DG_HEAT_DISINFECT_STATE_T state ); -static BOOL areThereAnyDGPumpsAlarm( void ); #ifndef _RELEASE_ static void setNelsonSupportConditions( void ); @@ -273,7 +264,7 @@ * hasROFCirculationBeenStarted, ROFCirculationTimer, targetDisinfectTime * ROFCirculationCoolingCounter, concentratePumpsPrimeTimer, areRsrvrsLeaking * haveDrainParamsBeenInit, tempGradOutOfRangeTimer, disinfectNVOps, - * dataPublishCounter, timeStatus, concPumpsStartTemperatureC, noctHeatDisStatus + * dataPublishCounter, timeStatus, concPumpsStartTemperatureC, passiveHeatDisStatus * @return none *************************************************************************/ void initHeatDisinfectMode( void ) @@ -304,10 +295,10 @@ dataPublishCounter = 0; concPumpsStartTemperatureC = HEAT_DISINFECT_CONC_PUMPS_START_TEMP_C; isRODisinfectDone = FALSE; - noctHeatDisStatus.TDiRunningSumC = 0.0F; // NOTE: the "is nocturnal" flag cannot be set here because it is set in with the request functions - noctHeatDisStatus.THdRunninSumC = 0.0F; - noctHeatDisStatus.sampleCount = 0; + passiveCoolHeatDisStatus.tempsCheckStartTimeMS = 0.0F; // NOTE: the "is passive" flag cannot be set here because it is set in with the request functions + passiveCoolHeatDisStatus.isTempBelowRange = FALSE; + // Initialize the disinfect times timeStatus[ RO_AT_77_C ].startTempC = HEAT_DISINFECT_START_TEMP_AT_77_C; timeStatus[ RO_AT_77_C ].startTimeMS = 0; @@ -465,22 +456,6 @@ heatDisinfectState = handleHeatDisinfectCoolDownHeatersState(); break; - case DG_HEAT_DISINFECT_STATE_NOCTURNAL_COOL_IDLE: - heatDisinfectState = handleHeatDisinfectNocturnalCoolIdleState(); - break; - - case DG_HEAT_DISINFECT_STATE_NOCTURNAL_COOL_CHECK_WATER_TEMP: - heatDisinfectState = handleHeatDisinfectNocturnalCoolCheckWaterTempState(); - break; - - case DG_HEAT_DISINFECT_STATE_NOCTURNAL_COOL_DRAIN_R1: - heatDisinfectState = handleHeatDisinfectNocturnalCoolDrainR1State(); - break; - - case DG_HEAT_DISINFECT_STATE_NOCTURNAL_COOL_DRAIN_R2: - heatDisinfectState = handleHeatDisinfectNocturnalCoolDrainR2State(); - break; - case DG_HEAT_DISINFECT_STATE_MIX_DRAIN_R1: heatDisinfectState = handleHeatDisinfectMixDrainR1State(); break; @@ -559,17 +534,17 @@ /*********************************************************************//** * @brief - * The setNocturnalHeatDisinfectStatus function sets the status of the - * nocturnal heat disinfect. + * The setActiveOrPassiveHeatDisinfectStatus function sets the status of the + * heat disinfect as to whether it is active cool or passive cool * @details Inputs: none * @details Outputs: nocturnalHeatDisStatus - * @param isNocturnal boolean flag to indicate whether to run nocturnal heat + * @param isPassive boolean flag to indicate whether to run passive heat * disinfect or not * @return none *************************************************************************/ -void setNocturnalHeatDisinfectStatus( BOOL isNocturnal ) +void setActiveOrPassiveHeatDisinfectStatus( BOOL isPassive ) { - noctHeatDisStatus.isNocturnalHeatDisRqustd = isNocturnal; + passiveCoolHeatDisStatus.isPassiveHeatDisRqustd = isPassive; } // ********** private functions ********** @@ -601,7 +576,7 @@ setValveState( VPO, VALVE_STATE_FILL_C_TO_NC); setValveState( VRD1, VALVE_STATE_OPEN ); setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); - SEND_EVENT_WITH_2_U32_DATA( DG_EVENT_NOCTURNAL_HEAT_DISINFECT_STATUS, (U32)noctHeatDisStatus.isNocturnalHeatDisRqustd, 0 ) + SEND_EVENT_WITH_2_U32_DATA( DG_EVENT_PASSIVE_COOL_HEAT_DISINFECT_STATUS, (U32)passiveCoolHeatDisStatus.isPassiveHeatDisRqustd, 0 ) return state; } @@ -1147,8 +1122,8 @@ startHeater( DG_TRIMMER_HEATER ); } - // If the user has selected the nocturnal heat disinfect, trigger the alarm to prompt the user to turn off the inlet water valves - if ( TRUE == noctHeatDisStatus.isNocturnalHeatDisRqustd ) + // If the user has selected the passive cool heat disinfect, trigger the alarm to prompt the user to turn off the inlet water valves + if ( TRUE == passiveCoolHeatDisStatus.isPassiveHeatDisRqustd ) { activateAlarmNoData( ALARM_ID_DG_TURN_OFF_INLET_WATER_VALVES ); } @@ -1439,14 +1414,34 @@ *************************************************************************/ static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCoolDownHeatersState( void ) { - DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_COOL_DOWN_HEATERS; + DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_COOL_DOWN_HEATERS; + BOOL setActuatorsPriorToTransition = FALSE; heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_COOL_DOWN_DEVICE; writeDisinfectDataToNV( USAGE_INFO_HEAT_DIS ); - if ( TRUE == didTimeout( stateTimer, POST_HEAT_DISINFECT_WAIT_TIME_MS ) ) + if ( ( TRUE == didTimeout( stateTimer, POST_HEAT_DISINFECT_WAIT_TIME_MS ) ) && ( FALSE == passiveCoolHeatDisStatus.isPassiveHeatDisRqustd ) ) { + setActuatorsPriorToTransition = TRUE; + } + else + { + F32 TDiC = getTemperatureValue( TEMPSENSORS_INLET_DIALYSATE ); + F32 THdC = getTemperatureValue( TEMPSENSORS_HEAT_DISINFECT ); + + if ( ( TDiC > PASSIVE_COOL_TEMP_THRESHOLD_TO_DRAIN_C ) && ( THdC > PASSIVE_COOL_TEMP_THRESHOLD_TO_DRAIN_C ) ) + { + passiveCoolHeatDisStatus.tempsCheckStartTimeMS = getMSTimerCount(); + } + else if ( TRUE == didTimeout( passiveCoolHeatDisStatus.tempsCheckStartTimeMS, PASSIVE_COOL_TIME_TO_DRAIN_MS ) ) + { + setActuatorsPriorToTransition = TRUE; + } + } + + if ( TRUE == setActuatorsPriorToTransition ) + { signalROPumpHardStop(); if ( TRUE == isDrainPumpOn() ) @@ -1457,9 +1452,11 @@ } else { - stateTimer = getMSTimerCount(); - state = ( TRUE == noctHeatDisStatus.isNocturnalHeatDisRqustd ? DG_HEAT_DISINFECT_STATE_NOCTURNAL_COOL_IDLE : DG_HEAT_DISINFECT_STATE_MIX_DRAIN_R1 ); - setHeatDisinfectActuators( state ); + setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); + rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; + stateTimer = getMSTimerCount(); + state = DG_HEAT_DISINFECT_STATE_MIX_DRAIN_R1; } } @@ -1468,152 +1465,6 @@ /*********************************************************************//** * @brief - * The handleHeatDisinfectNocturnalCoolIdleState function handles the heat - * disinfect nocturnal cool idel state. In this state, heat disinfect idles - * until the specified time has elapsed to transition the next state. - * @details Inputs: stateTimer - * @details Outputs: stateTimer - * @return next state of the heat disinfect state machine - *************************************************************************/ -static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectNocturnalCoolIdleState( void ) -{ - DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_NOCTURNAL_COOL_IDLE; - - if ( TRUE == didTimeout( stateTimer, NOCTURNAL_COOL_IDLE_TIME_MS ) ) - { - stateTimer = getMSTimerCount(); - state = DG_HEAT_DISINFECT_STATE_NOCTURNAL_COOL_CHECK_WATER_TEMP; - setHeatDisinfectActuators( state ); - } - - if ( TRUE == areThereAnyDGPumpsAlarm() ) - { - state = DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH; - } - - return state; -} - -/*********************************************************************//** - * @brief - * The handleHeatDisinfectNocturnalCoolCheckWaterTempState function handles - * the heat disinfect nocturnal cool check the water temperature state. - * In this state, the fluid is run for the specified period of time and then - * TDi and THd temperature sensor values are averaged. If the values are less - * than the specified values then the state machine transitions to the next - * state, otherwise it transitions to the nocturnal cool idle state. - * @details Inputs: noctHeatDisStatus, stateTimer - * @details Outputs: noctHeatDisStatus, stateTimer - * @return next state of the heat disinfect state machine - *************************************************************************/ -static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectNocturnalCoolCheckWaterTempState( void ) -{ - DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_NOCTURNAL_COOL_CHECK_WATER_TEMP; - - if ( TRUE == didTimeout( stateTimer, NOCTURNAL_COOL_RUN_TIME_PRIOR_TEMP_AVG_MS ) ) - { - noctHeatDisStatus.TDiRunningSumC += getTemperatureValue( TEMPSENSORS_INLET_DIALYSATE ); - noctHeatDisStatus.THdRunninSumC += getTemperatureValue( TEMPSENSORS_HEAT_DISINFECT ); - noctHeatDisStatus.sampleCount += 1; - - if ( TRUE == didTimeout( stateTimer, ( NOCTURNAL_COOL_RUN_TIME_PRIOR_TEMP_AVG_MS + NOCTURNAL_COOL_RUN_TIME_TO_TEMP_AVG_MS ) ) ) - { - F32 avgTDiC = noctHeatDisStatus.TDiRunningSumC / (F32)noctHeatDisStatus.sampleCount; - F32 avgTHdC = noctHeatDisStatus.THdRunninSumC / (F32)noctHeatDisStatus.sampleCount; - - // Time has elapsed, stop running - deenergizeActuators( FALSE ); - - // Assume the default state transition is the nocturnal cool idle - state = DG_HEAT_DISINFECT_STATE_NOCTURNAL_COOL_IDLE; - - if ( ( avgTDiC <= NOCTURNAL_COOL_TEMP_THRESHOLD_TO_DRAIN_C ) && ( avgTHdC <= NOCTURNAL_COOL_TEMP_THRESHOLD_TO_DRAIN_C ) ) - { - state = DG_HEAT_DISINFECT_STATE_NOCTURNAL_COOL_DRAIN_R1; - } - - setHeatDisinfectActuators( state ); - } - } - - if ( TRUE == areThereAnyDGPumpsAlarm() ) - { - state = DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH; - } - - return state; -} - -/*********************************************************************//** - * @brief - * The handleHeatDisinfectNocturnalCoolDrainR1State function handles - * the heat disinfect nocturnal cool drain R1 state. - * In this state, reservoir 1 is drained and if the drain is complete within - * the specified time then it transitions to the next state otherwise, it - * transitions to the cancel basic path state. - * @details Inputs: stateTimer - * @details Outputs: stateTimer, rsrvr1Status, prevHeatDisinfectState - * @return next state of the heat disinfect state machine - *************************************************************************/ -static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectNocturnalCoolDrainR1State( void ) -{ - DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_NOCTURNAL_COOL_DRAIN_R1; - - if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr1Status ) - { - rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT_MS, RSRVRS_INITIAL_DRAIN_TIMEOUT_MS ); - } - else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) - { - state = DG_HEAT_DISINFECT_STATE_NOCTURNAL_COOL_DRAIN_R2; - stateTimer = getMSTimerCount(); - setHeatDisinfectActuators( state ); - } - else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) - { - prevHeatDisinfectState = state; - state = DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH; - } - - return state; -} - -/*********************************************************************//** - * @brief - * The handleHeatDisinfectNocturnalCoolDrainR2State function handles - * the heat disinfect nocturnal cool drain R2 state. - * In this state, reservoir 2 is drained and if the drain is complete within - * the specified time then it transitions to the next state otherwise, it - * transitions to the cancel basic path state. - * @details Inputs: stateTimer - * @details Outputs: stateTimer, rsrvr2Status, prevHeatDisinfectState - * @return next state of the heat disinfect state machine - *************************************************************************/ -static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectNocturnalCoolDrainR2State( void ) -{ - DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_NOCTURNAL_COOL_DRAIN_R2; - - if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr2Status ) - { - rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT_MS, RSRVRS_INITIAL_DRAIN_TIMEOUT_MS ); - } - else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) - { - deenergizeActuators( NO_PARK_CONC_PUMPS ); - - state = ( ALARM_ID_NO_ALARM == alarmDetectedPendingTrigger ? DG_HEAT_DISINFECT_STATE_COMPLETE : DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH ); - } - else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) - { - prevHeatDisinfectState = state; - state = DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH; - } - - 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 @@ -1627,23 +1478,28 @@ static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectMixDrainR1State( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_MIX_DRAIN_R1; + U32 targetDrainRPM = ( FALSE == passiveCoolHeatDisStatus.isPassiveHeatDisRqustd ? DRAIN_PUMP_TARGET_RPM : DRAIN_PUMP_RPM_IN_MIX_DRAIN ); heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_FLUSH_AFTER_DISINFECT; if ( ( TRUE == didTimeout( stateTimer, DRAIN_PUMP_START_TIME_IN_MIX_DRAIN_MS ) ) && ( FALSE == isDrainPumpInMixDrainOn ) ) { isDrainPumpInMixDrainOn = TRUE; - setValveState( VPI, VALVE_STATE_OPEN ); + if ( FALSE == passiveCoolHeatDisStatus.isPassiveHeatDisRqustd ) + { + setValveState( VPI, VALVE_STATE_OPEN ); + turnOnUVReactor( INLET_UV_REACTOR ); + } + setValveState( VRD1, VALVE_STATE_OPEN ); setValveState( VBF, VALVE_STATE_CLOSED ); setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); // Turn on the drain pump to drain the reservoirs in open loop mode - setDrainPumpTargetRPM( DRAIN_PUMP_RPM_IN_MIX_DRAIN ); - turnOnUVReactor( INLET_UV_REACTOR ); + setDrainPumpTargetRPM( targetDrainRPM ); } else if ( TRUE == isDrainPumpInMixDrainOn ) { @@ -1742,9 +1598,8 @@ *************************************************************************/ static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCancelModeWaterPathState( void ) { - DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; - U32 drainTimeoutMS = ( CANCELLATION_MODE_COLD == cancellationMode ? RSRVRS_INITIAL_DRAIN_TIMEOUT_MS : RSRVRS_MIX_DRAIN_TIMEOUT_MS ); - BOOL isTemperatureInRangeForDrain = TRUE; + DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; + U32 drainTimeoutMS = ( CANCELLATION_MODE_COLD == cancellationMode ? RSRVRS_INITIAL_DRAIN_TIMEOUT_MS : RSRVRS_MIX_DRAIN_TIMEOUT_MS ); // Set the heat disinfect UI state heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_CANCEL_DISINFECT; @@ -1758,102 +1613,85 @@ // Stop all the actuators first then decide who should run next deenergizeActuators( NO_PARK_CONC_PUMPS ); - // 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 ) ) + // The two sensors must be less than a threshold to decide if mix drain is needed to normal drain or the + // passive cool heat disinfect should have been selected + if ( ( ( TDi < MIX_DRAIN_TEMPERATURE_THRESHOLD_C ) && ( TRo < MIX_DRAIN_TEMPERATURE_THRESHOLD_C ) ) || + ( TRUE == passiveCoolHeatDisStatus.isPassiveHeatDisRqustd ) ) { targetRPM = DRAIN_PUMP_TARGET_RPM; cancellationMode = CANCELLATION_MODE_COLD; } else { - if ( TRUE == noctHeatDisStatus.isNocturnalHeatDisRqustd ) - { - isTemperatureInRangeForDrain = FALSE; - state = DG_HEAT_DISINFECT_STATE_NOCTURNAL_COOL_IDLE; - } - else - { - // 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_NO ); + // 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_NO ); - targetRPM = DRAIN_PUMP_RPM_IN_MIX_DRAIN; - cancellationMode = CANCELLATION_MODE_HOT; - } + targetRPM = DRAIN_PUMP_RPM_IN_MIX_DRAIN; + cancellationMode = CANCELLATION_MODE_HOT; } - stateTimer = getMSTimerCount(); + rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; + rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; + haveDrainParamsBeenInit[ DG_RESERVOIR_1 ] = FALSE; + haveDrainParamsBeenInit[ DG_RESERVOIR_2 ] = FALSE; + stateTimer = getMSTimerCount(); - if ( TRUE == isTemperatureInRangeForDrain ) - { - rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - haveDrainParamsBeenInit[ DG_RESERVOIR_1 ] = FALSE; - haveDrainParamsBeenInit[ DG_RESERVOIR_2 ] = FALSE; - - // The drain is set to start from reservoir 2 since all the actuators have been de-energized - // Set the drain valve to reservoir 2 - setValveState( VRD2, VALVE_STATE_OPEN ); - setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); - setDrainPumpTargetRPM( targetRPM ); - } - else - { - setHeatDisinfectActuators( DG_HEAT_DISINFECT_STATE_NOCTURNAL_COOL_IDLE ); - } + // The drain is set to start from reservoir 2 since all the actuators have been de-energized + // Set the drain valve to reservoir 2 + setValveState( VRD2, VALVE_STATE_OPEN ); + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); + setDrainPumpTargetRPM( targetRPM ); } - if ( TRUE == isTemperatureInRangeForDrain ) + // If reservoir 2 is empty, set to drain reservoir 1 + if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr2Status ) { - // If reservoir 2 is empty, set to drain reservoir 1 - if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr2Status ) - { - // If the cancellation water path cannot be done, got to basic cancellation path - rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT_MS, drainTimeoutMS ); + // If the cancellation water path cannot be done, got to basic cancellation path + rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT_MS, drainTimeoutMS ); - if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) - { - // Set the drain valve to reservoir 1 and close reservoir 2 - setValveState( VRD1, VALVE_STATE_OPEN ); - setValveState( VRD2, VALVE_STATE_CLOSED ); - } - } - else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) + if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) { - // Stop the actuators that are running before going to basic cancellation path - setValveState( VRD1, VALVE_STATE_CLOSED ); + // Set the drain valve to reservoir 1 and close reservoir 2 + setValveState( VRD1, VALVE_STATE_OPEN ); setValveState( VRD2, VALVE_STATE_CLOSED ); - signalDrainPumpHardStop(); - - prevHeatDisinfectState = state; - state = DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH; } + } + else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) + { + // Stop the actuators that are running before going to basic cancellation path + setValveState( VRD1, VALVE_STATE_CLOSED ); + setValveState( VRD2, VALVE_STATE_CLOSED ); + signalDrainPumpHardStop(); - // If reservoir 2 has already been drained and reservoir 1 is empty, reset and switch to complete - if ( ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) && ( DG_RESERVOIR_ABOVE_TARGET == rsrvr1Status ) ) - { - // If the cancellation water path cannot be done, got to basic cancellation path - rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT_MS, drainTimeoutMS ); + prevHeatDisinfectState = state; + state = DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH; + } - if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) - { - setValveState( VRD1, VALVE_STATE_CLOSED ); - setValveState( VRD2, VALVE_STATE_CLOSED ); - signalDrainPumpHardStop(); - failHeatDisinfect(); - } - } - else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) + // If reservoir 2 has already been drained and reservoir 1 is empty, reset and switch to complete + if ( ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) && ( DG_RESERVOIR_ABOVE_TARGET == rsrvr1Status ) ) + { + // If the cancellation water path cannot be done, got to basic cancellation path + rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT_MS, drainTimeoutMS ); + + if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) { setValveState( VRD1, VALVE_STATE_CLOSED ); setValveState( VRD2, VALVE_STATE_CLOSED ); signalDrainPumpHardStop(); - - prevHeatDisinfectState = state; - state = DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH; + failHeatDisinfect(); } } + else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) + { + setValveState( VRD1, VALVE_STATE_CLOSED ); + setValveState( VRD2, VALVE_STATE_CLOSED ); + signalDrainPumpHardStop(); + prevHeatDisinfectState = state; + state = DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH; + } + return state; } @@ -1880,7 +1718,7 @@ else #endif - if ( FALSE == noctHeatDisStatus.isNocturnalHeatDisRqustd ) + if ( FALSE == passiveCoolHeatDisStatus.isPassiveHeatDisRqustd ) { requestNewOperationMode( DG_MODE_HCOL ); } @@ -2315,101 +2153,7 @@ } } -/*********************************************************************//** - * @brief - * The setHeatDisinfectActuators function set the actuators prior to transitioning - * to the new heat disinfect state - * @details Inputs: none - * @details Outputs: rsrvr1Status, rsrvr2Status, haveDrainParamsBeenInit - * @param state the heat disinfect state that the exec is about to transition - * @return: none - *************************************************************************/ -static void setHeatDisinfectActuators( DG_HEAT_DISINFECT_STATE_T state ) -{ - switch( state ) - { - case DG_HEAT_DISINFECT_STATE_NOCTURNAL_COOL_IDLE: - deenergizeActuators( NO_PARK_CONC_PUMPS ); - break; - case DG_HEAT_DISINFECT_STATE_NOCTURNAL_COOL_CHECK_WATER_TEMP: - if ( getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ) >= RSRVRS_FULL_VOL_ML ) - { - setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); - setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); - setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); - setValveState( VRD1, VALVE_STATE_CLOSED ); - setValveState( VRD2, VALVE_STATE_OPEN ); - } - else if ( getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ) >= RSRVRS_FULL_VOL_ML ) - { - setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); - setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); - setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); - setValveState( VRD1, VALVE_STATE_OPEN ); - setValveState( VRD2, VALVE_STATE_CLOSED ); - } - setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); - setValveState( VBF, VALVE_STATE_OPEN ); - setValveState( VDR, VALVE_STATE_RECIRC_C_TO_NC ); - setValveState( VRC, VALVE_STATE_RECIRC_C_TO_NC ); - setROPumpTargetDutyCycle( HEAT_DISINFECT_TARGET_RO_PUMP_DC ); - setDrainPumpTargetOutletFlowLPM( HEAT_DISINFECT_TARGET_RO_FLOW_LPM ); - break; - - case DG_HEAT_DISINFECT_STATE_NOCTURNAL_COOL_DRAIN_R1: - haveDrainParamsBeenInit[ DG_RESERVOIR_1 ] = FALSE; - rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - setValveState( VPO, VALVE_STATE_FILL_C_TO_NC); - setValveState( VRD1, VALVE_STATE_OPEN ); - setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); - break; - - case DG_HEAT_DISINFECT_STATE_NOCTURNAL_COOL_DRAIN_R2: - haveDrainParamsBeenInit[ DG_RESERVOIR_2 ] = FALSE; - rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - setValveState( VPO, VALVE_STATE_FILL_C_TO_NC); - setValveState( VRD1, VALVE_STATE_CLOSED ); - setValveState( VRD2, VALVE_STATE_OPEN ); - setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); - break; - - case DG_HEAT_DISINFECT_STATE_MIX_DRAIN_R1: - setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); - setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); - rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - break; - - default: - // Do nothing. More state should be added in the future. - break; - } -} - -/*********************************************************************//** - * @brief - * The areThereAnyDGPumpsAlarm function handles whether there are any RO and/or - * drain pump alarms are triggered. - * @details Inputs: none - * @details Outputs: none - * @return TRUE if any of the RO and/or drain pump alarms are triggered otherwise, FALSE - *************************************************************************/ -static BOOL areThereAnyDGPumpsAlarm( void ) -{ - BOOL status = FALSE; - - status |= isAlarmActive( ALARM_ID_DG_RO_PUMP_PRESSURE_OUT_OF_RANGE ); - status |= isAlarmActive( ALARM_ID_DG_MAX_RO_PUMP_PWM_EXCEEDED ); - status |= isAlarmActive( ALARM_ID_DG_RO_PUMP_DUTY_CYCLE_OUT_OF_RANGE ); - status |= isAlarmActive( ALARM_ID_DG_DRAIN_PUMP_DIRECTION_FPGA_FAULT ); - status |= isAlarmActive( ALARM_ID_DG_DRAIN_PUMP_DIRECTION_INVALID ); - status |= isAlarmActive( ALARM_ID_DG_DRAIN_PUMP_OFF_FAULT ); - status |= isAlarmActive( ALARM_ID_DG_DRAIN_PUMP_RPM_OUT_OF_RANGE ); - - return status; -} - - /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/