Index: firmware/App/Modes/ModeHeatDisinfect.c =================================================================== diff -u -r2c08db070a6e09306caf461e7aceeb53097fd995 -r3ee95c7a0e4a4618837494ba59240422f594c868 --- firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 2c08db070a6e09306caf461e7aceeb53097fd995) +++ firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 3ee95c7a0e4a4618837494ba59240422f594c868) @@ -8,7 +8,7 @@ * @file ModeHeatDisinfect.c * * @author (last) Dara Navaei -* @date (last) 21-Dec-2022 +* @date (last) 30-Mar-2023 * * @author (original) Sean * @date (original) 20-Apr-2020 @@ -53,8 +53,8 @@ // Drain R1 & R2 states defines #define DRAIN_PUMP_TARGET_RPM 2400 ///< Drain pump target RPM during drain. -#define RSRVRS_INITIAL_DRAIN_TIME_OUT_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 initial drain time out in milliseconds. -#define DRAIN_WEIGHT_UNCHANGE_TIMEOUT ( 6 * MS_PER_SECOND ) ///< Time period of unchanged weight during draining before timeout. +#define RSRVRS_INITIAL_DRAIN_TIMEOUT_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 initial drain time out in milliseconds. +#define DRAIN_WEIGHT_UNCHANGE_TIMEOUT_MS ( 6 * MS_PER_SECOND ) ///< Time period of unchanged weight during draining before timeout. // Flush drain path state defines #define FLUSH_DRAIN_WAIT_TIME_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. @@ -67,7 +67,7 @@ #define MAX_FLUSH_CIRC_TEMP_SENSOR_DIFF_C 3.0F ///< Maximum flush circulation temperature difference tolerance in C. #define NUM_OF_TEMP_SENSORS_TO_AVG 3.0F ///< Number of temperature sensors to average to check the difference. #define ACID_PUMP_SPEED_ML_PER_MIN 30.6F ///< Acid concentrate pump speed in mL/min. -// The bicarb pump is 2% faster than the acid pump to create a flow from acid to bicarb line during heat disinfect +// The acid pump is 2% faster than the bicarb pump to create a flow from acid to bicarb line during heat disinfect #define BICARB_PUMP_SPEED_ML_PER_MIN -30.0F ///< Bicarb concentrate pump speed in mL/min. // Flush and drain R1 and R2 @@ -78,23 +78,30 @@ #define RSRVRS_500ML_FILL_UP_TIMEOUT_MS ( 4 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 partial fill up timeout in ms. #define RSRVRS_DRAIN_TIMEOUT_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 drain timeout in ms. -// Fill and heat water -#define HEAT_DISINFECT_TARGET_TEMPERATURE_C 82.0F ///< Heat disinfect target water temperature in C. -#define HEAT_DISINFECT_START_TEMPERATURE_C 81.0F ///< Heat disinfect minimum acceptable temperature in C. +// Target temperature +#define HEAT_DISINFECT_PRIM_HEATER_TARGET_TEMP_C 90.0F ///< Heat disinfect primary heater target temperature in C. +#define HEAT_DISINFECT_TRIM_HEATER_TARGET_TEMP_C 90.0F ///< Heat disinfect trimmer heater target temperature in C. +#define HEAT_DISINFECT_CONC_PUMPS_START_TEMP_C 75.0F ///< Heat disinfect start concentrate pumps target temperature in C. +#define HEAT_DISINFECT_TRIMMER_HEATER_STOP_TEMP_C 75.0F ///< Heat disinfect trimmer heater stop temperature in C. +#define HEAT_DISINFECT_START_TEMP_AT_77_C 77.0F ///< Heat disinfect start disinfect at 77 C in C. +#define HEAT_DISINFECT_STOP_TEMP_AT_76_C 76.0F ///< Heat disinfect stop disinfect at 76 C in C. +#define HEAT_DISINFECT_START_TEMP_AT_82_C 82.0F ///< Heat disinfect start disinfect at 82 C in C. +#define HEAT_DISINFECT_STOP_TEMP_AT_81_C 81.0F ///< Heat disinfect stop disinfect at 81 C in C. // R1 to R2 & R2 to R1 heat disinfect circulation #define HEAT_DISINFECT_TARGET_RO_FLOW_LPM 1.3F ///< Heat disinfect target RO flow rate in L/min. #define HEAT_DISINFECT_TARGET_RO_FLOW_TRANSFER_LPM 0.8F ///< Heat disinfect target RO flow rate in L/min when transferring between reservoirs. #define HEAT_DISINFECT_MAX_RO_PRESSURE_PSI 30 ///< Heat disinfect maximum RO pressure in psi. -#define HEAT_DISINFECT_TIME_MS ( 10 * SEC_PER_MIN * MS_PER_SECOND ) ///< Heat disinfect time for each section in milliseconds. -#define HEAT_DISINFECT_START_TEMP_TIMOUT_MS ( 4 * MIN_PER_HOUR * SEC_PER_MIN * MS_PER_SECOND ) ///< Heat disinfect reaching to minimum temperature timeout in milliseconds. -#define RSRVRS_TARGET_VOL_OUT_TIMEOUT_MS ( 0.5F * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 maximum volume out of range timeout during heat disinfect. TODO change this to 5 seconds -#define RSRVRS_MAX_TARGET_VOL_CHANGE_ML 250.0F // TODO temporary change. Change back to 100 ///< Reservoirs 1 & 2 maximum allowed volume change when full during heat disinfect. +#define HEAT_DISINFECT_START_TEMP_TIMEOUT_MS ( 4 * MIN_PER_HOUR * SEC_PER_MIN * MS_PER_SECOND ) ///< Heat disinfect reaching to minimum temperature timeout in milliseconds. +#define RSRVRS_TARGET_VOL_OUT_TIMEOUT_MS ( 5 * MS_PER_SECOND ) ///< Reservoirs 1 & 2 maximum volume out of range timeout during heat disinfect. +#define RSRVRS_MAX_TARGET_VOL_CHANGE_ML 100.0F ///< Reservoirs 1 & 2 maximum allowed volume change when full during heat disinfect. #define POST_HEAT_DISINFECT_WAIT_TIME_MS ( 3 * SEC_PER_MIN * MS_PER_SECOND ) ///< Heat disinfect final wait time before flushing the system in milliseconds. #define HEAT_DISINFECT_MAX_TEMP_GRADIENT_C 15.0F ///< Heat disinfect maximum allowed temperature gradient in between hottest and coldest sensors. #define HEAT_DISINFECT_TEMP_GRAD_OUT_RANGE_TIME_MS ( 0.16 * SEC_PER_MIN * MS_PER_SECOND ) ///< Heat disinfect temperature gradient out of range timeout in milliseconds. #define HEAT_DISINFECT_TARGET_RO_PUMP_DC 0.4F ///< Heat disinfect target RO pump duty cycle. #define HEAT_DISINFECT_REF_RSRVR_TIMEOUT_MS ( 5 * MS_PER_SECOND ) ///< Heat disinfect getting reference reservoirs value timeout in milliseconds. +#define HEAT_DISINFECT_AT_82_C_TIME_MS ( 10 * SEC_PER_MIN * MS_PER_SECOND ) ///< Heat disinfect time at 82 C in milliseconds. +#define HEAT_DISINFECT_AT_77_C_TIME_MS ( 32 * SEC_PER_MIN * MS_PER_SECOND ) ///< Heat disinfect time at 77 C in milliseconds. // Mix drain R1 and R2 #define RSRVRS_MIX_DRAIN_TIMEOUT_MS ( 5 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 mix drain timeout in ms. @@ -103,15 +110,12 @@ #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. -/// Cancellation paths -typedef enum Cancellation_modes -{ - CANCELLATION_MODE_NONE = 0, ///< Cancellation mode none. - CANCELLATION_MODE_BASIC, ///< Cancellation mode basic. - CANCELLATION_MODE_HOT, ///< Cancellation mode hot. - CANCELLATION_MODE_COLD, ///< Cancellation mode cold. - NUM_OF_CANCELLATION_MODES ///< Number of cancellation modes. -} CANCELLATION_MODE_T; +#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. +#define NELSON_SUPPORT_DISINFECT_TIME_MS ( 2 * MIN_PER_HOUR * SEC_PER_MIN * MS_PER_SECOND ) // Nelson support heat disinfect time in milliseconds. +#define NELSON_SUPPORT_INOCULATE_TIME_MS ( 30 * SEC_PER_MIN * MS_PER_SECOND ) // Nelson support inoculate time in milliseconds. +#endif /// Heat disinfect status typedef enum Heat_disinfect_status @@ -125,12 +129,32 @@ NUM_OF_HEAT_DISINFECT_STATUS ///< Number of heat disinfect status. } HEAT_DISINFECT_STATUS_T; +/// Heat disinfect times enum +typedef enum Heat_Disinfect_Times +{ + RO_AT_77_C = 0, ///< Heat disinfect RO disinfect at 77 C. + RO_AT_82_C, ///< Heat disinfect RO disinfect at 82 C. + RSRVR_AT_77_C, ///< Heat disinfect reservoir disinfect at 77 C. + RSRVR_AT_82_C, ///< Heat disinfect reservoir disinfect at 82 C. + NUM_OF_HEAT_DISINFECT_TIMES ///< Number of heat disinfect times. +} HEAT_DISINFECT_TIMES_T; + /// Non-volatile write structure typedef struct { BOOL hasDisStatusBeenWrittenToNV; ///< Boolean flag to indicate whether the disinfect status been written to NV or not. } DISINFECT_NV_OPS_T; +/// Heat disinfect time status structure +typedef struct +{ + U32 startTimeMS; ///< Heat disinfect start time in milliseconds. + U32 targetTimeMS; ///< Heat disinfect target time in milliseconds. + TEMPERATURE_SENSORS_T tempSensor; ///< Heat disinfect temperature sensor to check. + F32 startTempC; ///< Heat disinfect temperature to start disinfect in C. + F32 stopTempC; ///< Heat disinfect temperature to stop disinfect in C. +} HEAT_DISINFECT_TIME_STATUS_T; + // ********** private data ********** static DG_HEAT_DISINFECT_STATE_T heatDisinfectState; ///< Current active heat disinfect state. @@ -145,8 +169,6 @@ static DG_RESERVOIR_STATUS_T rsrvr2Status; ///< Reservoir 2 status. static F32 rsrvr1RefVolML; ///< Reservoir 1 reference volume in heat disinfect in milliliters. static F32 rsrvr2RefVolML; ///< Reservoir 2 reference volume in heat disinfect in milliliters. -static U32 heatDisinfectTimer; ///< Heat disinfect timer. -static BOOL isPartialDisinfectInProgress; ///< Heat disinfect partial complete/in progess flag. static U32 rsrvrsVolMonitorTimer; ///< Reservoir 1 & 2 volume monitor timers during heat disinfect. static BOOL areRsrvrsLeaking; ///< Reservoir 1 & 2 leak check flag during heat disinfect. static U32 dataPublishCounter; ///< Heat Disinfect data publish counter. @@ -158,7 +180,18 @@ static BOOL haveDrainParamsBeenInit[ NUM_OF_DG_RESERVOIRS ]; ///< Boolean flag to indicate whether the drain parameters have been reset or not. static U32 tempGradOutOfRangeTimer; ///< Temperature gradient out of range start timer. static DISINFECT_NV_OPS_T disinfectNVOps; ///< Disinfect non-volatile memory operations. +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. +#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 + * support the special conditions that are needed to be created to test the disinfects. The support codes are not compiled in a release + * build. + */ +static NELSON_SUPPORT_T nelsonSupport; // Nelson support. +#endif + // ********** private function prototypes ********** static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectStartState( void ); @@ -185,42 +218,47 @@ static DG_RESERVOIR_STATUS_T getRsrvrFillStatus( DG_RESERVOIR_ID_T reservoir, F32 targetVol, U32 timeout ); static DG_RESERVOIR_STATUS_T getRsrvrDrainStatus( DG_RESERVOIR_ID_T r, U32 drainSteadyStateTimeout, U32 timeout ); static HEAT_DISINFECT_STATUS_T getHeatDisinfectStatus( void ); +static BOOL hasDisinfectTimeElapsed( HEAT_DISINFECT_TIMES_T disinfectTime ); static void publishHeatDisinfectData( void ); static void monitorModeHeatDisinfect( void ); static void writeDisinfectDataToNV( DG_USAGE_INFO_ITEMS_T info ); +#ifndef _RELEASE_ +static void setNelsonSupportConditions( void ); +static DG_HEAT_DISINFECT_STATE_T handleNelsonHeatDisinfectFillR1WithWaterState( void ); +#endif + /*********************************************************************//** * @brief * The initHeatDisinfectMode function initializes the heat disinfect mode * module. * @details Inputs: none - * @details Outputs: heatDisinfectState, stateTimer, + * @details Outputs: heatDisinfectState, stateTimer, isRODisinfectDone * stateTrialCounter, areTempSensorsInRange, rsrvr1Status, rsrvr2Status, * rsrvr1RefVolML, rsrvr2RefVolML, overallHeatDisinfectTimer, * cancellationMode, rsrvrFillStableTimeCounter, prevHeatDisinfectState * isPartialDisinfectInProgress, isDrainPumpOnInMixDrain, heatDisinfectTimer * hasROFCirculationBeenStarted, ROFCirculationTimer, targetDisinfectTime * ROFCirculationCoolingCounter, concentratePumpsPrimeTimer, areRsrvrsLeaking * haveDrainParamsBeenInit, tempGradOutOfRangeTimer, disinfectNVOps, - * dataPublishCounter + * dataPublishCounter, timeStatus, concPumpsStartTemperatureC * @return none *************************************************************************/ void initHeatDisinfectMode( void ) { heatDisinfectState = DG_HEAT_DISINFECT_STATE_START; prevHeatDisinfectState = DG_HEAT_DISINFECT_STATE_START; heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_NOT_RUNNING; - stateTimer = 0; + stateTimer = getMSTimerCount(); stateTrialCounter = 0; areTempSensorsInRange = FALSE; rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; rsrvr1RefVolML = 0.0F; rsrvr2RefVolML = 0.0F; - overallHeatDisinfectTimer = 0; + overallHeatDisinfectTimer = getMSTimerCount(); cancellationMode = CANCELLATION_MODE_NONE; rsrvrFillStableTimeCounter = 0; - isPartialDisinfectInProgress = FALSE; isDrainPumpInMixDrainOn = FALSE; concentratePumpsPrimeTimer = 0; targetDisinfectTime = 0; @@ -229,10 +267,40 @@ tempGradOutOfRangeTimer = 0; disinfectNVOps.hasDisStatusBeenWrittenToNV = FALSE; alarmDetectedPendingTrigger = ALARM_ID_NO_ALARM; - heatDisinfectTimer = 0; rsrvrsVolMonitorTimer = 0; areRsrvrsLeaking = FALSE; dataPublishCounter = 0; + concPumpsStartTemperatureC = HEAT_DISINFECT_CONC_PUMPS_START_TEMP_C; + isRODisinfectDone = 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; + timeStatus[ RO_AT_77_C ].stopTempC = HEAT_DISINFECT_STOP_TEMP_AT_76_C; + timeStatus[ RO_AT_77_C ].targetTimeMS = HEAT_DISINFECT_AT_77_C_TIME_MS; + timeStatus[ RO_AT_77_C ].tempSensor = TEMPSENSORS_HEAT_DISINFECT; + + timeStatus[ RO_AT_82_C ].startTempC = HEAT_DISINFECT_START_TEMP_AT_82_C; + timeStatus[ RO_AT_82_C ].startTimeMS = 0; + timeStatus[ RO_AT_82_C ].stopTempC = HEAT_DISINFECT_STOP_TEMP_AT_81_C; + timeStatus[ RO_AT_82_C ].targetTimeMS = HEAT_DISINFECT_AT_82_C_TIME_MS; + timeStatus[ RO_AT_82_C ].tempSensor = TEMPSENSORS_HEAT_DISINFECT; + + timeStatus[ RSRVR_AT_77_C ].startTempC = HEAT_DISINFECT_START_TEMP_AT_77_C; + timeStatus[ RSRVR_AT_77_C ].startTimeMS = 0; + timeStatus[ RSRVR_AT_77_C ].stopTempC = HEAT_DISINFECT_STOP_TEMP_AT_76_C; + timeStatus[ RSRVR_AT_77_C ].targetTimeMS = HEAT_DISINFECT_AT_77_C_TIME_MS; + timeStatus[ RSRVR_AT_77_C ].tempSensor = TEMPSENSORS_INLET_DIALYSATE; + + timeStatus[ RSRVR_AT_82_C ].startTempC = HEAT_DISINFECT_START_TEMP_AT_82_C; + timeStatus[ RSRVR_AT_82_C ].startTimeMS = 0; + timeStatus[ RSRVR_AT_82_C ].stopTempC = HEAT_DISINFECT_STOP_TEMP_AT_81_C; + timeStatus[ RSRVR_AT_82_C ].targetTimeMS = HEAT_DISINFECT_AT_82_C_TIME_MS; + timeStatus[ RSRVR_AT_82_C ].tempSensor = TEMPSENSORS_INLET_DIALYSATE; + +#ifndef _RELEASE_ + setNelsonSupportConditions(); +#endif } /*********************************************************************//** @@ -356,6 +424,12 @@ heatDisinfectState = handleHeatDisinfectCompleteState(); break; +#ifndef _RELEASE_ + case DG_NELSON_HEAT_DISINFECT_STATE_FILL_R1_WITH_WATER: + heatDisinfectState = handleNelsonHeatDisinfectFillR1WithWaterState(); + break; +#endif + default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_HEAT_DISINFECT_INVALID_EXEC_STATE, heatDisinfectState ) heatDisinfectState = DG_HEAT_DISINFECT_STATE_START; @@ -455,32 +529,29 @@ if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr1Status ) { - rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS ); + rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT_MS, RSRVRS_INITIAL_DRAIN_TIMEOUT_MS ); } else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) { tareLoadCell( LOAD_CELL_RESERVOIR_1_PRIMARY ); tareLoadCell( LOAD_CELL_RESERVOIR_1_BACKUP ); - // Assume reservoir 2 is full and drain it - rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - // Done with draining R1, close it setValveState( VRD1, VALVE_STATE_CLOSED ); // Set the actuators to drain R2. // NOTE: Drain pump is already on and VDr is already on drain state setValveState( VRD2, VALVE_STATE_OPEN ); - state = DG_HEAT_DISINFECT_STATE_DRAIN_R2; - setValveState( VPO, VALVE_STATE_FILL_C_TO_NC); - // Start the timer - stateTimer = getMSTimerCount(); + // Assume reservoir 2 is full and drain it + rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; + state = DG_HEAT_DISINFECT_STATE_DRAIN_R2; + stateTimer = getMSTimerCount(); } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { prevHeatDisinfectState = state; - state = DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH; + state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; } return state; @@ -503,7 +574,7 @@ if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr2Status ) { - rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS ); + rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT_MS, RSRVRS_INITIAL_DRAIN_TIMEOUT_MS ); } else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) { @@ -512,19 +583,28 @@ signalDrainPumpHardStop(); - // Done with draining R2, close it - setValveState( VRD2, VALVE_STATE_CLOSED ); - setValveState( VPI, VALVE_STATE_OPEN ); - stateTrialCounter = 0; - stateTimer = getMSTimerCount(); - state = DG_HEAT_DISINFECT_STATE_FLUSH_DRAIN; - - setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); +#ifndef _RELEASE_ + if ( NELSON_DRAIN_SAMPLES == nelsonSupport ) + { + state = DG_HEAT_DISINFECT_STATE_COMPLETE; + } + else +#endif + { + // Done with draining R2, close it + turnOnUVReactor( INLET_UV_REACTOR ); + setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); + setValveState( VRD2, VALVE_STATE_CLOSED ); + setValveState( VPI, VALVE_STATE_OPEN ); + stateTrialCounter = 0; + stateTimer = getMSTimerCount(); + state = DG_HEAT_DISINFECT_STATE_FLUSH_DRAIN; + } } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { prevHeatDisinfectState = state; - state = DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH; + state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; } return state; @@ -550,7 +630,6 @@ // Check if flush time has elapsed if ( TRUE == didTimeout( stateTimer, FLUSH_DRAIN_WAIT_TIME_MS ) ) { - turnOnUVReactor( INLET_UV_REACTOR ); setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); stateTimer = getMSTimerCount(); @@ -640,9 +719,15 @@ setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); - setHeaterTargetTemperature( DG_PRIMARY_HEATER, HEAT_DISINFECT_TARGET_TEMPERATURE_C ); - startHeater( DG_PRIMARY_HEATER ); +#ifndef _RELEASE_ + if ( nelsonSupport != NELSON_INOCULATE ) +#endif + { + setHeaterTargetTemperature( DG_PRIMARY_HEATER, HEAT_DISINFECT_PRIM_HEATER_TARGET_TEMP_C ); + startHeater( DG_PRIMARY_HEATER ); + } + // Set the NV data to FLASE to be able to write another NV data ops disinfectNVOps.hasDisStatusBeenWrittenToNV = FALSE; stateTimer = getMSTimerCount(); @@ -742,7 +827,7 @@ // If reservoir 1 is empty, turn off the drain pump if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr1Status ) { - rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS ); + rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT_MS, RSRVRS_INITIAL_DRAIN_TIMEOUT_MS ); } else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) { @@ -789,10 +874,11 @@ signalROPumpHardStop(); stopHeater( DG_PRIMARY_HEATER ); turnOffUVReactor( INLET_UV_REACTOR ); + turnOffUVReactor( OUTLET_UV_REACTOR ); // Set the valves to drain R2 and no fill setValveState( VPI, VALVE_STATE_CLOSED ); - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); - setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); + setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); setValveState( VRD2, VALVE_STATE_OPEN ); setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); @@ -834,7 +920,7 @@ // If reservoir 2 is empty, set the drain valve to drain R1 if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr2Status ) { - rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS ); + rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT_MS, RSRVRS_INITIAL_DRAIN_TIMEOUT_MS ); } else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) { @@ -872,7 +958,7 @@ // If reservoir 1 is empty, set the state to fill water state if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr1Status ) { - rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS ); + rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT_MS, RSRVRS_INITIAL_DRAIN_TIMEOUT_MS ); } else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) { @@ -887,14 +973,19 @@ setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); setValveState( VRD1, VALVE_STATE_CLOSED ); - setValveState( VRD2, VALVE_STATE_OPEN ); + setValveState( VRD2, VALVE_STATE_CLOSED ); turnOnUVReactor( INLET_UV_REACTOR ); // Turn on the RO pump setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); - // Start heating the water while we are filling up the reservoirs - setHeaterTargetTemperature( DG_PRIMARY_HEATER, HEAT_DISINFECT_TARGET_TEMPERATURE_C ); - startHeater( DG_PRIMARY_HEATER ); +#ifndef _RELEASE_ + if ( nelsonSupport != NELSON_INOCULATE ) +#endif + { + // Start heating the water while we are filling up the reservoirs + setHeaterTargetTemperature( DG_PRIMARY_HEATER, HEAT_DISINFECT_PRIM_HEATER_TARGET_TEMP_C ); + startHeater( DG_PRIMARY_HEATER ); + } rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; @@ -927,8 +1018,9 @@ static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectFillWithWaterState( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_FILL_WITH_WATER; - heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_HEAT_UP_WATER; + heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_HEAT_UP_WATER; + // First reservoir 1 must be full if ( DG_RESERVOIR_BELOW_TARGET == rsrvr1Status ) { @@ -943,19 +1035,24 @@ if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) { turnOffUVReactor( INLET_UV_REACTOR ); - // Set the valves to drain R2 and no fill setValveState( VPI, VALVE_STATE_CLOSED ); setValveState( VBF, VALVE_STATE_OPEN ); setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VDR, VALVE_STATE_RECIRC_C_TO_NC ); setValveState( VRC, VALVE_STATE_RECIRC_C_TO_NC ); + setValveState( VRD1, VALVE_STATE_CLOSED ); + setValveState( VRD2, VALVE_STATE_OPEN ); signalROPumpHardStop(); // Set the drain pump to control mode setDrainPumpTargetOutletFlowLPM( HEAT_DISINFECT_TARGET_RO_FLOW_LPM ); - // Start the trimmer heater since we are recirculating water and there is flow in the shunt line - setHeaterTargetTemperature( DG_TRIMMER_HEATER, HEAT_DISINFECT_TARGET_TEMPERATURE_C ); - startHeater( DG_TRIMMER_HEATER ); +#ifndef _RELEASE_ + if ( nelsonSupport != NELSON_INOCULATE ) +#endif + { + setHeaterTargetTemperature( DG_TRIMMER_HEATER, HEAT_DISINFECT_TRIM_HEATER_TARGET_TEMP_C ); + startHeater( DG_TRIMMER_HEATER ); + } stateTimer = getMSTimerCount(); rsrvrsVolMonitorTimer = getMSTimerCount(); @@ -1030,23 +1127,21 @@ setValveState( VRD2, VALVE_STATE_CLOSED ); setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); - - // Set the drain pump to control mode setDrainPumpTargetOutletFlowLPM( HEAT_DISINFECT_TARGET_RO_FLOW_TRANSFER_LPM ); - // Turn off trimmer heater for transition stopHeater( DG_TRIMMER_HEATER ); // Although there is fluid in both reservoirs, but they are set to empty // to begin the transition of hot water from R1 to R2. - rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; - rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; - stateTimer = getMSTimerCount(); - rsrvr1RefVolML = 0.0F; - rsrvr2RefVolML = 0.0F; - // Reset the timer for the next disinfect state - tempGradOutOfRangeTimer = 0; - state = DG_HEAT_DISINFECT_STATE_FILL_R2_WITH_HOT_WATER; + rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; + rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; + stateTimer = getMSTimerCount(); + rsrvr1RefVolML = 0.0F; + rsrvr2RefVolML = 0.0F; + tempGradOutOfRangeTimer = 0; + state = DG_HEAT_DISINFECT_STATE_FILL_R2_WITH_HOT_WATER; + timeStatus[ RSRVR_AT_77_C ].startTimeMS = 0; + timeStatus[ RSRVR_AT_82_C ].startTimeMS = 0; break; case HEAT_DISINFECT_HEAT_UP_IN_PROGRESS: @@ -1074,8 +1169,9 @@ static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectFillR2WithHotWaterState( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_FILL_R2_WITH_HOT_WATER; - heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_TRANSITION_HOT_WATER; + heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_TRANSITION_HOT_WATER; + // First reservoir 1 must be partially full if ( DG_RESERVOIR_BELOW_TARGET == rsrvr1Status ) { @@ -1090,10 +1186,6 @@ // Set the drain pump to control mode setDrainPumpTargetOutletFlowLPM( HEAT_DISINFECT_TARGET_RO_FLOW_LPM ); - // Start the trimmer heater since we are recirculating water and there is flow in the shunt line - setHeaterTargetTemperature( DG_TRIMMER_HEATER, HEAT_DISINFECT_TARGET_TEMPERATURE_C ); - startHeater( DG_TRIMMER_HEATER ); - stateTimer = getMSTimerCount(); state = DG_HEAT_DISINFECT_STATE_DISINFECT_R2_TO_R1; } @@ -1127,8 +1219,9 @@ { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_DISINFECT_R2_TO_R1; HEAT_DISINFECT_STATUS_T status = getHeatDisinfectStatus(); - heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_DISINFECT_RESERVOIR_2; + heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_DISINFECT_RESERVOIR_2; + if ( TRUE == didTimeout( stateTimer, HEAT_DISINFECT_REF_RSRVR_TIMEOUT_MS ) ) { if ( ( rsrvr1RefVolML < NEARLY_ZERO ) && ( rsrvr2RefVolML < NEARLY_ZERO ) ) @@ -1149,13 +1242,53 @@ break; case HEAT_DISINFECT_COMPLETE: - requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID, NO_PARK_CONC_PUMPS ); - requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); - // Turn off the heaters - stopHeater( DG_PRIMARY_HEATER ); - stopHeater( DG_TRIMMER_HEATER ); - stateTimer = getMSTimerCount(); - state = DG_HEAT_DISINFECT_STATE_COOL_DOWN_HEATERS; + if ( TRUE == isRODisinfectDone ) + { +#ifndef _RELEASE_ + if ( ( NELSON_HEAT_DISINFECT == nelsonSupport ) || ( NELSON_POS_CONTROL_HEAT_DISINFECT == nelsonSupport ) ) + { + deenergizeActuators( NO_PARK_CONC_PUMPS ); + state = DG_HEAT_DISINFECT_STATE_COMPLETE; + } + else +#endif + { + requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID, NO_PARK_CONC_PUMPS ); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); + stopHeater( DG_PRIMARY_HEATER ); + stopHeater( DG_TRIMMER_HEATER ); + + timeStatus[ RSRVR_AT_77_C ].startTimeMS = 0; + timeStatus[ RSRVR_AT_82_C ].startTimeMS = 0; + timeStatus[ RO_AT_77_C ].startTimeMS = 0; + timeStatus[ RO_AT_82_C ].startTimeMS = 0; + rsrvr1RefVolML = 0.0F; + rsrvr2RefVolML = 0.0F; + stateTimer = getMSTimerCount(); + state = DG_HEAT_DISINFECT_STATE_COOL_DOWN_HEATERS; + } + } +#ifndef _RELEASE_ + if ( NELSON_INOCULATE == nelsonSupport ) + { + // Set the valves to transfer hot water from R1 to R2 and fill up R2. + setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); + setValveState( VRD1, VALVE_STATE_CLOSED ); + setValveState( VRD2, VALVE_STATE_OPEN ); + setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); + setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); + setDrainPumpTargetOutletFlowLPM( HEAT_DISINFECT_TARGET_RO_FLOW_TRANSFER_LPM ); + + // Although there is fluid in both reservoirs, but they are set to empty + // to begin the transition of hot water from R1 to R2. + rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; + rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; + stateTimer = getMSTimerCount(); + rsrvr1RefVolML = 0.0F; + rsrvr2RefVolML = 0.0F; + state = DG_NELSON_HEAT_DISINFECT_STATE_FILL_R1_WITH_WATER; + } +#endif break; case HEAT_DISINFECT_HEAT_UP_IN_PROGRESS: @@ -1179,8 +1312,9 @@ static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCoolDownHeatersState( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_COOL_DOWN_HEATERS; - heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_COOL_DOWN_DEVICE; + heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_COOL_DOWN_DEVICE; + writeDisinfectDataToNV( USAGE_INFO_HEAT_DIS ); if ( TRUE == didTimeout( stateTimer, POST_HEAT_DISINFECT_WAIT_TIME_MS ) ) @@ -1219,8 +1353,9 @@ static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectMixDrainR1State( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_MIX_DRAIN_R1; - heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_FLUSH_AFTER_DISINFECT; + heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_FLUSH_AFTER_DISINFECT; + if ( ( TRUE == didTimeout( stateTimer, DRAIN_PUMP_START_TIME_IN_MIX_DRAIN_MS ) ) && ( FALSE == isDrainPumpInMixDrainOn ) ) { isDrainPumpInMixDrainOn = TRUE; @@ -1309,10 +1444,8 @@ // Set the heat disinfect UI state heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_CANCEL_DISINFECT; + cancellationMode = CANCELLATION_MODE_BASIC; - // Set the cancellation mode - cancellationMode = CANCELLATION_MODE_BASIC; - failHeatDisinfect(); return state; @@ -1334,10 +1467,10 @@ 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 ); // Set the heat disinfect UI state heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_CANCEL_DISINFECT; - U32 drainTimeoutMS = ( CANCELLATION_MODE_COLD == cancellationMode ? RSRVRS_INITIAL_DRAIN_TIME_OUT_MS : RSRVRS_MIX_DRAIN_TIMEOUT_MS ); if ( CANCELLATION_MODE_NONE == cancellationMode ) { @@ -1362,7 +1495,6 @@ targetRPM = DRAIN_PUMP_RPM_IN_MIX_DRAIN; cancellationMode = CANCELLATION_MODE_HOT; - drainTimeoutMS = RSRVRS_MIX_DRAIN_TIMEOUT_MS; } rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; @@ -1371,7 +1503,6 @@ // 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 ); - // Start the drain pump setDrainPumpTargetRPM( targetRPM ); // Start the timer for drain timeout @@ -1382,7 +1513,7 @@ 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, drainTimeoutMS ); + rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT_MS, drainTimeoutMS ); if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) { @@ -1406,7 +1537,7 @@ 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, drainTimeoutMS ); + rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT_MS, drainTimeoutMS ); if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) { @@ -1441,10 +1572,20 @@ static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCompleteState( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_COMPLETE; - heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_COMPLETE; - requestNewOperationMode( DG_MODE_HCOL ); + heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_COMPLETE; +#ifndef _RELEASE_ + if ( nelsonSupport != NELSON_NONE ) + { + requestNewOperationMode( DG_MODE_STAN ); + } + else +#endif + { + requestNewOperationMode( DG_MODE_HCOL ); + } + return state; } @@ -1464,7 +1605,8 @@ { SET_ALARM_WITH_1_U32_DATA( alarmDetectedPendingTrigger, prevHeatDisinfectState ) } - requestNewOperationMode( DG_MODE_FAUL ); + + requestNewOperationMode( DG_MODE_STAN ); } /*********************************************************************//** @@ -1482,7 +1624,7 @@ static DG_RESERVOIR_STATUS_T getRsrvrFillStatus( DG_RESERVOIR_ID_T reservoir, F32 targetVol, U32 timeout ) { DG_RESERVOIR_STATUS_T status = DG_RESERVOIR_BELOW_TARGET; - F32 volume = 0.0; + F32 volume = 0.0F; if ( DG_RESERVOIR_1 == reservoir ) { @@ -1502,7 +1644,7 @@ { if ( ++rsrvrFillStableTimeCounter >= RSRVRS_FULL_STABLE_TIME_COUNT ) { - status = DG_RESERVOIR_REACHED_TARGET; + status = DG_RESERVOIR_REACHED_TARGET; rsrvrFillStableTimeCounter = 0; // Set the state timer in case it needs to be used for another timeout check if ( ( DG_HEAT_DISINFECT_STATE_FLUSH_R2_AND_DRAIN_R1 == heatDisinfectState) && ( DG_RESERVOIR_2 == reservoir ) ) @@ -1546,6 +1688,7 @@ static DG_RESERVOIR_STATUS_T getRsrvrDrainStatus( DG_RESERVOIR_ID_T r, U32 drainSteadyStateTimeout, U32 timeout ) { DG_RESERVOIR_STATUS_T status = DG_RESERVOIR_ABOVE_TARGET; + BOOL isDrainComplete = FALSE; // If the drain parameters of the reservoir is not initialized, initialize them if ( FALSE == haveDrainParamsBeenInit[ r ] ) @@ -1554,11 +1697,13 @@ haveDrainParamsBeenInit[ r ] = TRUE; } - BOOL isDrainComplete = hasTargetDrainVolumeBeenReached( r, drainSteadyStateTimeout ); + // NOTE: the drain status should be checked once the reservoirs parameters are initialized. This is to make sure the + // the timers for stable drain time are initialized prior to using them again + isDrainComplete = hasTargetDrainVolumeBeenReached( r, drainSteadyStateTimeout ); if ( TRUE == isDrainComplete ) { - if ( ( DG_HEAT_DISINFECT_STATE_FLUSH_R2_AND_DRAIN_R1 == heatDisinfectState) && ( DG_RESERVOIR_1 == r ) ) + if ( ( DG_HEAT_DISINFECT_STATE_FLUSH_R2_AND_DRAIN_R1 == heatDisinfectState ) && ( DG_RESERVOIR_1 == r ) ) { if ( ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) && ( 0 == getDrainPumpTargetRPM() ) ) { @@ -1597,23 +1742,30 @@ * * @details Inputs: tempGradOutOfRangeTimer, areRsrvrsLeaking, * isPartialDisinfectInProgress, heatDisinfectTimer, - * targetDisinfectTime * @details Outputs: tempGradOutOfRangeTimer, alarmDetectedPendingTrigger, * areRsrvrsLeaking, isPartialDisinfectInProgress, - * heatDisinfectTimer, targetDisinfectTime + * heatDisinfectTimer * @return status of the heat disinfect (i.e in progress, complete) *************************************************************************/ static HEAT_DISINFECT_STATUS_T getHeatDisinfectStatus( void ) { HEAT_DISINFECT_STATUS_T status = HEAT_DISINFECT_HEAT_UP_IN_PROGRESS; - F32 TPoTemp = getTemperatureValue( TEMPSENSORS_OUTLET_PRIMARY_HEATER ); - F32 ThdTemp = getTemperatureValue( TEMPSENSORS_HEAT_DISINFECT ); + F32 TPoTempC = getTemperatureValue( TEMPSENSORS_OUTLET_PRIMARY_HEATER ); + F32 ThdTempC = getTemperatureValue( TEMPSENSORS_HEAT_DISINFECT ); + F32 TDiTempC = getTemperatureValue( TEMPSENSORS_INLET_DIALYSATE ); F32 loadCellA1 = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); F32 loadCellB1 = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); BOOL isR1OutOfRange = ( fabs( loadCellA1 - rsrvr1RefVolML ) > RSRVRS_MAX_TARGET_VOL_CHANGE_ML ? TRUE : FALSE ); BOOL isR2OutOfRange = ( fabs( loadCellB1 - rsrvr2RefVolML ) > RSRVRS_MAX_TARGET_VOL_CHANGE_ML ? TRUE : FALSE ); - BOOL isGradientOutOfRange = ( fabs( TPoTemp - ThdTemp ) > HEAT_DISINFECT_MAX_TEMP_GRADIENT_C ? TRUE : FALSE ); + BOOL isGradientOutOfRange = ( fabs( TPoTempC - ThdTempC ) > HEAT_DISINFECT_MAX_TEMP_GRADIENT_C ? TRUE : FALSE ); + if ( TRUE == didTimeout( stateTimer, HEAT_DISINFECT_START_TEMP_TIMEOUT_MS ) ) + { + // Heating up to minimum temperature for heat disinfect failed + alarmDetectedPendingTrigger = ALARM_ID_DG_HEAT_DISINFECT_TARGET_TEMP_TIMEOUT; + status = HEAT_DISINFECT_HEAT_UP_TIMEOUT; + } + // Perform check if no pending alarm if ( ALARM_ID_NO_ALARM == alarmDetectedPendingTrigger ) { @@ -1662,58 +1814,92 @@ } } - // Perform check if no pending alarm if ( ALARM_ID_NO_ALARM == alarmDetectedPendingTrigger ) { - // If the coldest spot which is THd is less than minimum heat disinfect temperature, - // reset the heat disinfect timers and check whether heating up has timed out - if ( ThdTemp < HEAT_DISINFECT_START_TEMPERATURE_C ) +#ifndef _RELEASE_ + if ( ( nelsonSupport != NELSON_INOCULATE ) && ( nelsonSupport != NELSON_POS_CONTROL_HEAT_DISINFECT ) ) +#endif { - // Keep reseting the disinfect timer so the elapsed time is always 0 until disinfect truly starts - heatDisinfectTimer = getMSTimerCount(); - isPartialDisinfectInProgress = FALSE; - targetDisinfectTime = 0; - - if ( TRUE == didTimeout( stateTimer, HEAT_DISINFECT_START_TEMP_TIMOUT_MS ) ) + if ( TDiTempC >= HEAT_DISINFECT_TRIMMER_HEATER_STOP_TEMP_C ) { - // Heating up to minimum temperature for heat disinfect failed - alarmDetectedPendingTrigger = ALARM_ID_DG_HEAT_DISINFECT_TARGET_TEMP_TIMEOUT; - status = HEAT_DISINFECT_HEAT_UP_TIMEOUT; + stopHeater( DG_TRIMMER_HEATER ); } + else if ( ( TDiTempC < HEAT_DISINFECT_TRIMMER_HEATER_STOP_TEMP_C ) && ( FALSE == isHeaterOn( DG_TRIMMER_HEATER ) ) ) + { + setHeaterTargetTemperature( DG_TRIMMER_HEATER, HEAT_DISINFECT_TRIM_HEATER_TARGET_TEMP_C ); + startHeater( DG_TRIMMER_HEATER ); + } } - else if ( ( isPartialDisinfectInProgress != TRUE ) && ( ThdTemp > HEAT_DISINFECT_START_TEMPERATURE_C ) ) + } + + // Perform check if no pending alarm + if ( ALARM_ID_NO_ALARM == alarmDetectedPendingTrigger ) + { + BOOL disinfectStatus = FALSE; + + if ( TPoTempC >= concPumpsStartTemperatureC ) { - // The temperature of the coldest spot is in range to start the disinfect timer - heatDisinfectTimer = getMSTimerCount(); - isPartialDisinfectInProgress = TRUE; - targetDisinfectTime = HEAT_DISINFECT_TIME_MS; - status = HEAT_DISINFECT_DISINFECT_IN_PROGRESS; + F32 acidSpeed = getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP1_ACID ); + F32 bicarbSpeed = getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB ); - // Turn the pumps on in reverse - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, ACID_PUMP_SPEED_ML_PER_MIN ); - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, BICARB_PUMP_SPEED_ML_PER_MIN ); + if ( ( acidSpeed < NEARLY_ZERO ) || ( bicarbSpeed < NEARLY_ZERO ) ) + { + // Turn the pumps on in reverse + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, ACID_PUMP_SPEED_ML_PER_MIN ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, BICARB_PUMP_SPEED_ML_PER_MIN ); - // During R1 to R2 disinfect, the concentrate pumps turn on - requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); - requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); + // During R1 to R2 disinfect, the concentrate pumps turn on + requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); + } } + + // Check whether the reservoir under disinfect has elapsed time. + disinfectStatus |= hasDisinfectTimeElapsed( RSRVR_AT_77_C ); + disinfectStatus |= hasDisinfectTimeElapsed( RSRVR_AT_82_C ); + + // If either of the reservoir's disinfect time has elapsed, call this section complete + status = ( TRUE == disinfectStatus ? HEAT_DISINFECT_COMPLETE : status ); } - // Perform check if no pending alarm - if ( ALARM_ID_NO_ALARM == alarmDetectedPendingTrigger ) + return status; +} + +/*********************************************************************//** + * @brief + * The hasDisinfectTimeElapsed function checks whether the disinfect time of + * either reservoirs or the RO filter has been elapsed. + * @details Inputs: timeStatus + * @details Outputs: timeStatus + * @param disinfectTime which is the time to check (i.e reservoir at 77 C or + * RO disinfect at 82 C) + * @return TRUE if the specified time has been elapsed otherwise FALSE + *************************************************************************/ +static BOOL hasDisinfectTimeElapsed( HEAT_DISINFECT_TIMES_T disinfectTime ) +{ + BOOL status = FALSE; + F32 temperatureValue = getTemperatureValue( timeStatus[ disinfectTime ].tempSensor ); + + if ( temperatureValue >= timeStatus[ disinfectTime ].startTempC ) { - // If heat disinfect temperature has been reached, check if this stage of heat disinfect is done - if ( ( TRUE == isPartialDisinfectInProgress ) && ( TRUE == didTimeout( heatDisinfectTimer, HEAT_DISINFECT_TIME_MS ) ) ) + // If the temperature of the specified temperature sensor has elapsed the start temperature and the start timer is in reset (it is 0) + // start the timer. + // If the timer has started and time of the disinfect has elapsed, set the status to TRUE. + if ( 0 == timeStatus[ disinfectTime ].startTimeMS ) { - // Done with this stage of heat disnfect. Reset the variables - // Target disinfect time is the time that is published to the UI and when there is - // no disinfect count down, this variable is set to 0. When the target time is 0, the UI - // hides the timer on the UI disinfect screen - targetDisinfectTime = 0; - status = HEAT_DISINFECT_COMPLETE; - isPartialDisinfectInProgress = FALSE; + timeStatus[ disinfectTime ].startTimeMS = getMSTimerCount(); } + else if ( TRUE == didTimeout( timeStatus[ disinfectTime ].startTimeMS, timeStatus[ disinfectTime ].targetTimeMS ) ) + { + + status = TRUE; + } } + else if ( temperatureValue < timeStatus[ disinfectTime ].stopTempC ) + { + // If the temperature dropped below the target, reset the timer + timeStatus[ disinfectTime ].startTimeMS = 0; + } return status; } @@ -1733,36 +1919,20 @@ MODE_HEAT_DISINFECT_DATA_T data; MODE_HEAT_DISINFECT_UI_DATA_T uiData; - data.heatDisinfectState = (U32)heatDisinfectState; - data.overallElapsedTime = calcTimeSince( overallHeatDisinfectTimer ); - data.stateElapsedTime = calcTimeSince( stateTimer ); - data.cancellationMode = (U32)cancellationMode; - data.heatDisinfectUIState = (U32)heatDisinfectUIState; + data.heatDisinfectState = (U32)heatDisinfectState; + data.overallElapsedTime = calcTimeSince( overallHeatDisinfectTimer ); + data.stateElapsedTime = calcTimeSince( stateTimer ); + data.cancellationMode = (U32)cancellationMode; + data.heatDisinfectUIState = (U32)heatDisinfectUIState; + uiData.heatDisinfectTargetTime = targetDisinfectTime; + uiData.ro77CountdownTimeS = ( 0 == timeStatus[ RO_AT_77_C ].startTimeMS ? 0 : ( timeStatus[ RO_AT_77_C ].targetTimeMS - calcTimeSince( timeStatus[ RO_AT_77_C ].startTimeMS ) ) / 1000 ); // The count down is converted into seconds since the UI does not work with milliseconds + uiData.ro82CountdownTimeS = ( 0 == timeStatus[ RO_AT_82_C ].startTimeMS ? 0 : ( timeStatus[ RO_AT_82_C ].targetTimeMS - calcTimeSince( timeStatus[ RO_AT_82_C ].startTimeMS ) ) / 1000 ); + uiData.r77CountdownTimeS = ( 0 == timeStatus[ RSRVR_AT_77_C ].startTimeMS ? 0 : ( timeStatus[ RSRVR_AT_77_C ].targetTimeMS - calcTimeSince( timeStatus[ RSRVR_AT_77_C ].startTimeMS ) ) / 1000 ); + uiData.r82CountdownTimeS = ( 0 == timeStatus[ RSRVR_AT_82_C ].startTimeMS ? 0 : ( timeStatus[ RSRVR_AT_82_C ].targetTimeMS - calcTimeSince( timeStatus[ RSRVR_AT_82_C ].startTimeMS ) ) / 1000 ); + data.R1FillLevel = rsrvr1RefVolML; + data.R2FillLevel = rsrvr2RefVolML; - // If the mode is in the actual heat disinfect states, publish the elapsed time, otherwise publish 0 to avoid confusion - if ( ( DG_HEAT_DISINFECT_STATE_DISINFECT_R1_TO_R2 == heatDisinfectState ) || - ( DG_HEAT_DISINFECT_STATE_DISINFECT_R2_TO_R1 == heatDisinfectState ) ) - { - // If the disinfect target time is 0, meaning the actual disinfect has not started, set the count down to 0, otherwise, publish - // the actual value - U32 countDown = ( HEAT_DISINFECT_TIME_MS == targetDisinfectTime ? ( targetDisinfectTime - calcTimeSince( heatDisinfectTimer) ) : 0 ); - - uiData.heatDisinfectTargetTime = targetDisinfectTime; - uiData.heatDisinfectCountdownTime = countDown / 1000; // The count down is converted into seconds since the UI does not work with milliseconds - data.R1FillLevel = rsrvr1RefVolML; - data.R2FillLevel = rsrvr2RefVolML; - } - else - { - uiData.heatDisinfectTargetTime = 0; - uiData.heatDisinfectCountdownTime = 0; - data.R1FillLevel = 0.0; - data.R2FillLevel = 0.0; - } - broadcastData( MSG_ID_DG_HEAT_DISINFECT_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( MODE_HEAT_DISINFECT_DATA_T ) ); - - // Publish data to UI broadcastData( MSG_ID_DG_HEAT_DISINFECT_TIME_DATA, COMM_BUFFER_OUT_CAN_DG_2_UI, (U08*)&uiData, sizeof( MODE_HEAT_DISINFECT_UI_DATA_T ) ); dataPublishCounter = 0; @@ -1781,32 +1951,30 @@ *************************************************************************/ static void monitorModeHeatDisinfect( void ) { - BOOL areInletWaterAlarmsActive = FALSE; + // Constantly check the status of the RO disinfect + isRODisinfectDone |= hasDisinfectTimeElapsed( RO_AT_77_C ); + isRODisinfectDone |= hasDisinfectTimeElapsed( RO_AT_82_C ); #ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_CAPS_MONITOR ) != SW_CONFIG_ENABLE_VALUE ) + if ( ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_CAPS_MONITOR ) != SW_CONFIG_ENABLE_VALUE ) && ( nelsonSupport != NELSON_INOCULATE ) ) #endif { if ( ( STATE_OPEN == getSwitchStatus( CONCENTRATE_CAP ) ) || ( STATE_OPEN == getSwitchStatus( DIALYSATE_CAP ) ) ) { // Set the variables to fail and go to cancel water path. Set the pending alarm to no alarm so the cancel water path // will not be raising the alarm at end of the cancel water path. The recoverable alarm is raised here in this function - U32 cap = (U32)( STATE_OPEN == getSwitchStatus( CONCENTRATE_CAP ) ? CONCENTRATE_CAP : DIALYSATE_CAP ); prevHeatDisinfectState = heatDisinfectState; heatDisinfectState = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; - alarmDetectedPendingTrigger = ALARM_ID_DG_DIALYSATE_OR_CONC_CAP_NOT_IN_PROPER_POSITION; + alarmDetectedPendingTrigger = ALARM_ID_DG_DIALYSATE_CAP_NOT_IN_PROPER_POSITION; + + if ( STATE_OPEN == getSwitchStatus( CONCENTRATE_CAP ) ) + { + alarmDetectedPendingTrigger = ALARM_ID_DG_CONCENTRATE_CAP_NOT_IN_PROPER_POSITION; + } } } - areInletWaterAlarmsActive |= isAlarmActive( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_TEMP_TOO_HIGH ); - areInletWaterAlarmsActive |= isAlarmActive( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_TEMP_TOO_LOW ); - areInletWaterAlarmsActive |= isAlarmActive( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_PRESSURE_TOO_HIGH ); - areInletWaterAlarmsActive |= isAlarmActive( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_PRESSURE_TOO_LOW ); - areInletWaterAlarmsActive |= isAlarmActive( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_COND_TOO_HIGH ); - areInletWaterAlarmsActive |= isAlarmActive( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_COND_TOO_LOW ); - areInletWaterAlarmsActive |= isAlarmActive( ALARM_ID_DG_DIALYSATE_TEMPERATURE_SENSORS_OUT_OF_RANGE ); - - if ( ( TRUE == areInletWaterAlarmsActive ) ) + if ( ( TRUE == isDGFaultAlarmActive() ) && ( heatDisinfectState != DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH ) ) { prevHeatDisinfectState = heatDisinfectState; heatDisinfectState = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; @@ -1832,3 +2000,179 @@ } /**@}*/ + +// ********** Nelson Support Functions ********** + +#ifndef _RELEASE_ +/*********************************************************************//** + * @brief + * The setNelsonSupportConditions function sets the disinfect variables for + * Nelson support. + * @details Inputs: nelsonSupport + * @details Outputs: timeStatus, heatDisinfectState, concPumpsStartTemperatureC + * @return: none + *************************************************************************/ +static void setNelsonSupportConditions( void ) +{ + switch ( nelsonSupport ) + { + case NELSON_INOCULATE: + concPumpsStartTemperatureC = NELSON_SUPPORT_TARGET_TEMP_C; + timeStatus[ RO_AT_77_C ].startTempC = NELSON_SUPPORT_TARGET_TEMP_C; + timeStatus[ RO_AT_77_C ].startTimeMS = 0; + timeStatus[ RO_AT_77_C ].stopTempC = NELSON_SUPPORT_STOP_TEMP_C; + timeStatus[ RO_AT_77_C ].targetTimeMS = NELSON_SUPPORT_INOCULATE_TIME_MS; + timeStatus[ RO_AT_77_C ].tempSensor = TEMPSENSORS_HEAT_DISINFECT; + + timeStatus[ RO_AT_82_C ].startTempC = NELSON_SUPPORT_TARGET_TEMP_C; + timeStatus[ RO_AT_82_C ].startTimeMS = 0; + timeStatus[ RO_AT_82_C ].stopTempC = NELSON_SUPPORT_STOP_TEMP_C; + timeStatus[ RO_AT_82_C ].targetTimeMS = NELSON_SUPPORT_INOCULATE_TIME_MS; + timeStatus[ RO_AT_82_C ].tempSensor = TEMPSENSORS_HEAT_DISINFECT; + + timeStatus[ RSRVR_AT_77_C ].startTempC = NELSON_SUPPORT_TARGET_TEMP_C; + timeStatus[ RSRVR_AT_77_C ].startTimeMS = 0; + timeStatus[ RSRVR_AT_77_C ].stopTempC = NELSON_SUPPORT_STOP_TEMP_C; + // Set 82 C time to be the shorter time since the entire inoculation time should be 30 mins but the 77 C is 32 minutes + timeStatus[ RSRVR_AT_77_C ].targetTimeMS = HEAT_DISINFECT_AT_82_C_TIME_MS; + timeStatus[ RSRVR_AT_77_C ].tempSensor = TEMPSENSORS_INLET_DIALYSATE; + + timeStatus[ RSRVR_AT_82_C ].startTempC = NELSON_SUPPORT_TARGET_TEMP_C; + timeStatus[ RSRVR_AT_82_C ].startTimeMS = 0; + timeStatus[ RSRVR_AT_82_C ].stopTempC = NELSON_SUPPORT_STOP_TEMP_C; + timeStatus[ RSRVR_AT_82_C ].targetTimeMS = HEAT_DISINFECT_AT_82_C_TIME_MS; + timeStatus[ RSRVR_AT_82_C ].tempSensor = TEMPSENSORS_INLET_DIALYSATE; + break; + + case NELSON_POS_CONTROL_HEAT_DISINFECT: + concPumpsStartTemperatureC = NELSON_SUPPORT_TARGET_TEMP_C; + timeStatus[ RO_AT_77_C ].startTempC = NELSON_SUPPORT_TARGET_TEMP_C; + timeStatus[ RO_AT_77_C ].startTimeMS = 0; + timeStatus[ RO_AT_77_C ].stopTempC = NELSON_SUPPORT_STOP_TEMP_C; + timeStatus[ RO_AT_77_C ].targetTimeMS = NELSON_SUPPORT_DISINFECT_TIME_MS; + timeStatus[ RO_AT_77_C ].tempSensor = TEMPSENSORS_HEAT_DISINFECT; + + timeStatus[ RO_AT_82_C ].startTempC = NELSON_SUPPORT_TARGET_TEMP_C; + timeStatus[ RO_AT_82_C ].startTimeMS = 0; + timeStatus[ RO_AT_82_C ].stopTempC = NELSON_SUPPORT_STOP_TEMP_C; + timeStatus[ RO_AT_82_C ].targetTimeMS = NELSON_SUPPORT_DISINFECT_TIME_MS; + timeStatus[ RO_AT_82_C ].tempSensor = TEMPSENSORS_HEAT_DISINFECT; + + timeStatus[ RSRVR_AT_77_C ].startTempC = NELSON_SUPPORT_TARGET_TEMP_C; + timeStatus[ RSRVR_AT_77_C ].startTimeMS = 0; + timeStatus[ RSRVR_AT_77_C ].stopTempC = NELSON_SUPPORT_STOP_TEMP_C; + timeStatus[ RSRVR_AT_77_C ].targetTimeMS = HEAT_DISINFECT_AT_82_C_TIME_MS; + timeStatus[ RSRVR_AT_77_C ].tempSensor = TEMPSENSORS_INLET_DIALYSATE; + + timeStatus[ RSRVR_AT_82_C ].startTempC = NELSON_SUPPORT_TARGET_TEMP_C; + timeStatus[ RSRVR_AT_82_C ].startTimeMS = 0; + timeStatus[ RSRVR_AT_82_C ].stopTempC = NELSON_SUPPORT_STOP_TEMP_C; + timeStatus[ RSRVR_AT_82_C ].targetTimeMS = HEAT_DISINFECT_AT_82_C_TIME_MS; + timeStatus[ RSRVR_AT_82_C ].tempSensor = TEMPSENSORS_INLET_DIALYSATE; + setValveState( VPI, VALVE_STATE_CLOSED ); + setValveState( VBF, VALVE_STATE_OPEN ); + setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState( VDR, VALVE_STATE_RECIRC_C_TO_NC ); + setValveState( VRC, VALVE_STATE_RECIRC_C_TO_NC ); + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); + 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 ); + signalROPumpHardStop(); + setDrainPumpTargetOutletFlowLPM( HEAT_DISINFECT_TARGET_RO_FLOW_LPM ); + heatDisinfectState = DG_HEAT_DISINFECT_STATE_DISINFECT_R1_TO_R2; + break; + + case NELSON_HEAT_DISINFECT: + // Set the valves to drain R2 and no fill + setValveState( VPI, VALVE_STATE_CLOSED ); + setValveState( VBF, VALVE_STATE_OPEN ); + setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState( VDR, VALVE_STATE_RECIRC_C_TO_NC ); + setValveState( VRC, VALVE_STATE_RECIRC_C_TO_NC ); + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); + 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 ); + signalROPumpHardStop(); + setDrainPumpTargetOutletFlowLPM( HEAT_DISINFECT_TARGET_RO_FLOW_LPM ); + setHeaterTargetTemperature( DG_PRIMARY_HEATER, HEAT_DISINFECT_PRIM_HEATER_TARGET_TEMP_C ); + setHeaterTargetTemperature( DG_TRIMMER_HEATER, HEAT_DISINFECT_TRIM_HEATER_TARGET_TEMP_C ); + startHeater( DG_PRIMARY_HEATER ); + startHeater( DG_TRIMMER_HEATER ); + heatDisinfectState = DG_HEAT_DISINFECT_STATE_DISINFECT_R1_TO_R2; + break; + + case NELSON_DRAIN_SAMPLES: + heatDisinfectState = DG_HEAT_DISINFECT_STATE_START; + break; + + case NELSON_NONE: + default: + // Do nothing for these cases. + break; + } +} + +/*********************************************************************//** + * @brief + * The handleNelsonHeatDisinfectFillR1WithWaterState function handles the Nelson + * fill reservoir 1 with water. + * @details Inputs: rsrvr1Status, rsrvr2Status + * @details Outputs: rsrvr1Status, rsrvr2Status, prevHeatDisinfectState + * @return next state of the heat disinfect state machine + *************************************************************************/ +static DG_HEAT_DISINFECT_STATE_T handleNelsonHeatDisinfectFillR1WithWaterState( void ) +{ + DG_HEAT_DISINFECT_STATE_T state = DG_NELSON_HEAT_DISINFECT_STATE_FILL_R1_WITH_WATER; + + // First reservoir 2 must be partially full + if ( DG_RESERVOIR_BELOW_TARGET == rsrvr2Status ) + { + rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_500ML_FILL_UP_TIMEOUT_MS ); + } + else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) + { + rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_1, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS ); + + if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) + { + deenergizeActuators( NO_PARK_CONC_PUMPS ); + state = DG_HEAT_DISINFECT_STATE_COMPLETE; + } + else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) + { + prevHeatDisinfectState = state; + state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; + } + } + else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) + { + prevHeatDisinfectState = state; + state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; + } + + return state; +} + +#endif + +#ifndef _RELEASE_ +/*********************************************************************//** + * @brief + * The setHeatNelsonSupportMode function sets the requested Nelson support + * mode (i.e. inoculate, ...) + * @details Inputs: none + * @details Outputs: nelsonSupport + * @param support the type Nelson support (i.e. inoculate, heat disinfect) + * @return none + *************************************************************************/ +void setHeatNelsonSupportMode( NELSON_SUPPORT_T support ) +{ + nelsonSupport = support; +} +#endif