Index: firmware/App/Modes/ModeHeatDisinfect.c =================================================================== diff -u -r8b8b9bbb288c06acec1fdf8a2e93248c3d775478 -r86eec09ab556fbd970ddcae9dc622727928ee757 --- firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 8b8b9bbb288c06acec1fdf8a2e93248c3d775478) +++ firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 86eec09ab556fbd970ddcae9dc622727928ee757) @@ -41,11 +41,11 @@ // General defines #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. +#define HEAT_DISINFECT_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Mode chem disinfect data publish interval in counts. // Start state defines #define MIN_INLET_PRESSURE_PSI 30.0 ///< Minimum water inlet pressure in psi. -#define MAX_START_STATE_TEMP_SENSORS_DIFF_C 1.0 ///< Max start state TDi and TRo difference tolerance in C. +#define MAX_START_STATE_TEMP_SENSORS_DIFF_C 3.0 ///< Max start state TDi and TRo difference tolerance in C. // Drain R1 & R2 states defines #define DRAIN_PUMP_TARGET_RPM 1800 ///< Drain pump target RPM during drain. @@ -106,7 +106,7 @@ CANCELLATION_MODE_HOT, ///< Cancellation mode hot. CANCELLATION_MODE_COLD, ///< Cancellation mode cold. NUM_OF_CANCELLATION_MODES ///< Number of cancellation modes. -} CANCELLATION_MODES_T; +} CANCELLATION_MODE_T; /// Heat disinfect status typedef enum Heat_disinfect_status @@ -137,7 +137,7 @@ 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_MODES_T cancellationMode = CANCELLATION_MODE_NONE; ///< Cancellation mode. +static CANCELLATION_MODE_T cancellationMode = CANCELLATION_MODE_NONE; ///< Cancellation mode. static U32 rsrvrFillStableTimeCounter = 0; ///< Reservoirs fill stable time counter. static ALARM_ID_T alarmDetectedPendingTrigger; ///< Heat disinfect alarm to raise. static BOOL isDrainPumpInMixDrainOn = FALSE; ///< Flag to show the drain pump is on during mix drain. @@ -182,8 +182,8 @@ * @details Outputs: heatDisinfectState, stateTimer, isThisLastDrain, * stateTrialCounter, areTempSensorsInRange, rsrvr1Status, rsrvr2Status, * R1HeatDisinfectVol, R2HeatDisinfectVol, overallHeatDisinfectTimer, - * cancellationMode, rsrvrFillStableTimeCounter, isPartialDisinfectInProgress, - * isDrainPumpOnInMixDrain + * cancellationMode, rsrvrFillStableTimeCounter, prevHeatDisinfectState + * isPartialDisinfectInProgress, isDrainPumpOnInMixDrain * @return none *************************************************************************/ void initHeatDisinfectMode( void ) @@ -406,7 +406,7 @@ F32 TDiTemp = getTemperatureValue( TEMPSENSORS_OUTLET_REDUNDANT ); //TODo change to TDi F32 TRoTemp = getTemperatureValue( TEMPSENSORS_OUTLET_REDUNDANT ); - // If the inlet pressure is less than the threshold and TDi and TRo difference is greater than 1 C, the cycle + // If the inlet pressure is less than the threshold and 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 ) ) { @@ -547,7 +547,7 @@ * @brief * The handleHeatDisinfectFlushDrainState function handles the heat disinfect * flush drain state. The state flushes the drain line for a period of time - * and then measure the temperature and conductivity of water. If they are + * and then measures the temperature and conductivity of water. If they are * not within the range, it transitions to basic cancellation path, otherwise * it transitions to the next state. * @details Inputs: stateTimer, stateTrialCounter, alarm, @@ -609,7 +609,7 @@ DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_FLUSH_CIRCULATION; // 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 ) ) + if ( ( TRUE == didTimeout( stateTimer, FLUSH_CICRCULATION_WAIT_TIME_MS ) ) && ( FALSE == areTempSensorsInRange ) ) { F32 ThdTemp = getTemperatureValue( TEMPSENSORS_OUTLET_REDUNDANT ); // TODO add THd later. This is the new temp sensor of the coldest spot. F32 TPoTemp = getTemperatureValue( TEMPSENSORS_OUTLET_PRIMARY_HEATER ); @@ -690,7 +690,7 @@ { rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_1, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS ); - // Keep monitoring the status of reservoir 2 as the same time + // 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 @@ -974,7 +974,7 @@ // 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_BACKUP ); //TODO change this back to primary + R1HeatDisinfectVol = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); R2HeatDisinfectVol = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); stateTimer = getMSTimerCount(); @@ -1318,6 +1318,18 @@ 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 ) { @@ -1388,6 +1400,21 @@ if ( DG_RESERVOIR_BELOW_TARGET == rsrvr2Status ) { rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS ); + + U32 drainPumpRPM = getTargetDrainPumpRPM(); + // Keep monitoring the status of reservoir 1 as the same time + F32 volume = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); + // 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 ) @@ -1592,7 +1619,7 @@ * @brief * The failHeatDisinfect function sets the alarm that failed the heat * disinfect mode. - * @details Inputs: alarm, prevHeatDisinfectState + * @details Inputs: alarmDetectedPendingTrigger, prevHeatDisinfectState * @details Outputs: none * @return none *************************************************************************/ @@ -1620,7 +1647,7 @@ if ( r == DG_RESERVOIR_1 ) { - volume = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_BACKUP ); //TODO change back to primary + volume = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); } else if ( r == DG_RESERVOIR_2 ) { @@ -1659,8 +1686,7 @@ * reservoir. * @details Inputs: stateTimer, prevHeatDisinfectState, heatDisinfectState, * alarm - * @details Outputs: stateTimer, heatDisinfectState heatDisinfectState, - * alarm + * @details Outputs: stateTimer, heatDisinfectState, alarm * @param r is DG_RESERVOIR_1 or DG_RESERVOIR_2 * @param drainSteadyStateTimeout which is the time the reservoir's level * does not change and is steady state @@ -1711,11 +1737,11 @@ F32 TPoTemp = getTemperatureValue( TEMPSENSORS_OUTLET_PRIMARY_HEATER ); F32 ThdTemp = getTemperatureValue( TEMPSENSORS_OUTLET_REDUNDANT ); //TODO change this to actual TPm sensor later - BOOL isR1OutOfRange = fabs( getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_BACKUP ) - R1HeatDisinfectVol ) > RSRVRS_MAX_TARGET_VOL_CHANGE_ML; //TODo change this to primary when the stupid load cell was fixed + 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 either reservoir 1 or reservoir 2 are losing volume more than allowed volume - if ( isR1OutOfRange || isR2OutOfRange ) + 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 )