Index: firmware/App/Modes/ModeHeatDisinfect.c =================================================================== diff -u -raada74112204bc8e7c004510d0c86afb88cccc14 -r87acb1655edbf974497e4300f2c18eea62f8acba --- firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision aada74112204bc8e7c004510d0c86afb88cccc14) +++ firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 87acb1655edbf974497e4300f2c18eea62f8acba) @@ -55,7 +55,7 @@ // Flush drain path state defines #define FLUSH_DRAIN_WAIT_TIME_MS ( 1 * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. TODo original time was 60 seconds -#define MIN_INLET_TEMPERATURE_C 25.0 ///< Minimum water inlet temperature in C. +#define MIN_INLET_TEMPERATURE_C 15.0 ///< Minimum water inlet temperature in C. TODO original temperature was 25 C #define MIN_INLET_CONDUCTIVITY_US_PER_CM 0.0 ///< Minimum water inlet conductivity in uS/cm #define MAX_INLET_CONDUCTIVITY_US_PER_CM 2000.0 ///< Maximum water inlet conductivity in us/cm @@ -73,21 +73,21 @@ #define RSRVRS_DRAIN_TIMEOUT_MS ( 2 * 60 * MS_PER_SECOND ) ///< Reservoirs 1 & 2 drain timeout in ms. // Fill and heat water -#define HEAT_DISINFECT_TARGET_TEMPERATURE_C 88.0 ///< Heat disinfect target water temperature in C. +#define HEAT_DISINFECT_TARGET_TEMPERATURE_C 35.0 ///< Heat disinfect target water temperature in C. TODO original temperature was 88.0 // R1 to R2 & R2 to R1 heat disinfect circulation #define HEAT_DISINFECT_TARGET_RO_FLOW_LPM 0.6 ///< Heat disinfect target RO flow rate in L/min. #define HEAT_DISINFECT_MAX_RO_PRESSURE_PSI 30 ///< Heat disinfect maximum RO pressure in psi. #define HEAT_DISINFECT_TARGET_DRAIN_PRES_PSI 1.0 ///< Heat disinfect target drain outlet pressure in psi. -#define HEAT_DISINFECT_START_TEMPERATURE_C 81.0 ///< Heat disinfect minimum acceptable temperature in C. -#define HEAT_DISINFECT_TIME_MS ( 10 * 60 * MS_PER_SECOND ) ///< Heat disinfect time for each section in milliseconds. -#define HEAT_DISINFECT_START_TEMP_TIMOUT_MS ( 30 * 60 * MS_PER_SECOND ) ///< Heat disinfect reaching to minimum temperature timeout in milliseconds. +#define HEAT_DISINFECT_START_TEMPERATURE_C 31.0 ///< Heat disinfect minimum acceptable temperature in C. TODO original temperature was 81.0 +#define HEAT_DISINFECT_TIME_MS ( 0.5 * 60 * MS_PER_SECOND ) ///< Heat disinfect time for each section in milliseconds. TODO original time was 10 minutes +#define HEAT_DISINFECT_START_TEMP_TIMOUT_MS ( 30 * 60 * MS_PER_SECOND ) ///< Heat disinfect reaching to minimum temperature timeout in milliseconds. #define RSRVRS_TARGET_VOL_OUT_TIMEOUT_MS ( 2 * 60 * MS_PER_SECOND ) ///< Reservoirs 1 & 2 maximum volume out of range timeout during heat disnfect. #define RSRVRS_MAX_TARGET_VOL_CHANGE_ML 100.0 ///< Reservoirs 1 & 2 maximum allowed volume change when full during heat disinfect. #define POST_HEAT_DISINFECT_WAIT_TIME_MS ( 1 * 60 * MS_PER_SECOND ) ///< Heat disinfect final wait time before flushing the system in milliseconds. // Rinse R1 to R2 -#define ROF_MIN_LOW_PRESSURE_TEMPERATURE_C 45.0 ///< RO filter minimum temperature that the pressure must be no more than 30psi in C. +#define ROF_MIN_LOW_PRESSURE_TEMPERATURE_C 30.0 ///< RO filter minimum temperature that the pressure must be no more than 30psi in C. TODO the actual value is 45.0 /// TODO remove? typedef enum rsvrs_status @@ -131,11 +131,12 @@ static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectFlushDrainR1State( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectFillWithWaterState( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectDisinfectR1ToR2State( void ); -static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectFillR2WithHotWater( void ); +static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectFillR2WithHotWaterState( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectDisinfectR2ToR1State( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectMixDrainR1State( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectMixDrainR2State( void ); -static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectRinseR1ToR2( void ); +static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectCoolDownROFilterState( 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 handleHeatDisinfectCancelModeBasicPath( void ); @@ -198,7 +199,7 @@ *************************************************************************/ U32 execHeatDisinfectMode( void ) { - checkInletPressureFault(); // TODO what is this? + //checkInletPressureFault(); // TODO what is this? switch ( heatDisinfectState ) { @@ -247,7 +248,7 @@ break; case DG_HEAT_DISINFECT_STATE_FILL_R2_WITH_HOT_WATER: - heatDisinfectState = handleHeatDisinfectFillR2WithHotWater(); + heatDisinfectState = handleHeatDisinfectFillR2WithHotWaterState(); break; case DG_HEAT_DISINFECT_STATE_DISINFECT_R2_TO_R1: @@ -262,8 +263,12 @@ heatDisinfectState = handleHeatDisinfectMixDrainR2State(); break; + case DG_HEAT_DISINFECT_STATE_COOL_DOWN_RO_FILTER: + heatDisinfectState = handleHeatDisinfectCoolDownROFilterState(); + break; + case DG_HEAT_DISINFECT_STATE_RINSE_R1_TO_R2: - heatDisinfectState = handleHeatDisinfectRinseR1ToR2(); + heatDisinfectState = handleHeatDisinfectRinseR1ToR2State(); break; case DG_HEAT_DISINFECT_STATE_RINSE_R2_TO_R1_AND_DRAIN_R1: @@ -284,7 +289,7 @@ break; case DG_HEAT_DISINFECT_STATE_COMPLETE: - // Done with heat disinfect cycle, complete or not + // Done with heat disinfect cycle, failed or not break; default: @@ -394,10 +399,10 @@ //TODO turn on the concentrate pumps - // TODO discuss the cooling process for proper flow rate and pressure set + // Set the RO pump to run at full pressure setROPumpTargetFlowRate( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); - // Done with final rinsing + // Done with final draining isThisLastDrain = FALSE; stateTimer = getMSTimerCount(); state = DG_HEAT_DISINFECT_STATE_RINSE_CIRCULATION; @@ -467,7 +472,7 @@ if ( didTimeout( stateTimer, FLUSH_DRAIN_WAIT_TIME_MS ) ) { // If the inlet temperature and conductivity are in range, move onto the next state - if ( getTemperatureValue( TEMPSENSORS_INLET_PRIMARY_HEATER ) > 15 /*MIN_INLET_TEMPERATURE_C && TODO bring the code back + if ( getTemperatureValue( TEMPSENSORS_INLET_PRIMARY_HEATER ) > MIN_INLET_TEMPERATURE_C /*&& TODO bring the code back getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ) > MIN_INLET_CONDUCTIVITY_US_PER_CM*/ ) { setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); @@ -481,7 +486,7 @@ { stateTimer = getMSTimerCount(); } - // Couldn't get a good water sample after a couple of trials and the disinfection cycle failed + // Couldn't get a good water sample after a couple of trials and the disinfect cycle failed else { setModeToFailed( state ); @@ -805,25 +810,26 @@ /*********************************************************************//** * @brief - * The handleHeatDisinfectFillR2WithHotWater function handles fill R2 + * The handleHeatDisinfectFillR2WithHotWaterState function handles fill R2 * with water state. * @details Inputs: R1HeatDisinfectVol, R2HeatDisinfectVol * @details Outputs: R1HeatDisinfectVol, R2HeatDisinfectVol * @return next state of the heat disinfect state machine *************************************************************************/ -static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectFillR2WithHotWater( void ) +static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectFillR2WithHotWaterState( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_FILL_R2_WITH_HOT_WATER; // In this state, R2 is fully filled up and R1 is partially filled up with hot water // So waiting for R1 to get to the level of defined partially full - BOOL isR1PartiallyFull = fabs( getLoadCellFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ) - RSRVRS_PARTIAL_FILL_VOL_ML ) < RSRVRS_MAX_TARGET_VOL_CHANGE_ML; + BOOL isR1PartiallyFull = fabs( getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ) - RSRVRS_PARTIAL_FILL_VOL_ML ) < + RSRVRS_MAX_TARGET_VOL_CHANGE_ML; if ( isRsrvrFull( DG_RESERVOIR_2, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS, state ) && isR1PartiallyFull ) { // Get the current volumes to be monitored during R2 to R1 heat disinfect state - R1HeatDisinfectVol = getLoadCellFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); - R2HeatDisinfectVol = getLoadCellFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); + R1HeatDisinfectVol = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); + R2HeatDisinfectVol = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); //TODO turn on CP1 and CP2 @@ -843,10 +849,10 @@ *************************************************************************/ static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectDisinfectR2ToR1State( void ) { - DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_FILL_R2_WITH_HOT_WATER; + DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_DISINFECT_R2_TO_R1; - // Keep monitoring for the end of heat disinfect and while the port delay has not started - if ( isStateHeatDisinfectComplete( state ) && FALSE == hasPostHeatDisinfectWaitStarted ) + // Keep monitoring for the end of heat disinfect and while the post delay has not started + if ( isStateHeatDisinfectComplete( state ) && hasPostHeatDisinfectWaitStarted != TRUE ) { // Turn off the pumps and heaters //TODO turn off CP1 and CP2 @@ -858,10 +864,11 @@ } else if ( hasPostHeatDisinfectWaitStarted && didTimeout( stateTimer, POST_HEAT_DISINFECT_WAIT_TIME_MS ) ) { - // Stop the drain pump to exit the closed loop + // Stop the drain pump and the RO pump to exit the closed loop signalDrainPumpHardStop(); + signalROPumpHardStop(); - // Deenergize all the valves that are not in the path anymore and set the other + // De-energize all the valves that are not in the path anymore and set the other // valves to drain the hot water setValveState( VPI, VALVE_STATE_OPEN ); setValveState( VBF, VALVE_STATE_CLOSED ); @@ -871,6 +878,7 @@ setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); + setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NC ); // Turn on the drain pump to drain the reservoirs in open loop mode setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); @@ -928,18 +936,45 @@ // Done with draining the reservoirs signalDrainPumpHardStop(); + 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. + * @details Inputs: stateTimer + * @details Outputs: stateTimer + * @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; + + F32 ThdTemp = getTemperatureValue( TEMPSENSORS_INLET_DIALYSATE ); //TODO change this to actual TPm sensor later + + // Check if the coldest spot temperature is less than 45 C so the RO filter + // can safely run fluid through + if ( ThdTemp < ROF_MIN_LOW_PRESSURE_TEMPERATURE_C ) + { // Set the valves to fill up R1 and overflow to R2 - // The RO pump is still running at low pressure until the coldest - // spot temperature is less than 45 C. setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); 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 ); - + setROPumpTargetFlowRate( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); + // Set both reservoirs status to FLASE + isR1Full = FALSE; + isR2Full = FALSE; stateTimer = getMSTimerCount(); + state = DG_HEAT_DISINFECT_STATE_RINSE_R1_TO_R2; } @@ -948,25 +983,23 @@ /*********************************************************************//** * @brief - * The handleHeatDisinfectRinseR1ToR2 function handles the heat + * The handleHeatDisinfectRinseR1ToR2State function handles the heat * disinfect rinse R1 to R2 state. * @details Inputs: stateTimer, isR1Full, isR2Full * @details Outputs: stateTimer, isR1Full, isR2Full * @return next state of the heat disinfect state machine *************************************************************************/ -static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectRinseR1ToR2( void ) +static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectRinseR1ToR2State( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_RINSE_R1_TO_R2; - if ( FALSE == isR1Full ) + if ( isR1Full != TRUE ) { - // Since reservoir 1 is being filled up at a lower flow rate, the timeout is twice as long as a normal fill up - isR1Full = isRsrvrFull( DG_RESERVOIR_1, RSRVRS_FULL_VOL_ML, 2 * RSRVRS_FILL_UP_TIMEOUT_MS, state ); + isR1Full = isRsrvrFull( DG_RESERVOIR_1, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS, state ); } - else + if ( isR1Full ) { - // Since reservoir 2 is being filled up at a lower flow rate, the timeout is longer than a normal fill up - isR2Full = isRsrvrFull( DG_RESERVOIR_2, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS, state ); + isR2Full = isRsrvrFull( DG_RESERVOIR_2, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_500ML_FILL_UP_TIMEOUT_MS, state ); if ( isR2Full ) { @@ -975,9 +1008,11 @@ setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); - setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); + // Set both reservoirs status to FLASE + isR1Full = FALSE; + isR2Full = FALSE; stateTimer = getMSTimerCount(); state = DG_HEAT_DISINFECT_STATE_RINSE_R2_TO_R1_AND_DRAIN_R1; } @@ -998,46 +1033,43 @@ { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_RINSE_R2_TO_R1_AND_DRAIN_R1; - if ( isR1Full ) + if ( isRsrvrEmpty( DG_RESERVOIR_1, DRAIN_WEIGH_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS, state ) ) { - // Since reservoir 1 is being filled up at a lower flow rate, the timeout is twice as long as a normal fill up - isR1Full = isRsrvrEmpty( DG_RESERVOIR_1, DRAIN_WEIGH_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS, state ); - // Done with draining R1 signalDrainPumpHardStop(); } - else if ( FALSE == isR1Full ) + + // First reservoir 2 must be completely full + if ( isR2Full != TRUE ) { - if ( FALSE == isR2Full ) + isR2Full = isRsrvrFull( DG_RESERVOIR_2, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS, state ); + } + // Once reservoir 2 is completely full, monitor reservoir 1 + if ( isR2Full ) + { + isR1Full = isRsrvrFull( DG_RESERVOIR_1, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_500ML_FILL_UP_TIMEOUT_MS, state ); + + if ( isR1Full ) { - isR2Full = isRsrvrFull( DG_RESERVOIR_2, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS, state ); - } - else - { - isR1Full = isRsrvrFull( DG_RESERVOIR_1, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_500ML_FILL_UP_TIMEOUT_MS, state ); + // Done with filling, turn off the RO pump + signalROPumpHardStop(); - if ( isR1Full ) - { - // Done with filling, turn off the RO pump - signalROPumpHardStop(); + // Deenergize all the valves and set the VDr to drain R2 + setValveState( VPI, VALVE_STATE_CLOSED ); + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); + setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); + setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); + setValveState( VRD, VALVE_STATE_R2_C_TO_NO ); + setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); + setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); - // Deenergize all the valves and set the VDr to drain R2 - setValveState( VPI, VALVE_STATE_CLOSED ); - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); - setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); - setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); - setValveState( VRD, VALVE_STATE_R2_C_TO_NO ); - 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 on the drain pump to drain R2 - setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); - - // This is the last drain of heat disinfect cycle - isThisLastDrain = TRUE; - stateTimer = getMSTimerCount(); - state = DG_HEAT_DISINFECT_STATE_DRAIN_R2; - } + // This is the last drain of heat disinfect cycle + isThisLastDrain = TRUE; + stateTimer = getMSTimerCount(); + state = DG_HEAT_DISINFECT_STATE_DRAIN_R2; } } @@ -1223,7 +1255,7 @@ else if ( didTimeout( rsrvrsVolMonitorTimer, RSRVRS_TARGET_VOL_OUT_TIMEOUT_MS ) ) { areRsrvrsLeaking = FALSE; - //setModeToFailed( state ); TODO uncomment + setModeToFailed( state ); } } // We are in range @@ -1241,10 +1273,11 @@ if ( didTimeout( stateTimer, HEAT_DISINFECT_START_TEMP_TIMOUT_MS ) ) { // Heating up to minimum temperature for heat disinfect failed - setModeToFailed( state ); + //setModeToFailed( state ); TODO un-comment + BOOL test = FALSE; } } - else + else if ( hasHeatDisinfectStarted != TRUE && TPmTemp > HEAT_DISINFECT_START_TEMPERATURE_C ) { // The temperature of the coldest spot is in range start. Start the timer for heat disinfect cycle heatDisinfectTimer = getMSTimerCount(); @@ -1254,7 +1287,7 @@ // If the flag is TRUE, check if this stage of heat disinfect is done if ( hasHeatDisinfectStarted ) { - if ( didTimeout( heatDisinfectTimer, HEAT_DISINFECT_START_TEMP_TIMOUT_MS ) ) + if ( didTimeout( heatDisinfectTimer, HEAT_DISINFECT_TIME_MS ) ) { // Done with this stage of heat disnfect. Reset the variables heatDisinfectStatus = TRUE; @@ -1279,11 +1312,20 @@ { MODE_HEAT_DISINFECT_DATA_T data; - data.heatDisinfectState = (U32)heatDisinfectState; - data.overallElapsedTime = calcTimeSince( overallHeatDisinfectTimer ); - data.stateElapsedTime = calcTimeSince( stateTimer ); - data.heatDisinfectElapsedTime = 0; + data.heatDisinfectState = (U32)heatDisinfectState; // TODO remove + data.overallElapsedTime = calcTimeSince( overallHeatDisinfectTimer ); + data.stateElapsedTime = calcTimeSince( stateTimer ); + // If the mode is in the actual heat disinfect states, publish the elapsed time, otherwise publish 0 to avoid confusion + if ( heatDisinfectState == DG_HEAT_DISINFECT_STATE_DISINFECT_R1_TO_R2 || heatDisinfectState == DG_HEAT_DISINFECT_STATE_DISINFECT_R2_TO_R1 ) + { + data.heatDisinfectElapsedTime = calcTimeSince( heatDisinfectTimer ); + } + else + { + data.heatDisinfectElapsedTime = 0; + } + broadcastHeatDisinfectData( &data ); dataPublishCounter = 0;