Index: firmware/App/Modes/ModeHeatDisinfect.c =================================================================== diff -u -r2510a84808ee5179d3f84f0b04f24c5a4122dbe5 -r518fb519933260477ba20118744399f94ac1a632 --- firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 2510a84808ee5179d3f84f0b04f24c5a4122dbe5) +++ firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 518fb519933260477ba20118744399f94ac1a632) @@ -35,27 +35,47 @@ // ********** private definitions ********** -#define HEAT_DISINFECTION_TARGET_TEMP 85U ///< Heat disinfection target temperature -#define HEAT_DISINFECTION_OVERALL_TIME 60U ///< Heat disinfection overall time in minutes -#define HEAT_DISINFECTION_RECIRC_PATH_TIME_MINS 5U -#define HEAT_DISINFECTION_FLUSH_TIME_MINS 3U -#define HEAT_DISINFECTION_OVERALL_TIME_MINS 30U +#define HEAT_DISINFECT_TARGET_TEMPERATURE 85U ///< Heat disinfection target temperature +#define MAX_TPO_AND_TDI_SENSORS_DIFFERENCE 1U +#define MAX_TEMPERATURE_DEVIATION_FROM_TARGET 4U +#define HEAT_DISINFECT_EVAC_RECIRC_PATH_TIME_MS 4000U //TODo do we need this? +#define HEAT_DISINFECT_RECIRC_PATH_TIME_MS 120000U +#define HEAT_DISINFECT_FLUSH_TIME_MINS 3U +#define HEAT_DISINFECT_OVERALL_TIME_MINS 50U + #define DRAIN_PUMP_TARGET_DELTA_PRESSURE 0U #define DRAIN_PUMP_TARGET_RPM 2800U #define RO_PUMP_TARGET_FLOW_RATE_LPM 0.9 +#define FULL_RESERVOIRS_WEIGHT_GRAMS 2000U +#define EMPTY_RESERVOIRS_WEIGHT_GRAMS 0U + // ********** private data ********** +/// Heat disinfect evacuate states +typedef enum evacuate_path +{ + EVACUATE_OFF_STATE = 0, + EVACUATE_RECIRC_PATH_STATE, + EVACUATE_RESERVOIR_1_STATE, + EVACUATE_RESERVOIR_2_STATE, + NUM_OF_EVACUTE_STATES +} HEAT_DISINFECT_EVACUTE_STATE_T; //TODO do we need this enum? + +static HEAT_DISINFECT_EVACUTE_STATE_T heatDisinfectEvacState = EVACUATE_OFF_STATE; static DG_HEAT_DISINFECT_STATE_T heatDisinfectionState = DG_HEAT_DISINFECT_STATE_START; ///< Currently active heat disinfect state. -static BOOL hasTemperatureReachedToTarget; static U32 heatDisinfectElapsedTime; +static U32 stateTimer; // ********** private function prototypes ********** -static void setActuatorsToStop( void ); +static void stopActuators( void ); +static BOOL isTemperatureInRange( void ); +static void execEvacuateFluidPath( void ); // TODO may not be needed (internal state machine) static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectStart( void ); +static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectEvacDialysateRecircPath( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectEvacDialysateReservoir1( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectEvacDialysateReservoir2( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectFillWithWater( void ); @@ -91,7 +111,7 @@ void transitionToHeatDisinfectMode( void ) { initHeatDisinfectMode(); - setActuatorsToStop(); + stopActuators(); } /*********************************************************************//** @@ -111,6 +131,9 @@ heatDisinfectionState = handleHeatDisinfectStart(); break; + case DG_HEAT_DISINFECT_STATE_EVAC_RECIRC_PATH: + break; + case DG_HEAT_DISINFECT_STATE_EVAC_DIALYSATE_RESERVOIR_1: heatDisinfectionState = handleHeatDisinfectEvacDialysateReservoir1(); break; @@ -180,8 +203,7 @@ *************************************************************************/ void startDGHeatDisinfect( void ) { - // NOTE: make sure DG is not in the middle of something and it is in standby - // + // TODO: make sure DG is not in the middle of something and it is in standby initHeatDisinfectMode(); requestNewOperationMode( DG_MODE_HEAT ); } @@ -196,80 +218,159 @@ *************************************************************************/ void stopDGHeatDisinfect( void ) { - //heatDisinfectionState = DG_HEAT_DISINFECT_STATE_START; // request standby mode - setActuatorsToStop(); + heatDisinfectionState = DG_HEAT_DISINFECT_STATE_COMPLETE; + stopActuators(); requestNewOperationMode( DG_MODE_STAN ); } // ********** private function definitions ********** static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectStart( void ) { - DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_EVAC_DIALYSATE_RESERVOIR_1; + DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_EVAC_RECIRC_PATH; - setActuatorsToStop(); + stopActuators(); - /*setValveState ( VPI, VALVE_STATE_OPEN ); + // Set the actuators for evacuate recirculation path + setValveState ( VPI, VALVE_STATE_OPEN ); setValveState ( VBF, VALVE_STATE_OPEN ); setValveState ( VSP, VALVE_STATE_CLOSED ); setValveState ( VPD, VALVE_STATE_OPEN_C_TO_NO ); setValveState ( VPO, VALVE_STATE_NOFILL_C_TO_NO ); setValveState ( VDR, VALVE_STATE_DRAIN_C_TO_NO ); - setValveState ( VRC, VALVE_STATE_RECIRC_C_TO_NC ); + setValveState ( VRC, VALVE_STATE_DRAIN_C_TO_NO ); setValveState ( VRO, VALVE_STATE_R2_C_TO_NO ); - setValveState ( VRD, VALVE_STATE_R1_C_TO_NC ); - setValveState ( VRI, VALVE_STATE_R2_C_TO_NC ); - setValveState ( VRF, VALVE_STATE_R1_C_TO_NC ); + setValveState ( VRD, VALVE_STATE_R1_C_TO_NO ); + setValveState ( VRI, VALVE_STATE_R1_C_TO_NO ); + setValveState ( VRF, VALVE_STATE_R2_C_TO_NO ); + setROPumpTargetFlowRate( RO_PUMP_TARGET_FLOW_RATE_LPM ); + stateTimer = getMSTimerCount(); // For evac recirc path - setROPumpTargetFlowRate( 0 ); - //setDrainPumpTargetSpeed( DRAIN_PUMP_TARGET_RPM, PUMP_CONTROL_MODE_OPEN_LOOP ); - stopInletUVReactor(); - stopOutletUVReactor(); - stopPrimaryHeater(); - stopTrimmerHeater();*/ + return state; +} - //TODO FOR TESTING ONLY, REMOVE - state = DG_HEAT_DISINFECT_STATE_DISINFECT_RECIRC_PATH; - //TODO FOR TESTING ONLY, REMOVE +static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectEvacDialysateRecircPath( void ) +{ + DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_EVAC_RECIRC_PATH; + if ( didTimeout( stateTimer, HEAT_DISINFECT_EVAC_RECIRC_PATH_TIME_MS ) ) + { + // Set the state to evacuate reservoir 1 + signalROPumpHardStop(); + setValveState ( VPI, VALVE_STATE_OPEN ); + setValveState ( VBF, VALVE_STATE_OPEN ); + setValveState ( VSP, VALVE_STATE_CLOSED ); + setValveState ( VPD, VALVE_STATE_OPEN_C_TO_NO ); + 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_R2_C_TO_NO ); + setValveState ( VRD, VALVE_STATE_R1_C_TO_NC ); + setValveState ( VRI, VALVE_STATE_R1_C_TO_NO ); + setValveState ( VRF, VALVE_STATE_R2_C_TO_NO ); + setDrainPumpTargetSpeed ( DRAIN_PUMP_TARGET_RPM ); + + state = DG_HEAT_DISINFECT_STATE_EVAC_DIALYSATE_RESERVOIR_1; + } + return state; } static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectEvacDialysateReservoir1( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_EVAC_DIALYSATE_RESERVOIR_1; - setValveState ( VPI, VALVE_STATE_OPEN ); - setValveState ( VBF, VALVE_STATE_OPEN ); - setValveState ( VSP, VALVE_STATE_CLOSED ); - setValveState ( VPD, VALVE_STATE_OPEN_C_TO_NO ); - setValveState ( VPO, VALVE_STATE_NOFILL_C_TO_NO ); - setValveState ( VDR, VALVE_STATE_RECIRC_C_TO_NC ); - setValveState ( VRC, VALVE_STATE_RECIRC_C_TO_NC ); - setValveState ( VRO, VALVE_STATE_R2_C_TO_NO ); - setValveState ( VRD, VALVE_STATE_R1_C_TO_NO ); - setValveState ( VRI, VALVE_STATE_R1_C_TO_NO ); - setValveState ( VRF, VALVE_STATE_R2_C_TO_NO ); + F32 reservoir1Weight = getLoadCellFilteredWeight ( LOAD_CELL_A1 ); - setROPumpTargetFlowRate( 0 ); - signalDrainPumpHardStop(); - stopInletUVReactor(); - stopOutletUVReactor(); - stopPrimaryHeater(); - stopTrimmerHeater(); + if ( reservoir1Weight <= EMPTY_RESERVOIRS_WEIGHT_GRAMS ) + { + // Set the state to evacuate reservoir 2 + setValveState ( VPI, VALVE_STATE_OPEN ); + setValveState ( VBF, VALVE_STATE_OPEN ); + setValveState ( VSP, VALVE_STATE_CLOSED ); + setValveState ( VPD, VALVE_STATE_OPEN_C_TO_NO ); + 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_R2_C_TO_NO ); + setValveState ( VRD, VALVE_STATE_R1_C_TO_NO ); + setValveState ( VRI, VALVE_STATE_R1_C_TO_NO ); + setValveState ( VRF, VALVE_STATE_R2_C_TO_NO ); + //setDrainPumpTargetSpeed ( DRAIN_PUMP_TARGET_RPM ); probably it is not needed + state = DG_HEAT_DISINFECT_STATE_EVAC_DIALYSATE_RESERVOIR_2; + } + return state; } static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectEvacDialysateReservoir2( void ) { + DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_EVAC_DIALYSATE_RESERVOIR_2; + F32 reservoir2Weight = getLoadCellFilteredWeight ( LOAD_CELL_B1 ); + + if ( reservoir2Weight <= EMPTY_RESERVOIRS_WEIGHT_GRAMS ) + { + // Set the state to fill water + setValveState ( VPI, VALVE_STATE_OPEN ); + setValveState ( VBF, VALVE_STATE_OPEN ); + setValveState ( VSP, VALVE_STATE_CLOSED ); + 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 ( VRO, VALVE_STATE_R2_C_TO_NO ); + setValveState ( VRD, VALVE_STATE_R2_C_TO_NO ); + setValveState ( VRI, VALVE_STATE_R2_C_TO_NC ); + setValveState ( VRF, VALVE_STATE_R1_C_TO_NC ); + setROPumpTargetFlowRate( RO_PUMP_TARGET_FLOW_RATE_LPM ); + + // Start the UV reactors to disinfect the water that + // is being filled up + startInletUVReactor(); + startOutletUVReactor(); + + state = DG_HEAT_DISINFECT_STATE_FILL_WITH_WATER; + } + + return state; } static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectFillWithWater( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_FILL_WITH_WATER; + F32 reservoir1Weight = getLoadCellFilteredWeight ( LOAD_CELL_A1 ); + F32 reservoir2Weight = getLoadCellFilteredWeight ( LOAD_CELL_B1 ); + + if ( reservoir1Weight >= FULL_RESERVOIRS_WEIGHT_GRAMS && + reservoir2Weight >= FULL_RESERVOIRS_WEIGHT_GRAMS ) + { + // Drain pump is stopped to exit the open loop mode + signalDrainPumpHardStop(); + + setValveState ( VPI, VALVE_STATE_OPEN ); + setValveState ( VBF, VALVE_STATE_OPEN ); + setValveState ( VSP, VALVE_STATE_CLOSED ); + setValveState ( VPD, VALVE_STATE_OPEN_C_TO_NO ); + setValveState ( VPO, VALVE_STATE_FILL_C_TO_NC ); + setValveState ( VDR, VALVE_STATE_RECIRC_C_TO_NC ); + setValveState ( VRC, VALVE_STATE_RECIRC_C_TO_NC ); + setValveState ( VRO, VALVE_STATE_R2_C_TO_NC ); + setValveState ( VRD, VALVE_STATE_R2_C_TO_NC ); + setValveState ( VRI, VALVE_STATE_R1_C_TO_NO ); + setValveState ( VRF, VALVE_STATE_R2_C_TO_NO ); + + setROPumpTargetFlowRate( RO_PUMP_TARGET_FLOW_RATE_LPM ); + setDrainPumpTargetDeltaPressure( DRAIN_PUMP_TARGET_DELTA_PRESSURE ); + + setPrimaryHeaterTargetTemperature( HEAT_DISINFECT_TARGET_TEMPERATURE ); + startPrimaryHeater(); + + state = DG_HEAT_DISINFECT_STATE_HEAT_WATER; + } + return state; } @@ -278,37 +379,58 @@ { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_HEAT_WATER; - return state; + F32 TPi = getTemperatureValue ( TEMPSENSORS_OUTLET_PRIMARY_HEATER_TEMP_SENSOR ); + F32 TDi = getTemperatureValue ( TEMPSENSORS_INLET_DIALYSATE_TEMP_SENSOR ); + if ( fabs(TPi - TDi) <= MAX_TPO_AND_TDI_SENSORS_DIFFERENCE ) + { + setValveState ( VPI, VALVE_STATE_OPEN ); + setValveState ( VBF, VALVE_STATE_OPEN ); + setValveState ( VSP, VALVE_STATE_CLOSED ); + setValveState ( VPD, VALVE_STATE_OPEN_C_TO_NO ); + setValveState ( VPO, VALVE_STATE_NOFILL_C_TO_NO ); + setValveState ( VDR, VALVE_STATE_RECIRC_C_TO_NC ); + setValveState ( VRC, VALVE_STATE_RECIRC_C_TO_NC ); + setValveState ( VRO, VALVE_STATE_R2_C_TO_NO ); + setValveState ( VRD, VALVE_STATE_R1_C_TO_NO ); + setValveState ( VRI, VALVE_STATE_R1_C_TO_NO ); + setValveState ( VRF, VALVE_STATE_R2_C_TO_NO ); + stateTimer = getMSTimerCount(); + state = DG_HEAT_DISINFECT_STATE_DISINFECT_RECIRC_PATH; + } + + return state; } static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectRecirculationPath( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_DISINFECT_RECIRC_PATH; - setValveState ( VPI, VALVE_STATE_OPEN ); - setValveState ( VBF, VALVE_STATE_OPEN ); - setValveState ( VSP, VALVE_STATE_CLOSED ); - setValveState ( VPD, VALVE_STATE_OPEN_C_TO_NO ); - setValveState ( VPO, VALVE_STATE_NOFILL_C_TO_NO ); - //setValveState ( VDR, VALVE_STATE_RECIRC_C_TO_NC ); //For the actual heat disinfection - setValveState ( VDR, VALVE_STATE_DRAIN_C_TO_NO ); // For sending the fluid to drain for pump testing - setValveState ( VRC, VALVE_STATE_DRAIN_C_TO_NO ); - setValveState ( VRO, VALVE_STATE_R2_C_TO_NO ); - setValveState ( VRD, VALVE_STATE_R1_C_TO_NO ); - setValveState ( VRI, VALVE_STATE_R1_C_TO_NO ); - setValveState ( VRF, VALVE_STATE_R2_C_TO_NO ); + // If the temperature is out of tolerance, go back to heat water + if ( ! isTemperatureInRange() ) + { + state = DG_HEAT_DISINFECT_STATE_HEAT_WATER; + } + else if ( didTimeout( stateTimer, HEAT_DISINFECT_EVAC_RECIRC_PATH_TIME_MS ) ) + { + heatDisinfectElapsedTime = heatDisinfectElapsedTime + HEAT_DISINFECT_EVAC_RECIRC_PATH_TIME_MS; //TODO Test + setValveState ( VPI, VALVE_STATE_OPEN ); + setValveState ( VBF, VALVE_STATE_OPEN ); + setValveState ( VSP, VALVE_STATE_CLOSED ); + setValveState ( VPD, VALVE_STATE_OPEN_C_TO_NO ); + setValveState ( VPO, VALVE_STATE_FILL_C_TO_NC ); + setValveState ( VDR, VALVE_STATE_RECIRC_C_TO_NC ); + setValveState ( VRC, VALVE_STATE_RECIRC_C_TO_NC ); + setValveState ( VRO, VALVE_STATE_R2_C_TO_NO ); + setValveState ( VRD, VALVE_STATE_R1_C_TO_NO ); + setValveState ( VRI, VALVE_STATE_R2_C_TO_NC ); + setValveState ( VRF, VALVE_STATE_R1_C_TO_NC ); - setROPumpTargetFlowRate( 0.75 ); - //setDrainPumpTargetSpeed( 0, PUMP_CONTROL_MODE_CLOSED_LOOP ); - //startInletUVReactor(); - //startOutletUVReactor(); - //startPrimaryHeater(); - //stopTrimmerHeater(); + setDrainPumpTargetDeltaPressure( DRAIN_PUMP_TARGET_DELTA_PRESSURE ); + setROPumpTargetFlowRate( RO_PUMP_TARGET_FLOW_RATE_LPM ); - // For debugging purposes only REMOVE - state = DG_HEAT_DISINFECT_STATE_DISINFECT_RESERVOIR_1_TO_2; - // For debugging purposes only REMOVE + state = DG_HEAT_DISINFECT_STATE_DISINFECT_RESERVOIR_1_TO_2; + } return state; } @@ -340,8 +462,31 @@ return state; } -static void setActuatorsToStop( void ) +static void execEvacuateFluidPath( void ) { + switch ( heatDisinfectEvacState ) + { + case EVACUATE_OFF_STATE: + break; + + case EVACUATE_RECIRC_PATH_STATE: + break; + + case EVACUATE_RESERVOIR_1_STATE: + break; + + case EVACUATE_RESERVOIR_2_STATE: + break; + + default: + break; + } +} + + + +static void stopActuators( void ) +{ /*setValveState ( VRF, VALVE_STATE_R1_C_TO_NC ); setValveState ( VRI, VALVE_STATE_R2_C_TO_NC ); setValveState ( VRD, VALVE_STATE_R2_C_TO_NO ); @@ -363,4 +508,21 @@ stopTrimmerHeater(); } +static BOOL isTemperatureInRange( void ) +{ + BOOL result = FALSE; + F32 TPi = getTemperatureValue ( TEMPSENSORS_OUTLET_PRIMARY_HEATER_TEMP_SENSOR ); + F32 TDi = getTemperatureValue ( TEMPSENSORS_INLET_DIALYSATE_TEMP_SENSOR ); + + if ( fabs( TPi - TDi ) <= MAX_TEMPERATURE_DEVIATION_FROM_TARGET ) + { + // Reset the heat disinfect elapsed time + // It has to start over + heatDisinfectElapsedTime = 0; + result = TRUE; + } + + return result; +} + /**@}*/