Index: firmware/App/Modes/ModeHeatDisinfect.c =================================================================== diff -u -r7d4711edd7b40cd3e29f43e766f79a8a09586fe9 -rf5d8da2ffed2cb22132c791039ba8a1221e31223 --- firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 7d4711edd7b40cd3e29f43e766f79a8a09586fe9) +++ firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision f5d8da2ffed2cb22132c791039ba8a1221e31223) @@ -117,6 +117,10 @@ #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. +// 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. #define NELSON_SUPPORT_STOP_TEMP_C ( NELSON_SUPPORT_TARGET_TEMP_C - 5.0F ) // Nelson support heat disinfect stop temperature in C. @@ -162,6 +166,14 @@ F32 stopTempC; ///< Heat disinfect temperature to stop disinfect in C. } HEAT_DISINFECT_TIME_STATUS_T; +/// Passive heat disinfect status +typedef struct +{ + 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 ********** static DG_HEAT_DISINFECT_STATE_T heatDisinfectState; ///< Current active heat disinfect state. @@ -190,8 +202,9 @@ static HEAT_DISINFECT_TIME_STATUS_T timeStatus[ NUM_OF_HEAT_DISINFECT_TIMES ]; ///< Heat disinfect time status. static F32 concPumpsStartTemperatureC; ///< Heat disinfect concentrate pumps start temperature in C. 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 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 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 @@ -251,7 +264,7 @@ * hasROFCirculationBeenStarted, ROFCirculationTimer, targetDisinfectTime * ROFCirculationCoolingCounter, concentratePumpsPrimeTimer, areRsrvrsLeaking * haveDrainParamsBeenInit, tempGradOutOfRangeTimer, disinfectNVOps, - * dataPublishCounter, timeStatus, concPumpsStartTemperatureC + * dataPublishCounter, timeStatus, concPumpsStartTemperatureC, passiveHeatDisStatus * @return none *************************************************************************/ void initHeatDisinfectMode( void ) @@ -282,6 +295,8 @@ dataPublishCounter = 0; concPumpsStartTemperatureC = HEAT_DISINFECT_CONC_PUMPS_START_TEMP_C; isRODisinfectDone = FALSE; + 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; @@ -516,6 +531,21 @@ return status; } +/*********************************************************************//** + * @brief + * 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 isPassive boolean flag to indicate whether to run passive heat + * disinfect or not + * @return none + *************************************************************************/ +void setActiveOrPassiveHeatDisinfectStatus( BOOL isPassive ) +{ + passiveCoolHeatDisStatus.isPassiveHeatDisRqustd = isPassive; +} + // ********** private functions ********** /*********************************************************************//** @@ -545,6 +575,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_PASSIVE_COOL_HEAT_DISINFECT_STATUS, (U32)passiveCoolHeatDisStatus.isPassiveHeatDisRqustd, 0 ) return state; } @@ -1090,6 +1121,12 @@ startHeater( DG_TRIMMER_HEATER ); } + // 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 ); + } + stateTimer = getMSTimerCount(); rsrvrsVolMonitorTimer = getMSTimerCount(); state = DG_HEAT_DISINFECT_STATE_DISINFECT_R1_TO_R2; @@ -1376,14 +1413,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() ) @@ -1412,31 +1469,36 @@ * times out, it transitions to basic cancellation state. Otherwise, it * transitions to the next state. * @details Inputs: stateTimer, rsrvr1Status, rsrvr2Status, - * isDrainPumpOnInMixDrain + * isDrainPumpOnInMixDrain, passiveCoolHeatDisStatus * @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; + U32 targetDrainRPM = ( TRUE == 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 ) { @@ -1550,8 +1612,10 @@ // 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; @@ -1652,9 +1716,16 @@ } else #endif + + if ( FALSE == passiveCoolHeatDisStatus.isPassiveHeatDisRqustd ) { requestNewOperationMode( DG_MODE_HCOL ); } + else + { + // After nocturnal run transition to standby since there is not active cool + requestNewOperationMode( DG_MODE_STAN ); + } return state; }