Index: firmware/App/Modes/ModeHeatDisinfect.c =================================================================== diff -u -rb57941bb4258fd7fb44fc1ea5057de80b322f867 -r2c08db070a6e09306caf461e7aceeb53097fd995 --- firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision b57941bb4258fd7fb44fc1ea5057de80b322f867) +++ firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 2c08db070a6e09306caf461e7aceeb53097fd995) @@ -1,14 +1,14 @@ /************************************************************************** * -* Copyright (c) 2020-2022 Diality Inc. - All Rights Reserved. +* Copyright (c) 2020-2023 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file ModeHeatDisinfect.c * * @author (last) Dara Navaei -* @date (last) 24-Oct-2022 +* @date (last) 21-Dec-2022 * * @author (original) Sean * @date (original) 20-Apr-2020 @@ -19,6 +19,7 @@ #include "ConcentratePumps.h" #include "ConductivitySensors.h" +#include "CPLD.h" #include "DrainPump.h" #include "Heaters.h" #include "LoadCell.h" @@ -38,7 +39,6 @@ #include "Timers.h" #include "UVReactors.h" #include "Valves.h" -#include "CPLD.h" /** * @addtogroup DGHeatDisinfectMode @@ -51,36 +51,31 @@ #define MAX_ALLOWED_STATE_TRIALS 1 ///< Max allowed trials on a state. This is general among all the states. #define HEAT_DISINFECT_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Mode heat disinfect data publish interval in counts. -// Start state defines -#define MIN_INLET_PRESSURE_PSI 30.0F ///< Minimum water inlet pressure in psi. -#define MAX_START_STATE_TEMP_SENSORS_DIFF_C 3.0F ///< Max start state TDi and TRo difference tolerance in C. - // 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. // Flush drain path state defines -#define FLUSH_DRAIN_WAIT_TIME_MS ( SEC_PER_MIN * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. -#define MIN_INLET_TEMPERATURE_C 25.0F ///< Minimum water inlet temperature in C. -#define MAX_INLET_CONDUCTIVITY_US_PER_CM 2000.0F ///< Maximum water inlet conductivity in us/cm +#define FLUSH_DRAIN_WAIT_TIME_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. // Flush circulation path state defines #define RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM 0.8F ///< RO pump target flow rate during flush/fill in L/min. #define MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI 130 ///< Maximum RO pump pressure during flush/fill states in psi. -#define FLUSH_CICRCULATION_WAIT_TIME_MS ( 30 * MS_PER_SECOND ) ///< Flush/rinse circulation path wait time in milliseconds. TODO original time was 30 seconds -#define MAX_FLUSH_CIRC_TEMP_SENSOR_DIFF_C 50.0F ///< Maximum flush circulation temperature difference tolerance in C. TODO original difference was 3.0 degrees -#define NUM_OF_TEMP_SENSORS_TO_AVG 4.0F ///< Number of temperature sensors to average to check the difference. -#define ACID_PUMP_SPEED_ML_PER_MIN -30.0F ///< Acid concentrate pump speed in mL/min. +#define FLUSH_CICRCULATION_WAIT_TIME_MS ( 60 * MS_PER_SECOND ) ///< Flush circulation path wait time in milliseconds. +#define FLUSH_CIRCULATION_CONC_PUMPS_WAIT_TIME_MS ( 3 * SEC_PER_MIN * MS_PER_SECOND ) ///< Flush circulation concentrate pumps on time in milliseconds. +#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 -#define BICARB_PUMP_SPEED_ML_PER_MIN 30.6F ///< Bicarb concentrate pump speed in mL/min. +#define BICARB_PUMP_SPEED_ML_PER_MIN -30.0F ///< Bicarb concentrate pump speed in mL/min. // Flush and drain R1 and R2 -#define RSRVRS_FULL_VOL_ML 1850.0F ///< Reservoirs 1 & 2 full volume in mL. TODo original value was 1900 +#define RSRVRS_FULL_VOL_ML 1900.0F ///< Reservoirs 1 & 2 full volume in mL. #define RSRVRS_PARTIAL_FILL_VOL_ML 500.0F ///< Reservoirs 1 & 2 partial volume in mL. #define RSRVRS_FULL_STABLE_TIME_COUNT ( ( 4 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Reservoirs 1 & 2 full stable time in counts. -#define RSRVRS_FILL_UP_TIMEOUT_MS ( 5 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 full fill up timeout in ms. TODO original value was 5 mins -#define RSRVRS_500ML_FILL_UP_TIMEOUT_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 partial fill up timeout in ms. +#define RSRVRS_FILL_UP_TIMEOUT_MS ( 5 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 full fill up timeout in ms. +#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 @@ -89,31 +84,23 @@ // 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_TARGET_DRAIN_PRES_PSI 12.0F ///< Heat disinfect target drain outlet 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 ( 10 * 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 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 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. -// Cool down RO filter -#define THD_REACH_BELOW_45_AFTER_CIRC_TIME_MS ( 5 * MS_PER_SECOND ) ///< Number of circulations that are needed to make the RO filter is below 45 C. -#define ROF_COOL_DOWN_TARGET_FLOW_LPM 0.3F ///< RO filter cool down target flow in L/min. -#define ROF_COOL_DOWN_CIRCULATION_TIME_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< RO filter cool down circulation timer in milliseconds. -#define TARGET_THD_SENSOR_FOR_RINSING_C 44.0F ///< Target THd temperature sensor value before rinsing in C. - // 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. #define DRAIN_PUMP_START_TIME_IN_MIX_DRAIN_MS ( 5 * MS_PER_SECOND ) ///< Time to start the drain pump at mix drain after directing the flow to drain in ms. #define DRAIN_PUMP_RPM_IN_MIX_DRAIN 600 ///< The RPM that the drain pump should be run during mix drain. #define MIX_DRAIN_WEIGHT_UNCHANGE_TIMEOUT ( 15 * MS_PER_SECOND ) ///< Time period of unchanged weight during mix draining before timeout. - -// Rinse R1 to R2 -#define ROF_MIN_LOW_PRESSURE_TEMPERATURE_C 45.0F ///< RO filter minimum temperature that the pressure must be no more than 30psi in C. - #define MIX_DRAIN_TEMPERATURE_THRESHOLD_C 60.0F ///< Temperature threshold for performing mix drain or normal drain. /// Cancellation paths @@ -142,38 +129,32 @@ typedef struct { BOOL hasDisStatusBeenWrittenToNV; ///< Boolean flag to indicate whether the disinfect status been written to NV or not. - BOOL hasDisCompleteDateBeenWrittenToNV; ///< Boolean flag to indicate whether the disinfect complete date been written to NV or not. } DISINFECT_NV_OPS_T; // ********** private data ********** -static DG_HEAT_DISINFECT_STATE_T heatDisinfectState = DG_HEAT_DISINFECT_STATE_START; ///< Current active heat disinfect state. -static DG_HEAT_DISINFECT_STATE_T prevHeatDisinfectState = DG_HEAT_DISINFECT_STATE_START; ///< Previous active heat disinfect state before alarm. -static DG_HEAT_DISINFECT_UI_STATE_T heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_NOT_RUNNING; ///< Current active heat disinfect UI state. -static U32 overallHeatDisinfectTimer = 0; ///< Heat disinfect cycle total timer. -static U32 stateTimer = 0; ///< Heat disinfect state timer to be used in different states. -static U32 stateTrialCounter = 0; ///< Heat disinfect state trial counter to be used for retries in different states. -static BOOL areTempSensorsInRange = FALSE; ///< Heat disinfect temperature sensors in/out range flag. -static U32 concentratePumpsPrimeTimer = 0; ///< Concentrate pumps prime timer. -/// Boolean flag to check whether draining R1 and R2 is at the end of the heat disinfect cycle or in the beginning. So the drain states can be reused. -static BOOL isThisLastDrain = FALSE; -static DG_RESERVOIR_STATUS_T rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; ///< Reservoir 1 status. -static DG_RESERVOIR_STATUS_T rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; ///< Reservoir 2 status. -static F32 R1HeatDisinfectVol = 0.0; ///< Reservoir 1 full volume during heat disinfect. -static F32 R2HeatDisinfectVol = 0.0; ///< Reservoir 2 full volume during heat disinfect. -static U32 heatDisinfectTimer = 0; ///< Heat disinfect timer. -static BOOL isPartialDisinfectInProgress = FALSE; ///< Heat disinfect partial complete/in progess flag. -static U32 rsrvrsVolMonitorTimer = 0; ///< Reservoir 1 & 2 volume monitor timers during heat disinfect. -static BOOL areRsrvrsLeaking = FALSE; ///< Reservoir 1 & 2 leak check flag during heat disinfect. -static U32 dataPublishCounter = 0; ///< Heat Disinfect data publish counter. -static CANCELLATION_MODE_T cancellationMode = CANCELLATION_MODE_NONE; ///< Cancellation mode. +static DG_HEAT_DISINFECT_STATE_T heatDisinfectState; ///< Current active heat disinfect state. +static DG_HEAT_DISINFECT_STATE_T prevHeatDisinfectState; ///< Previous active heat disinfect state before alarm. +static DG_HEAT_DISINFECT_UI_STATE_T heatDisinfectUIState; ///< Current active heat disinfect UI state. +static U32 overallHeatDisinfectTimer; ///< Heat disinfect cycle total timer. +static U32 stateTimer; ///< Heat disinfect state timer to be used in different states. +static U32 stateTrialCounter; ///< Heat disinfect state trial counter to be used for retries in different states. +static BOOL areTempSensorsInRange; ///< Heat disinfect temperature sensors in/out range flag. +static U32 concentratePumpsPrimeTimer; ///< Concentrate pumps prime timer. +static DG_RESERVOIR_STATUS_T rsrvr1Status; ///< Reservoir 1 status. +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. +static CANCELLATION_MODE_T cancellationMode; ///< Cancellation mode. static U32 rsrvrFillStableTimeCounter; ///< Reservoirs fill stable time counter. static ALARM_ID_T alarmDetectedPendingTrigger; ///< Heat disinfect alarm to raise. -static BOOL isDrainPumpInMixDrainOn = FALSE; ///< Flag to indicate the drain pump is on during mix drain. -static U32 ROFCirculationTimer = 0; ///< RO filter circulation timer. -static U32 ROFCoolingTimer = 0; ///< RO filter cooling timer. -static BOOL hasROFCirculationBeenStarted = FALSE; ///< Flag to indicate the water in RO filter has been recirculated. -static U32 targetDisinfectTime = 0; ///< Target disinfect time. +static BOOL isDrainPumpInMixDrainOn; ///< Flag to indicate the drain pump is on during mix drain. +static U32 targetDisinfectTime; ///< Target disinfect time. 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. @@ -194,12 +175,8 @@ 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 handleHeatDisinfectCoolDownROFilterState( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectMixDrainR1State( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectMixDrainR2State( void ); -static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectRinseR1ToR2State( void ); -static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectRinseR2ToR1AndDrainR1State( void ); -static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectRinseCirculationState( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCancelModeBasicPathState( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCancelModeWaterPathState( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCompleteState( void ); @@ -210,51 +187,52 @@ static HEAT_DISINFECT_STATUS_T getHeatDisinfectStatus( void ); static void publishHeatDisinfectData( void ); static void monitorModeHeatDisinfect( void ); -static void writeDisinfectDataToNV( void ); +static void writeDisinfectDataToNV( DG_USAGE_INFO_ITEMS_T info ); /*********************************************************************//** * @brief * The initHeatDisinfectMode function initializes the heat disinfect mode * module. * @details Inputs: none - * @details Outputs: heatDisinfectState, stateTimer, isThisLastDrain, + * @details Outputs: heatDisinfectState, stateTimer, * stateTrialCounter, areTempSensorsInRange, rsrvr1Status, rsrvr2Status, - * R1HeatDisinfectVol, R2HeatDisinfectVol, overallHeatDisinfectTimer, + * rsrvr1RefVolML, rsrvr2RefVolML, overallHeatDisinfectTimer, * cancellationMode, rsrvrFillStableTimeCounter, prevHeatDisinfectState - * isPartialDisinfectInProgress, isDrainPumpOnInMixDrain, + * isPartialDisinfectInProgress, isDrainPumpOnInMixDrain, heatDisinfectTimer * hasROFCirculationBeenStarted, ROFCirculationTimer, targetDisinfectTime - * ROFCirculationCoolingCounter, concentratePumpsPrimeTimer, - * haveDrainParamsBeenInit, tempGradOutOfRangeTimer, disinfectNVOps + * ROFCirculationCoolingCounter, concentratePumpsPrimeTimer, areRsrvrsLeaking + * haveDrainParamsBeenInit, tempGradOutOfRangeTimer, disinfectNVOps, + * dataPublishCounter * @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; - isThisLastDrain = FALSE; - stateTrialCounter = 0; - areTempSensorsInRange = FALSE; - rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; - rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; - R1HeatDisinfectVol = 0.0; - R2HeatDisinfectVol = 0.0; - overallHeatDisinfectTimer = 0; - cancellationMode = CANCELLATION_MODE_NONE; - rsrvrFillStableTimeCounter = 0; - isPartialDisinfectInProgress = FALSE; - isDrainPumpInMixDrainOn = FALSE; - ROFCirculationTimer = 0; - ROFCoolingTimer = 0; - hasROFCirculationBeenStarted = FALSE; - concentratePumpsPrimeTimer = 0; - targetDisinfectTime = 0; - haveDrainParamsBeenInit[ DG_RESERVOIR_1 ] = FALSE; - haveDrainParamsBeenInit[ DG_RESERVOIR_2 ] = FALSE; - tempGradOutOfRangeTimer = 0; - disinfectNVOps.hasDisCompleteDateBeenWrittenToNV = FALSE; - disinfectNVOps.hasDisStatusBeenWrittenToNV = FALSE; + heatDisinfectState = DG_HEAT_DISINFECT_STATE_START; + prevHeatDisinfectState = DG_HEAT_DISINFECT_STATE_START; + heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_NOT_RUNNING; + stateTimer = 0; + stateTrialCounter = 0; + areTempSensorsInRange = FALSE; + rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; + rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; + rsrvr1RefVolML = 0.0F; + rsrvr2RefVolML = 0.0F; + overallHeatDisinfectTimer = 0; + cancellationMode = CANCELLATION_MODE_NONE; + rsrvrFillStableTimeCounter = 0; + isPartialDisinfectInProgress = FALSE; + isDrainPumpInMixDrainOn = FALSE; + concentratePumpsPrimeTimer = 0; + targetDisinfectTime = 0; + haveDrainParamsBeenInit[ DG_RESERVOIR_1 ] = FALSE; + haveDrainParamsBeenInit[ DG_RESERVOIR_2 ] = FALSE; + tempGradOutOfRangeTimer = 0; + disinfectNVOps.hasDisStatusBeenWrittenToNV = FALSE; + alarmDetectedPendingTrigger = ALARM_ID_NO_ALARM; + heatDisinfectTimer = 0; + rsrvrsVolMonitorTimer = 0; + areRsrvrsLeaking = FALSE; + dataPublishCounter = 0; } /*********************************************************************//** @@ -267,7 +245,8 @@ *************************************************************************/ U32 transitionToHeatDisinfectMode( void ) { - deenergizeActuators(); + // Set all the actuators to reset and de-energized state + deenergizeActuators( NO_PARK_CONC_PUMPS ); initHeatDisinfectMode(); @@ -286,6 +265,17 @@ *************************************************************************/ U32 execHeatDisinfectMode( void ) { + // The inlet pressure shall be checked all the time as long as VPi is open + checkInletWaterPressure(); + + if ( heatDisinfectState != DG_HEAT_DISINFECT_STATE_FLUSH_DRAIN ) + { + // Do not check on the inlet water temperature and conductivity until the inlet filters have been flushed + // The initial states are drain reservoirs but in those states VPi is closed so these alarms are not checked + checkInletWaterTemperature(); + checkInletWaterConductivity(); + } + monitorModeHeatDisinfect(); switch ( heatDisinfectState ) @@ -346,10 +336,6 @@ heatDisinfectState = handleHeatDisinfectCoolDownHeatersState(); break; - case DG_HEAT_DISINFECT_STATE_COOL_DOWN_RO_FILTER: - heatDisinfectState = handleHeatDisinfectCoolDownROFilterState(); - break; - case DG_HEAT_DISINFECT_STATE_MIX_DRAIN_R1: heatDisinfectState = handleHeatDisinfectMixDrainR1State(); break; @@ -358,19 +344,7 @@ heatDisinfectState = handleHeatDisinfectMixDrainR2State(); break; - case DG_HEAT_DISINFECT_STATE_RINSE_R1_TO_R2: - heatDisinfectState = handleHeatDisinfectRinseR1ToR2State(); - break; - - case DG_HEAT_DISINFECT_STATE_RINSE_R2_TO_R1_AND_DRAIN_R1: - heatDisinfectState = handleHeatDisinfectRinseR2ToR1AndDrainR1State(); - break; - - case DG_HEAT_DISINFECT_STATE_RINSE_CIRCULATION: - heatDisinfectState = handleHeatDisinfectRinseCirculationState(); - break; - - case DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH: + case DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH: heatDisinfectState = handleHeatDisinfectCancelModeBasicPathState(); break; @@ -421,7 +395,7 @@ if ( DG_MODE_HEAT == getCurrentOperationMode() ) { // Reset all the actuators - deenergizeActuators(); + deenergizeActuators( NO_PARK_CONC_PUMPS ); // Transition to mode standby requestNewOperationMode( DG_MODE_STAN ); @@ -450,43 +424,18 @@ static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectStartState( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_DRAIN_R1; - F32 ppiPressure = getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_INLET ); - F32 TDiTemp = getTemperatureValue( TEMPSENSORS_INLET_DIALYSATE ); - F32 TRoTemp = getTemperatureValue( TEMPSENSORS_OUTLET_REDUNDANT ); + overallHeatDisinfectTimer = getMSTimerCount(); + heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_FLUSH_BEFORE_DISINFECT; + rsrvrFillStableTimeCounter = 0; + rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; + stateTimer = getMSTimerCount(); - // Start overall heat disinfect timer - overallHeatDisinfectTimer = getMSTimerCount(); + // Close VPi to prevent wasting water + setValveState( VPI, VALVE_STATE_CLOSED ); + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC); + setValveState( VRD1, VALVE_STATE_OPEN ); + setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); - // Set all the actuators to reset and de-energized state - deenergizeActuators(); - - // If the inlet pressure is less than or equal to the threshold or TDi and TRo difference is greater than 3 C, the cycle - // should be canceled - if ( ( ppiPressure <= MIN_INLET_PRESSURE_PSI ) || ( fabs( TDiTemp - TRoTemp ) > MAX_START_STATE_TEMP_SENSORS_DIFF_C ) ) - { - prevHeatDisinfectState = state; - alarmDetectedPendingTrigger = ALARM_ID_DG_HEAT_DISINFECT_INLET_PRES_AND_TEMP_SNSRS_OUT; - state = DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH; - } - else - { - // Set the heat disinfect UI state - heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_FLUSH_BEFORE_DISINFECT; - - // Close VPi to prevent wasting water - setValveState( VPI, VALVE_STATE_CLOSED ); - setValveState( VPO, VALVE_STATE_FILL_C_TO_NC); - - // Set the actuators to drain R1 - setValveState( VRD1, VALVE_STATE_OPEN ); - setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); - - rsrvrFillStableTimeCounter = 0; - // Assume reservoir 1 is full and drain it - rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - stateTimer = getMSTimerCount(); - } - return state; } @@ -496,7 +445,7 @@ * drain R1 state. The state drains reservoir 1. If the transition is * finished within the time, it transitions to the next state, otherwise, * it transitions to basic cancellation path. - * @details Inputs: stateTimer, rsrvr1Status, rsrvr2Status, isThisLastDrain + * @details Inputs: stateTimer, rsrvr1Status, rsrvr2Status * @details Outputs: stateTimer, rsrvr1Status, rsrvr2Status * @return next state of the heat disinfect state machine *************************************************************************/ @@ -510,43 +459,19 @@ } else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) { - if ( TRUE == isThisLastDrain ) - { - // Done with draining - signalDrainPumpHardStop(); + tareLoadCell( LOAD_CELL_RESERVOIR_1_PRIMARY ); + tareLoadCell( LOAD_CELL_RESERVOIR_1_BACKUP ); - // Set the valves to flush the recirculation line - setValveState( VPI, VALVE_STATE_OPEN ); - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); - setValveState( VRD1, VALVE_STATE_CLOSED ); - setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); - setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); + // Assume reservoir 2 is full and drain it + rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - // TODO turn on the concentrate pumps + // 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; - // Set the RO pump to run at full pressure - setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); - - // Done with final draining - isThisLastDrain = FALSE; - state = DG_HEAT_DISINFECT_STATE_RINSE_CIRCULATION; - } - else - { - 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 @@ -567,7 +492,7 @@ * drain R2 state. The state drains reservoir 2. If the transition is * finished within the time, it transitions to the next state, otherwise, * it transitions to basic cancellation path. - * @details Inputs: stateTimer, rsrvr2Status, isThisLastDrain, + * @details Inputs: stateTimer, rsrvr2Status * stateTrialCounter * @details Outputs: stateTimer, rsrvr2Status, stateTrialCounter * @return next state of the heat disinfect state machine @@ -582,33 +507,24 @@ } else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) { - if ( TRUE == isThisLastDrain ) - { - setValveState( VRD1, VALVE_STATE_OPEN ); - setValveState( VRD2, VALVE_STATE_CLOSED ); - rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - state = DG_HEAT_DISINFECT_STATE_DRAIN_R1; - } - else - { - tareLoadCell( LOAD_CELL_RESERVOIR_2_PRIMARY ); - tareLoadCell( LOAD_CELL_RESERVOIR_2_BACKUP ); + tareLoadCell( LOAD_CELL_RESERVOIR_2_PRIMARY ); + tareLoadCell( LOAD_CELL_RESERVOIR_2_BACKUP ); - signalDrainPumpHardStop(); + 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; - } + // 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 ); } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { prevHeatDisinfectState = state; - state = DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH; + state = DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH; } return state; @@ -634,43 +550,13 @@ // Check if flush time has elapsed if ( TRUE == didTimeout( stateTimer, FLUSH_DRAIN_WAIT_TIME_MS ) ) { - BOOL hasConductivityPassed = FALSE; + 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(); + stateTrialCounter = 0; + state = DG_HEAT_DISINFECT_STATE_FLUSH_CIRCULATION; - // If the inlet temperature and conductivity are in range, move onto the next state - if ( ( getTemperatureValue( TEMPSENSORS_INLET_PRIMARY_HEATER ) >= MIN_INLET_TEMPERATURE_C ) && - ( getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ) <= MAX_INLET_CONDUCTIVITY_US_PER_CM ) ) - { - hasConductivityPassed = TRUE; - } - -#ifndef _RELEASE_ - if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_DISINFECT_CONDUCTIVITY_CHECK ) ) - { - hasConductivityPassed = TRUE; - } -#endif - - if ( TRUE == hasConductivityPassed ) - { - 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(); - stateTrialCounter = 0; - state = DG_HEAT_DISINFECT_STATE_FLUSH_CIRCULATION; - } - // If the number of failures have not exceeded the limit, try again. - else if ( stateTrialCounter < MAX_ALLOWED_STATE_TRIALS ) - { - stateTrialCounter++; - stateTimer = getMSTimerCount(); - } - // Couldn't get a good water sample after a couple of trials and the disinfect cycle failed - else - { - alarmDetectedPendingTrigger = ALARM_ID_DG_HEAT_DISINFECT_INLET_COND_AND_TEMP_OUT; - prevHeatDisinfectState = state; - state = DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH; - } } return state; @@ -693,24 +579,24 @@ { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_FLUSH_CIRCULATION; + writeDisinfectDataToNV( USAGE_INFO_FILTER_FLUSH ); + // Check if the flush circulation time has elapsed and the temperature sensors are not in range yet if ( ( TRUE == didTimeout( stateTimer, FLUSH_CICRCULATION_WAIT_TIME_MS ) ) && ( FALSE == areTempSensorsInRange ) ) { F32 ThdTemp = getTemperatureValue( TEMPSENSORS_HEAT_DISINFECT ); F32 TPoTemp = getTemperatureValue( TEMPSENSORS_OUTLET_PRIMARY_HEATER ); - F32 TD1Temp = getTemperatureValue( TEMPSENSORS_CONDUCTIVITY_SENSOR_1 ); F32 TD2Temp = getTemperatureValue( TEMPSENSORS_CONDUCTIVITY_SENSOR_2 ); - F32 avgTemp = ( ThdTemp + TPoTemp + TD1Temp + TD2Temp ) / NUM_OF_TEMP_SENSORS_TO_AVG; + F32 avgTemp = ( ThdTemp + TPoTemp + TD2Temp ) / NUM_OF_TEMP_SENSORS_TO_AVG; // Check if any of the temperature sensors deviate for more than the defined value from the average of all // of the temperature sensors BOOL isThdOut = ( fabs( ThdTemp - avgTemp ) > MAX_FLUSH_CIRC_TEMP_SENSOR_DIFF_C ? TRUE : FALSE ); BOOL isTPoOut = ( fabs( TPoTemp - avgTemp ) > MAX_FLUSH_CIRC_TEMP_SENSOR_DIFF_C ? TRUE : FALSE ); - BOOL isTD1Out = ( fabs( TD1Temp - avgTemp ) > MAX_FLUSH_CIRC_TEMP_SENSOR_DIFF_C ? TRUE : FALSE ); BOOL isTD2Out = ( fabs( TD2Temp - avgTemp ) > MAX_FLUSH_CIRC_TEMP_SENSOR_DIFF_C ? TRUE : FALSE ); // Check if any of the temperature sensors are out of tolerance - if ( ( TRUE == isThdOut ) || ( TRUE == isTPoOut ) || ( TRUE == isTD1Out ) || ( TRUE == isTD2Out ) ) + if ( ( TRUE == isThdOut ) || ( TRUE == isTPoOut ) || ( TRUE == isTD2Out ) ) { // Check if we have exceeded the number of trials. If not, try another time if ( ++stateTrialCounter < MAX_ALLOWED_STATE_TRIALS ) @@ -720,9 +606,9 @@ // State failed. Cancel heat disinfect mode else { - alarmDetectedPendingTrigger = ALARM_ID_DG_TEMP_SENSORS_DIFF_OUT_OF_RANGE; - prevHeatDisinfectState = state; - state = DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH; + alarmDetectedPendingTrigger = ALARM_ID_DG_CLEANING_MODE_TEMP_SENSORS_DIFF_OUT_OF_RANGE; + prevHeatDisinfectState = state; + state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; } } else @@ -742,20 +628,25 @@ // Only start the concentrate pumps if the temperature sensors are in range if ( TRUE == areTempSensorsInRange ) { - if ( TRUE == didTimeout( concentratePumpsPrimeTimer, FLUSH_CICRCULATION_WAIT_TIME_MS ) ) + if ( TRUE == didTimeout( concentratePumpsPrimeTimer, FLUSH_CIRCULATION_CONC_PUMPS_WAIT_TIME_MS ) ) { rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; // Done with flushing the concentrate pumps line - requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); - requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID, NO_PARK_CONC_PUMPS ); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); - stateTimer = getMSTimerCount(); - state = DG_HEAT_DISINFECT_STATE_FLUSH_R1_AND_R2; + setHeaterTargetTemperature( DG_PRIMARY_HEATER, HEAT_DISINFECT_TARGET_TEMPERATURE_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(); + state = DG_HEAT_DISINFECT_STATE_FLUSH_R1_AND_R2; } } @@ -790,9 +681,9 @@ // until reservoir 2 is filled up and the tubing might expand or leak. if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) { - prevHeatDisinfectState = state; + prevHeatDisinfectState = state; alarmDetectedPendingTrigger = ALARM_ID_DG_INVALID_LOAD_CELL_VALUE; - state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; + state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; } } // Once R1 is full, keep monitoring for R2 level and timeout @@ -814,18 +705,18 @@ // Set both reservoirs status rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; - state = DG_HEAT_DISINFECT_STATE_FLUSH_R2_AND_DRAIN_R1; + state = DG_HEAT_DISINFECT_STATE_FLUSH_R2_AND_DRAIN_R1; } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { prevHeatDisinfectState = state; - state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; + state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; } } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { prevHeatDisinfectState = state; - state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; + state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; } return state; @@ -863,7 +754,7 @@ 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; } // First reservoir 2 must be completely full @@ -881,9 +772,9 @@ // sure the extra volume that is read is not because of previous water that is being drained currently and it is above 500 mL if ( ( volume >= RSRVRS_PARTIAL_FILL_VOL_ML ) && ( 0 == drainPumpRPM ) ) { - prevHeatDisinfectState = state; + prevHeatDisinfectState = state; alarmDetectedPendingTrigger = ALARM_ID_DG_INVALID_LOAD_CELL_VALUE; - state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; + state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; } } // Once R2 is full, R1 must be partially full @@ -896,7 +787,8 @@ { // Done with filing turn off the RO pump signalROPumpHardStop(); - + stopHeater( DG_PRIMARY_HEATER ); + turnOffUVReactor( INLET_UV_REACTOR ); // Set the valves to drain R2 and no fill setValveState( VPI, VALVE_STATE_CLOSED ); setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); @@ -905,20 +797,20 @@ setValveState( VRD2, VALVE_STATE_OPEN ); setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); // Start the timer for drain timeout - stateTimer = getMSTimerCount(); + stateTimer = getMSTimerCount(); rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - state = DG_HEAT_DISINFECT_STATE_FLUSH_DRAIN_R2; + state = DG_HEAT_DISINFECT_STATE_FLUSH_DRAIN_R2; } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { prevHeatDisinfectState = state; - state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; + 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; + state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; } return state; @@ -949,14 +841,14 @@ setValveState( VRD1, VALVE_STATE_OPEN ); setValveState( VRD2, VALVE_STATE_CLOSED ); // Start the timer for drain timeout - stateTimer = getMSTimerCount(); + stateTimer = getMSTimerCount(); rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - state = DG_HEAT_DISINFECT_STATE_FLUSH_DRAIN_R1; + state = DG_HEAT_DISINFECT_STATE_FLUSH_DRAIN_R1; } 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; @@ -996,7 +888,7 @@ setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); setValveState( VRD1, VALVE_STATE_CLOSED ); setValveState( VRD2, VALVE_STATE_OPEN ); - + 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 ); @@ -1006,15 +898,13 @@ rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; - - // Start the timer for drain timeout - stateTimer = getMSTimerCount(); - state = DG_HEAT_DISINFECT_STATE_FILL_WITH_WATER; + stateTimer = getMSTimerCount(); + state = DG_HEAT_DISINFECT_STATE_FILL_WITH_WATER; } 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; @@ -1037,10 +927,8 @@ 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; - // Set the heat disinfect UI state - heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_HEAT_UP_WATER; - // First reservoir 1 must be full if ( DG_RESERVOIR_BELOW_TARGET == rsrvr1Status ) { @@ -1054,43 +942,35 @@ // Once reservoir 2 is full, set the actuators for recirculation 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 ); - + signalROPumpHardStop(); // Set the drain pump to control mode - setDrainPumpTargetOutletPressure( HEAT_DISINFECT_TARGET_DRAIN_PRES_PSI ); + setDrainPumpTargetOutletFlowLPM( HEAT_DISINFECT_TARGET_RO_FLOW_LPM ); - // Set the RO flow to maximum pressure of 30psi since it is the maximum pressure on the RO filter - // at inlet temperature > 45 C - setROPumpTargetFlowRateLPM( HEAT_DISINFECT_TARGET_RO_FLOW_LPM, HEAT_DISINFECT_MAX_RO_PRESSURE_PSI ); - // 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 ); - // Get the current volumes of R1 & R2. These values will be used to make sure the reservoirs' - // volume does not change more than a certain amount during the actual heat disinfect cycle - R1HeatDisinfectVol = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); - R2HeatDisinfectVol = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); - - stateTimer = getMSTimerCount(); + stateTimer = getMSTimerCount(); rsrvrsVolMonitorTimer = getMSTimerCount(); - state = DG_HEAT_DISINFECT_STATE_DISINFECT_R1_TO_R2; + state = DG_HEAT_DISINFECT_STATE_DISINFECT_R1_TO_R2; } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { prevHeatDisinfectState = state; - state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; + state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; } } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { prevHeatDisinfectState = state; - state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; + state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; } return state; @@ -1113,6 +993,22 @@ DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_DISINFECT_R1_TO_R2; HEAT_DISINFECT_STATUS_T status = getHeatDisinfectStatus(); + if ( FALSE == isROPumpRunning() ) + { + setROPumpTargetDutyCycle( HEAT_DISINFECT_TARGET_RO_PUMP_DC ); + } + + if ( TRUE == didTimeout( stateTimer, HEAT_DISINFECT_REF_RSRVR_TIMEOUT_MS ) ) + { + if ( ( rsrvr1RefVolML < NEARLY_ZERO ) && ( rsrvr2RefVolML < NEARLY_ZERO ) ) + { + // Get the current volumes of R1 & R2. These values will be used to make sure the reservoirs' + // volume does not change more than a certain amount during the actual heat disinfect cycle + rsrvr1RefVolML = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); + rsrvr2RefVolML = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); + } + } + switch ( status ) { case HEAT_DISINFECT_RSRVRS_LEAK_TIMEOUT: @@ -1126,20 +1022,28 @@ break; case HEAT_DISINFECT_COMPLETE: - - requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); - requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID, NO_PARK_CONC_PUMPS ); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); // Set the valves to transfer hot water from R1 to R2 and fill up R2. setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); setValveState( VRD1, VALVE_STATE_OPEN ); 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; @@ -1170,10 +1074,8 @@ 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; - // Set the heat disinfect UI state - heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_TRANSITION_HOT_WATER; - // First reservoir 1 must be partially full if ( DG_RESERVOIR_BELOW_TARGET == rsrvr1Status ) { @@ -1185,22 +1087,26 @@ if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) { - // Get the current volumes to be monitored during R2 to R1 heat disinfect state - R1HeatDisinfectVol = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); - R2HeatDisinfectVol = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); + // Set the drain pump to control mode + setDrainPumpTargetOutletFlowLPM( HEAT_DISINFECT_TARGET_RO_FLOW_LPM ); - state = DG_HEAT_DISINFECT_STATE_DISINFECT_R2_TO_R1; + // 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; } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { prevHeatDisinfectState = state; - state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; + state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; } } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { prevHeatDisinfectState = state; - state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; + state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; } return state; @@ -1223,6 +1129,17 @@ HEAT_DISINFECT_STATUS_T status = getHeatDisinfectStatus(); 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 ) ) + { + // Get the current volumes of R1 & R2. These values will be used to make sure the reservoirs' + // volume does not change more than a certain amount during the actual heat disinfect cycle + rsrvr1RefVolML = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); + rsrvr2RefVolML = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); + } + } + switch ( status ) { case HEAT_DISINFECT_RSRVRS_LEAK_TIMEOUT: @@ -1232,6 +1149,8 @@ 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 ); @@ -1254,107 +1173,33 @@ * disinfect cool down heaters state. The state continues running the fluid * while the heaters are off for a certain period of time. * @details Inputs: stateTimer - * @details Outputs: stateTimer + * @details Outputs: stateTimer, heatDisinfectUIState * @return next state of the heat disinfect state machine *************************************************************************/ static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCoolDownHeatersState( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_COOL_DOWN_HEATERS; + heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_COOL_DOWN_DEVICE; - // Set the heat disinfect UI state - heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_COOL_DOWN_DEVICE; + writeDisinfectDataToNV( USAGE_INFO_HEAT_DIS ); - writeDisinfectDataToNV(); - if ( TRUE == didTimeout( stateTimer, POST_HEAT_DISINFECT_WAIT_TIME_MS ) ) { - // Stop the drain pump and the RO pump to exit the closed loop - signalDrainPumpHardStop(); signalROPumpHardStop(); - // De-energize all the valves that are not in the path anymore - // and wait for the RO membrane to be cooled down. - setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); - setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); - setValveState( VPI, VALVE_STATE_CLOSED ); - setValveState( VBF, VALVE_STATE_CLOSED ); - setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); - setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); - setValveState( VRD1, VALVE_STATE_CLOSED ); - - ROFCoolingTimer = getMSTimerCount(); - stateTimer = getMSTimerCount(); - state = DG_HEAT_DISINFECT_STATE_COOL_DOWN_RO_FILTER; - } - - return state; -} - -/*********************************************************************//** - * @brief - * The handleHeatDisinfectCoolDownROFilterState function handles the heat - * disinfect cool down RO filter state. The state monitors the temperature - * at THd and if it is less than 45 C, it transitions to the next state. - * @details Inputs: stateTimer, rsrvr1Status, hasROFCirculationBeenStarted, - * ROFCirculationCoolingCounter - * @details Outputs: stateTimer, rsrvr1Status, hasROFCirculationBeenStarted, - * ROFCirculationCoolingCounter - * @return next state of the heat disinfect state machine - *************************************************************************/ -static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCoolDownROFilterState( void ) -{ - DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_COOL_DOWN_RO_FILTER; - - // Set the heat disinfect UI state - heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_COOL_DOWN_DEVICE; - - // THd is the closet sensor to the RO filter and this temperature is monitored - // until it is dropped below 45 C to be able to run fluid through the RO filter - F32 THdTemp = getTemperatureValue( TEMPSENSORS_HEAT_DISINFECT ); - - // Check if the coldest spot temperature is less than 45 C so the RO filter can safely run - if ( ( FALSE == isROPumpRunning() ) && ( THdTemp < TARGET_THD_SENSOR_FOR_RINSING_C ) ) - { - U32 time = calcTimeSince( ROFCoolingTimer ); - - if ( time <= THD_REACH_BELOW_45_AFTER_CIRC_TIME_MS ) + if ( TRUE == isDrainPumpOn() ) { - setValveState( VPI, VALVE_STATE_OPEN ); - setValveState( VBF, VALVE_STATE_CLOSED ); - setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); - setValveState( VRC, VALVE_STATE_RECIRC_C_TO_NC ); - setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); - setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); - setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); - setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); - - rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - stateTimer = getMSTimerCount(); - state = DG_HEAT_DISINFECT_STATE_MIX_DRAIN_R1; + // Stop the drain pump and the RO pump to exit the closed loop + signalDrainPumpHardStop(); + setValveState( VRD1, VALVE_STATE_CLOSED ); } else { - // Set the valves to circulation. VBf is opened because the fluid in the RO filter might still be hot - setValveState( VBF, VALVE_STATE_OPEN ); - setValveState( VDR, VALVE_STATE_RECIRC_C_TO_NC ); - setValveState( VRC, VALVE_STATE_RECIRC_C_TO_NC ); - setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); - - // Set the RO flow to maximum pressure of 30psi since it is the maximum pressure on the RO filter - // at inlet temperature > 45 C - setROPumpTargetFlowRateLPM( ROF_COOL_DOWN_TARGET_FLOW_LPM, HEAT_DISINFECT_MAX_RO_PRESSURE_PSI ); - - hasROFCirculationBeenStarted = TRUE; - ROFCirculationTimer = getMSTimerCount(); + rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; + stateTimer = getMSTimerCount(); + state = DG_HEAT_DISINFECT_STATE_MIX_DRAIN_R1; } } - // If the RO filter water circulation is in progress and the time for it has elapsed, stop the pump - else if ( ( TRUE == hasROFCirculationBeenStarted ) && ( TRUE == didTimeout( ROFCirculationTimer, ROF_COOL_DOWN_CIRCULATION_TIME_MS ) ) ) - { - hasROFCirculationBeenStarted = FALSE; - ROFCoolingTimer = getMSTimerCount(); - signalROPumpHardStop(); - } return state; } @@ -1374,15 +1219,19 @@ 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; - // Set the heat disinfect UI state - 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 ); setValveState( VRD1, VALVE_STATE_OPEN ); + setValveState( VBF, VALVE_STATE_CLOSED ); + setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); + setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); // Turn on the drain pump to drain the reservoirs in open loop mode setDrainPumpTargetRPM( DRAIN_PUMP_RPM_IN_MIX_DRAIN ); } @@ -1400,13 +1249,13 @@ setValveState( VRD2, VALVE_STATE_OPEN ); rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - stateTimer = getMSTimerCount(); - state = DG_HEAT_DISINFECT_STATE_MIX_DRAIN_R2; + stateTimer = getMSTimerCount(); + state = DG_HEAT_DISINFECT_STATE_MIX_DRAIN_R2; } 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; } } @@ -1433,231 +1282,19 @@ } else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) { - // Done with draining the reservoirs - signalDrainPumpHardStop(); - - // Set the valves to fill up R1 and overflow to R2 - setValveState( VPI, VALVE_STATE_OPEN ); - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); - // Done with draining reservoir 2 - setValveState( VRD2, 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( VRF, VALVE_STATE_R1_C_TO_NC ); - setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); - setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); - setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); - - rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; - rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; - - stateTimer = getMSTimerCount(); - state = DG_HEAT_DISINFECT_STATE_RINSE_R1_TO_R2; + state = DG_HEAT_DISINFECT_STATE_COMPLETE; } 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; } /*********************************************************************//** * @brief - * The handleHeatDisinfectRinseR1ToR2State function handles the heat - * disinfect rinse R1 to R2 state. The state rinses reservoir 1 to reservoir - * 2. If the rinse process times out, it transitions to water cancellation - * state, otherwise, it transitions to the next state. - * @details Inputs: stateTimer, rsrvr1Status, rsrvr2Status - * @details Outputs: stateTimer, rsrvr1Status, rsrvr2Status - * @return next state of the heat disinfect state machine - *************************************************************************/ -static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectRinseR1ToR2State( void ) -{ - DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_RINSE_R1_TO_R2; - - if ( DG_RESERVOIR_BELOW_TARGET == rsrvr1Status ) - { - rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_1, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS ); - - // Keep monitoring the status of reservoir 2 at the same time - rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_500ML_FILL_UP_TIMEOUT_MS ); - // Reservoir 2 cannot be filled before reservoir 1 is filled and is overflowing to reservoir 2. If reservoir 2 has already - // reached to target volume, it means reservoir 1's load cell might be reading incorrect values. This situation might continue - // until reservoir 2 is filled up and the tubing might expand or leak. - if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) - { - prevHeatDisinfectState = state; - alarmDetectedPendingTrigger = ALARM_ID_DG_INVALID_LOAD_CELL_VALUE; - state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; - } - } - else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) - { - rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_500ML_FILL_UP_TIMEOUT_MS ); - - if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) - { - // Set the valves to rinse R2 to R1 and drain R1 - setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); - setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); - setValveState( VRD1, VALVE_STATE_OPEN ); - setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); - setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); - - rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; - stateTimer = getMSTimerCount(); - state = DG_HEAT_DISINFECT_STATE_RINSE_R2_TO_R1_AND_DRAIN_R1; - } - else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) - { - prevHeatDisinfectState = state; - state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; - } - } - else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) - { - prevHeatDisinfectState = state; - state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; - } - - return state; -} - -/*********************************************************************//** - * @brief - * The handleHeatDisinfectRinseR2ToR1AndDrainR1State function handles the - * heat disinfect rinse R2 to R1 and drain R1 state. The state rinses - * reservoir 2 and drains reservoir 1 at the same time. If the drain - * process times out, it transitions to basic cancellation state, and - * if the rinse times out, it transitions to water cancellation state. - * If the drain and rinse are completed within the define time, it - * transitions to the next state. - * @details Inputs: stateTimer, rsrvr1Status, rsrvr2Status, isThisLastDrain - * @details Outputs: stateTimer, rsrvr1Status, rsrvr2Status, isThisLastDrain - * @return next state of the heat disinfect state machine - *************************************************************************/ -static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectRinseR2ToR1AndDrainR1State( void ) -{ - DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_RINSE_R2_TO_R1_AND_DRAIN_R1; - - if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr1Status ) - { - rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS ); - } - else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) - { - // Done with draining R1 - signalDrainPumpHardStop(); - setValveState( VRD1, VALVE_STATE_CLOSED ); - } - else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) - { - prevHeatDisinfectState = state; - state = DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH; - } - - // First reservoir 2 must be completely full - if ( DG_RESERVOIR_BELOW_TARGET == rsrvr2Status ) - { - // Keep monitoring the status of reservoir 1 as the same time - F32 volume = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); - - rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS ); - - U32 drainPumpRPM = getDrainPumpTargetRPM(); - - // Reservoir 1 cannot be filled before reservoir 2 is filled and is overflowing to reservoir 1. If reservoir 1 has already - // reached to target volume, it means reservoir 2's load cell might be reading incorrect values. This situation might continue - // until reservoir 1 is filled up and the tubing might expand or leak. - // Before checking whether reservoir 1 is filled pre-maturely, we have to make sure reservoir 1 is drained completely to make - // sure the extra volume that is read is not because of previous water that is being drained currently and it is above 500 mL - if ( ( volume >= RSRVRS_PARTIAL_FILL_VOL_ML ) && ( 0 == drainPumpRPM ) ) - { - prevHeatDisinfectState = state; - alarmDetectedPendingTrigger = ALARM_ID_DG_INVALID_LOAD_CELL_VALUE; - state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; - } - } - // Once reservoir 2 is completely full, monitor reservoir 1 - else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) - { - rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_1, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_500ML_FILL_UP_TIMEOUT_MS ); - - if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) - { - // Done with filling, turn off the RO pump - signalROPumpHardStop(); - - // De-energize all the valves and set the VDr to drain R2 - setValveState( VPI, VALVE_STATE_CLOSED ); - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); - setValveState( VPO, VALVE_STATE_FILL_C_TO_NC); - setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); - setValveState( VRD2, VALVE_STATE_OPEN ); - setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); - setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); - - // Turn on the drain pump to drain R2 - setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); - - // Turn the pumps on in reverse - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, ACID_PUMP_SPEED_ML_PER_MIN ); - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, ACID_PUMP_SPEED_ML_PER_MIN ); - - // Turn on the concentrate pumps - requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); - requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); - - // This is the last drain of heat disinfect cycle - isThisLastDrain = TRUE; - stateTimer = getMSTimerCount(); - // Set the reservoir status - rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - state = DG_HEAT_DISINFECT_STATE_DRAIN_R2; - } - 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; -} - -/*********************************************************************//** - * @brief - * The handleHeatDisinfectRinseCirculationState function handles the - * heat disinfect rinse RO circulation and concentrate pumps state. Once - * the defined flush circulation time has elapsed, it transitions to the next - * state. - * @details Inputs: none - * @details Outputs: none - * @return next state of the heat disinfect state machine - *************************************************************************/ -static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectRinseCirculationState( void ) -{ - DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_RINSE_CIRCULATION; - - if ( TRUE == didTimeout( stateTimer, FLUSH_CICRCULATION_WAIT_TIME_MS ) ) - { - state = DG_HEAT_DISINFECT_STATE_COMPLETE; - } - - return state; -} - -/*********************************************************************//** - * @brief * The handleHeatDisinfectCancelModeBasicPathState function handles the * heat disinfect cancel mode basic path state. The state sets the state * to complete and raises an alarm. @@ -1700,6 +1337,7 @@ // 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 ) { @@ -1708,12 +1346,12 @@ F32 TRo = getTemperatureValue( TEMPSENSORS_OUTLET_REDUNDANT ); // Stop all the actuators first then decide who should run next - deenergizeActuators(); + 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 ) ) { - targetRPM = DRAIN_PUMP_TARGET_RPM; + targetRPM = DRAIN_PUMP_TARGET_RPM; cancellationMode = CANCELLATION_MODE_COLD; } else @@ -1722,8 +1360,9 @@ setValveState( VPI, VALVE_STATE_OPEN ); setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); - targetRPM = DRAIN_PUMP_RPM_IN_MIX_DRAIN; + targetRPM = DRAIN_PUMP_RPM_IN_MIX_DRAIN; cancellationMode = CANCELLATION_MODE_HOT; + drainTimeoutMS = RSRVRS_MIX_DRAIN_TIMEOUT_MS; } rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; @@ -1743,7 +1382,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, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS ); + rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, drainTimeoutMS ); if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) { @@ -1760,32 +1399,31 @@ signalDrainPumpHardStop(); prevHeatDisinfectState = state; - state = DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH; + state = DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH; } // 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, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS ); + rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, drainTimeoutMS ); 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 ) - { - setValveState( VRD1, VALVE_STATE_CLOSED ); - setValveState( VRD2, VALVE_STATE_CLOSED ); - signalDrainPumpHardStop(); + } + 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; - } + prevHeatDisinfectState = state; + state = DG_HEAT_DISINFECT_STATE_CANCEL_BASIC_PATH; } return state; @@ -1803,12 +1441,10 @@ 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; - // Set the heat disinfect UI state - heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_COMPLETE; + requestNewOperationMode( DG_MODE_HCOL ); - stopDGHeatDisinfect(); - return state; } @@ -1822,7 +1458,13 @@ *************************************************************************/ static void failHeatDisinfect( void ) { - SET_ALARM_WITH_1_U32_DATA( alarmDetectedPendingTrigger, prevHeatDisinfectState ) + // In the cleaning modes the alarms are triggered but the mode is not transitioned to fault automatically + // so transition to fault mode is done here + if ( alarmDetectedPendingTrigger != ALARM_ID_NO_ALARM ) + { + SET_ALARM_WITH_1_U32_DATA( alarmDetectedPendingTrigger, prevHeatDisinfectState ) + } + requestNewOperationMode( DG_MODE_FAUL ); } /*********************************************************************//** @@ -1916,9 +1558,9 @@ 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() ) ) + if ( ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) && ( 0 == getDrainPumpTargetRPM() ) ) { stateTimer = getMSTimerCount(); } @@ -1934,10 +1576,10 @@ else if ( TRUE == didTimeout( stateTimer, timeout ) ) { // Failed to drain on time. Update the previous heat disinfect state and transition to basic cancellation - prevHeatDisinfectState = heatDisinfectState; - alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_DRAIN_TIMEOUT; - haveDrainParamsBeenInit[ r ] = FALSE; - status = DG_RESERVOIR_NOT_REACHED_TARGET; + prevHeatDisinfectState = heatDisinfectState; + alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_DRAIN_TIMEOUT; + haveDrainParamsBeenInit[ r ] = FALSE; + status = DG_RESERVOIR_NOT_REACHED_TARGET; } return status; @@ -1946,89 +1588,107 @@ /*********************************************************************//** * @brief * The getHeatDisinfectStatus function monitors and returns the current - * stage of heat disinfect cycle. If the level of the reservoirs is drifted - * consecutively for the define period of time, it sets the reservoir leak - * time out alarm. If the target temperature is not reached within the - * defined period of time, it set the temperature out of range alarm. - * If the heat disinfect has started or has elapsed, it set the status of - * heat disinfect accordingly. - * @details Inputs: areRsrvrsLeaking, areRsrvrsLeaking - * @details Outputs: areRsrvrsLeaking, areRsrvrsLeaking, heatDisinfectState + * stage of heat disinfect cycle. It monitors + * 1) The temperature gradient betweeen TPo and Thd + * 2) Reservoir 1 or Reservoir 2 have lost more than allowed loss volume + * 3) THd must be above the minimum target disinfect temp for the + * target disinfect time + * 4) The overall heat disinfect time + * + * @details Inputs: tempGradOutOfRangeTimer, areRsrvrsLeaking, + * isPartialDisinfectInProgress, heatDisinfectTimer, + * targetDisinfectTime + * @details Outputs: tempGradOutOfRangeTimer, alarmDetectedPendingTrigger, + * areRsrvrsLeaking, isPartialDisinfectInProgress, + * heatDisinfectTimer, targetDisinfectTime * @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 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 ); - F32 TPoTemp = getTemperatureValue( TEMPSENSORS_OUTLET_PRIMARY_HEATER ); - F32 ThdTemp = getTemperatureValue( TEMPSENSORS_HEAT_DISINFECT ); - - BOOL isR1OutOfRange = fabs( getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ) - R1HeatDisinfectVol ) > RSRVRS_MAX_TARGET_VOL_CHANGE_ML; - BOOL isR2OutOfRange = fabs( getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ) - R2HeatDisinfectVol ) > RSRVRS_MAX_TARGET_VOL_CHANGE_ML; - - // Check if the temperature gradient in between the coldest and the hottest spot is more than the specified temperature and - // the timer has not started yet, start it - if ( ( fabs( TPoTemp - ThdTemp ) > HEAT_DISINFECT_MAX_TEMP_GRADIENT_C ) && ( 0 == tempGradOutOfRangeTimer ) ) + // Perform check if no pending alarm + if ( ALARM_ID_NO_ALARM == alarmDetectedPendingTrigger ) { - tempGradOutOfRangeTimer = getMSTimerCount(); - } - else if ( ( fabs( TPoTemp - ThdTemp ) > HEAT_DISINFECT_MAX_TEMP_GRADIENT_C ) && - ( TRUE == didTimeout( tempGradOutOfRangeTimer, HEAT_DISINFECT_TEMP_GRAD_OUT_RANGE_TIME_MS ) ) ) - { - alarmDetectedPendingTrigger = ALARM_ID_DG_HEAT_DISINFECT_TEMP_GRAD_OUT_OF_RANGE; - status = HEAT_DISINFECT_TEMP_GRADIENT_OUT_OF_RANGE; - } - - // Check if either reservoir 1 or reservoir 2 are losing volume more than allowed volume - if ( ( TRUE == isR1OutOfRange ) || ( TRUE == isR2OutOfRange ) ) - { - // If the leak is the first time after a while, set the flag and start the timer - if ( FALSE == areRsrvrsLeaking ) + if ( FALSE == isGradientOutOfRange ) { - areRsrvrsLeaking = TRUE; - rsrvrsVolMonitorTimer = getMSTimerCount(); + tempGradOutOfRangeTimer = 0; } - // If the volume is out of range and it has timed out, exit - else if ( TRUE == didTimeout( rsrvrsVolMonitorTimer, RSRVRS_TARGET_VOL_OUT_TIMEOUT_MS ) ) + else if ( 0 == tempGradOutOfRangeTimer ) { - areRsrvrsLeaking = FALSE; - alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_LEAK_TIMEOUT; - status = HEAT_DISINFECT_RSRVRS_LEAK_TIMEOUT; + tempGradOutOfRangeTimer = getMSTimerCount(); } + else if ( TRUE == didTimeout( tempGradOutOfRangeTimer, HEAT_DISINFECT_TEMP_GRAD_OUT_RANGE_TIME_MS ) ) + { + alarmDetectedPendingTrigger = ALARM_ID_DG_HEAT_DISINFECT_TEMP_GRAD_OUT_OF_RANGE; + status = HEAT_DISINFECT_TEMP_GRADIENT_OUT_OF_RANGE; + } } - // Reservoirs are in range - else - { - areRsrvrsLeaking = FALSE; - } - // 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 ) + // Perform check if no pending alarm + if ( ALARM_ID_NO_ALARM == alarmDetectedPendingTrigger ) { - // 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 ( ( rsrvr1RefVolML > NEARLY_ZERO ) && ( rsrvr2RefVolML > 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; + // Check if either reservoir 1 or reservoir 2 are losing volume more than allowed volume + if ( ( TRUE == isR1OutOfRange ) || ( TRUE == isR2OutOfRange ) ) + { + // If the leak is the first time after a while, set the flag and start the timer + if ( FALSE == areRsrvrsLeaking ) + { + areRsrvrsLeaking = TRUE; + rsrvrsVolMonitorTimer = getMSTimerCount(); + } + // If the volume is out of range and it has timed out, exit + else if ( TRUE == didTimeout( rsrvrsVolMonitorTimer, RSRVRS_TARGET_VOL_OUT_TIMEOUT_MS ) ) + { + areRsrvrsLeaking = FALSE; + alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_LEAK_TIMEOUT; + status = HEAT_DISINFECT_RSRVRS_LEAK_TIMEOUT; + } + } } + // Reservoirs are in range + else + { + areRsrvrsLeaking = FALSE; + } } - else if ( ( isPartialDisinfectInProgress != TRUE ) && ( ThdTemp > HEAT_DISINFECT_START_TEMPERATURE_C ) ) + + // Perform check if no pending alarm + if ( ALARM_ID_NO_ALARM == alarmDetectedPendingTrigger ) { - // 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; + // 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 ) + { + // Keep reseting the disinfect timer so the elapsed time is always 0 until disinfect truly starts + heatDisinfectTimer = getMSTimerCount(); + isPartialDisinfectInProgress = FALSE; + targetDisinfectTime = 0; - // In disinfect R1 to R2, concentrate pumps are also run - if ( DG_HEAT_DISINFECT_STATE_DISINFECT_R1_TO_R2 == heatDisinfectState ) + 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; + } + } + 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 ); @@ -2038,21 +1698,21 @@ requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); } } - else if ( ( TRUE == isPartialDisinfectInProgress ) && ( ThdTemp > HEAT_DISINFECT_START_TEMPERATURE_C ) ) - { - status = HEAT_DISINFECT_DISINFECT_IN_PROGRESS; - } - // 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 ) ) ) + // Perform check if no pending alarm + if ( ALARM_ID_NO_ALARM == alarmDetectedPendingTrigger ) { - // 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; + // 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 ) ) ) + { + // 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; + } } return status; @@ -2089,8 +1749,8 @@ uiData.heatDisinfectTargetTime = targetDisinfectTime; uiData.heatDisinfectCountdownTime = countDown / 1000; // The count down is converted into seconds since the UI does not work with milliseconds - data.R1FillLevel = R1HeatDisinfectVol; - data.R2FillLevel = R2HeatDisinfectVol; + data.R1FillLevel = rsrvr1RefVolML; + data.R2FillLevel = rsrvr2RefVolML; } else { @@ -2121,6 +1781,8 @@ *************************************************************************/ static void monitorModeHeatDisinfect( void ) { + BOOL areInletWaterAlarmsActive = FALSE; + #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_CAPS_MONITOR ) != SW_CONFIG_ENABLE_VALUE ) #endif @@ -2135,6 +1797,20 @@ alarmDetectedPendingTrigger = ALARM_ID_DG_DIALYSATE_OR_CONC_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 ) ) + { + prevHeatDisinfectState = heatDisinfectState; + heatDisinfectState = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; + } } /*********************************************************************//** @@ -2143,18 +1819,15 @@ * non-volatile memory. * @details Inputs: disinfectNVOps * @details Outputs: disinfectNVOps + * @param info the type disinfect data to write to the memory (i.e. heat + * disinfect start time) * @return: none *************************************************************************/ -static void writeDisinfectDataToNV( void ) +static void writeDisinfectDataToNV( DG_USAGE_INFO_ITEMS_T info ) { - if ( FALSE == disinfectNVOps.hasDisCompleteDateBeenWrittenToNV ) - { - disinfectNVOps.hasDisCompleteDateBeenWrittenToNV = setDisinfectStatus( TRUE ); - } - if ( FALSE == disinfectNVOps.hasDisStatusBeenWrittenToNV ) { - disinfectNVOps.hasDisStatusBeenWrittenToNV = setLastDisinfectDate( USAGE_INFO_HEAT_DISINFECT, getRTCTimestamp() ); + disinfectNVOps.hasDisStatusBeenWrittenToNV = setLastDisinfectDate( info, getRTCTimestamp() ); } }