Index: firmware/App/Modes/ModeHeatDisinfect.c =================================================================== diff -u -r9e5ee62245eb2a73b167eabd6c274a71a76a7b0e -r1440a4a2be8d12edebd405a20807882e5d32d619 --- firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 9e5ee62245eb2a73b167eabd6c274a71a76a7b0e) +++ firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 1440a4a2be8d12edebd405a20807882e5d32d619) @@ -78,15 +78,19 @@ #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 82.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_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. @@ -95,6 +99,8 @@ #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. @@ -125,12 +131,41 @@ 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; + +/// Heat disinfect reset time enum +typedef enum Heat_Disinfect_Reset_Time +{ + RESET_NONE = 0, ///< Heat disinfect reset no disinfect timer. + RESET_RO, ///< Heat disinfect reset RO disinfect timers. + RESET_RSRVR, ///< Heat disinfect reset reservoirs disinfect timers. + NUM_OF_RESETS ///< Number of heat disinfect resets. +} RESET_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 +180,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,6 +191,7 @@ 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. // ********** private function prototypes ********** @@ -185,6 +219,7 @@ 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, RESET_DISINFECT_TIMES_T reset ); static void publishHeatDisinfectData( void ); static void monitorModeHeatDisinfect( void ); static void writeDisinfectDataToNV( DG_USAGE_INFO_ITEMS_T info ); @@ -202,7 +237,7 @@ * hasROFCirculationBeenStarted, ROFCirculationTimer, targetDisinfectTime * ROFCirculationCoolingCounter, concentratePumpsPrimeTimer, areRsrvrsLeaking * haveDrainParamsBeenInit, tempGradOutOfRangeTimer, disinfectNVOps, - * dataPublishCounter + * dataPublishCounter, timeStatus * @return none *************************************************************************/ void initHeatDisinfectMode( void ) @@ -220,7 +255,6 @@ overallHeatDisinfectTimer = 0; cancellationMode = CANCELLATION_MODE_NONE; rsrvrFillStableTimeCounter = 0; - isPartialDisinfectInProgress = FALSE; isDrainPumpInMixDrainOn = FALSE; concentratePumpsPrimeTimer = 0; targetDisinfectTime = 0; @@ -229,10 +263,34 @@ tempGradOutOfRangeTimer = 0; disinfectNVOps.hasDisStatusBeenWrittenToNV = FALSE; alarmDetectedPendingTrigger = ALARM_ID_NO_ALARM; - heatDisinfectTimer = 0; rsrvrsVolMonitorTimer = 0; areRsrvrsLeaking = FALSE; dataPublishCounter = 0; + + // 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; } /*********************************************************************//** @@ -639,7 +697,7 @@ 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 ); + 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 @@ -893,7 +951,7 @@ 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 ); + setHeaterTargetTemperature( DG_PRIMARY_HEATER, HEAT_DISINFECT_PRIM_HEATER_TARGET_TEMP_C ); startHeater( DG_PRIMARY_HEATER ); rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; @@ -954,10 +1012,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(); rsrvrsVolMonitorTimer = getMSTimerCount(); state = DG_HEAT_DISINFECT_STATE_DISINFECT_R1_TO_R2; @@ -994,6 +1048,11 @@ DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_DISINFECT_R1_TO_R2; HEAT_DISINFECT_STATUS_T status = getHeatDisinfectStatus(); + // Constantly check the status of the RO disinfect times and do not reset its start time + // in case it elapsed before disinfecting the reservoirs. + hasDisinfectTimeElapsed( RO_AT_77_C, RESET_NONE ); + hasDisinfectTimeElapsed( RO_AT_82_C, RESET_NONE ); + if ( FALSE == isROPumpRunning() ) { setROPumpTargetDutyCycle( HEAT_DISINFECT_TARGET_RO_PUMP_DC ); @@ -1031,13 +1090,8 @@ 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; @@ -1078,6 +1132,11 @@ heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_TRANSITION_HOT_WATER; + // Constantly check the status of the RO disinfect times and do not reset its start time + // in case it elapsed before disinfecting the reservoirs. + hasDisinfectTimeElapsed( RO_AT_77_C, RESET_NONE ); + hasDisinfectTimeElapsed( RO_AT_82_C, RESET_NONE ); + // First reservoir 1 must be partially full if ( DG_RESERVOIR_BELOW_TARGET == rsrvr1Status ) { @@ -1092,10 +1151,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; } @@ -1129,9 +1184,15 @@ { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_DISINFECT_R2_TO_R1; HEAT_DISINFECT_STATUS_T status = getHeatDisinfectStatus(); + BOOL isRODisinfectDone = FALSE; heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_DISINFECT_RESERVOIR_2; + // Constantly check the status of the RO disinfect times and do not reset its start time + // in case it elapsed before disinfecting the reservoirs. + isRODisinfectDone |= hasDisinfectTimeElapsed( RO_AT_77_C, RESET_NONE ); + isRODisinfectDone |= hasDisinfectTimeElapsed( RO_AT_82_C, RESET_NONE ); + if ( TRUE == didTimeout( stateTimer, HEAT_DISINFECT_REF_RSRVR_TIMEOUT_MS ) ) { if ( ( rsrvr1RefVolML < NEARLY_ZERO ) && ( rsrvr2RefVolML < NEARLY_ZERO ) ) @@ -1152,13 +1213,19 @@ 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 ) + { + // RO disinfect has been elapsed, call the function to reset the RO start time + hasDisinfectTimeElapsed( RO_AT_77_C, RESET_RO ); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID, NO_PARK_CONC_PUMPS ); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); + stopHeater( DG_PRIMARY_HEATER ); + + rsrvr1RefVolML = 0.0F; + rsrvr2RefVolML = 0.0F; + stateTimer = getMSTimerCount(); + state = DG_HEAT_DISINFECT_STATE_COOL_DOWN_HEATERS; + } break; case HEAT_DISINFECT_HEAT_UP_IN_PROGRESS: @@ -1548,7 +1615,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 = hasTargetDrainVolumeBeenReached( r, drainSteadyStateTimeout ); + BOOL isDrainComplete = FALSE; // If the drain parameters of the reservoir is not initialized, initialize them if ( FALSE == haveDrainParamsBeenInit[ r ] ) @@ -1557,6 +1624,10 @@ haveDrainParamsBeenInit[ r ] = TRUE; } + // 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 ) ) @@ -1615,6 +1686,13 @@ 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 ); + if ( TRUE == didTimeout( stateTimer, HEAT_DISINFECT_START_TEMP_TIMOUT_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 ) { @@ -1666,55 +1744,84 @@ // 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 ) + BOOL disinfectStatus = FALSE; + + if ( TPoTemp >= HEAT_DISINFECT_CONC_PUMPS_START_TEMP_C ) { - // Keep reseting the disinfect timer so the elapsed time is always 0 until disinfect truly starts - heatDisinfectTimer = getMSTimerCount(); - isPartialDisinfectInProgress = FALSE; - targetDisinfectTime = 0; + F32 acidSpeed = getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP1_ACID ); + F32 bicarbSpeed = getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB ); - if ( TRUE == didTimeout( stateTimer, HEAT_DISINFECT_START_TEMP_TIMOUT_MS ) ) + if ( ( acidSpeed < NEARLY_ZERO ) || ( bicarbSpeed < NEARLY_ZERO ) ) { - // Heating up to minimum temperature for heat disinfect failed - alarmDetectedPendingTrigger = ALARM_ID_DG_HEAT_DISINFECT_TARGET_TEMP_TIMEOUT; - status = HEAT_DISINFECT_HEAT_UP_TIMEOUT; + // 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 ); } } - else if ( ( isPartialDisinfectInProgress != TRUE ) && ( ThdTemp > HEAT_DISINFECT_START_TEMPERATURE_C ) ) - { - // 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; - // 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 ); + // Check whether the reservoir under disinfect has elapsed time. + disinfectStatus |= hasDisinfectTimeElapsed( RSRVR_AT_77_C, RESET_RSRVR ); + disinfectStatus |= hasDisinfectTimeElapsed( RSRVR_AT_82_C, RESET_RSRVR ); - // During R1 to R2 disinfect, the concentrate pumps turn on - requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); - requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); - } + // 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) + * @param reset which is the type of reset timer (i.e. reset reservoirs) + * @return TRUE if the specified time has been elapsed otherwise FALSE + *************************************************************************/ +static BOOL hasDisinfectTimeElapsed( HEAT_DISINFECT_TIMES_T disinfectTime, RESET_DISINFECT_TIMES_T reset ) +{ + 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 ) ) + { + // If either of the reservoir's disinfect has been elapsed, reset the timer for both to get ready for the next reservoir's disinfect + // The RO time is not reset because the RO disinfect time is not checked until both reservoirs are disinfected first. + if ( RESET_RO == reset ) + { + timeStatus[ RO_AT_77_C ].startTimeMS = 0; + timeStatus[ RO_AT_82_C ].startTimeMS = 0; + } + else if ( RESET_RSRVR == reset ) + { + timeStatus[ RSRVR_AT_77_C ].startTimeMS = 0; + timeStatus[ RSRVR_AT_82_C ].startTimeMS = 0; + } + + status = TRUE; + } } + else if ( temperatureValue < timeStatus[ disinfectTime ].stopTempC ) + { + // If the temperature dropped below the target, reset the timer + timeStatus[ disinfectTime ].startTimeMS = 0; + } return status; } @@ -1734,36 +1841,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;