/************************************************************************** * * Copyright (c) 2019-2020 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) Sean Nash * @date (last) 26-May-2020 * * @author (original) Sean * @date (original) 20-Apr-2020 * ***************************************************************************/ #include "Timers.h" #include "ModeHeatDisinfect.h" #include "OperationModes.h" #include "Valves.h" #include "Heaters.h" #include "DrainPump.h" #include "LoadCell.h" #include "ROPump.h" #include "TemperatureSensors.h" #include "UVReactors.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" // TODO control composition pumps // TODO add header to functions // TODO add documentation /** * @addtogroup DGHeatDisinfectMode * @{ */ // ********** private definitions ********** // TODO: Change the target temperature to 85 #define HEAT_DISINFECT_TARGET_TEMPERATURE 30U ///< Heat disinfection target temperature #define MAX_TPO_AND_TDI_SENSORS_DIFFERENCE 1U #define MAX_TEMPERATURE_DEVIATION_FROM_TARGET 4U #define HEAT_DISINFECT_RECIRC_PATH_TIME_MINS 1U #define HEAT_DISINFECT_R1_TO_R2_TIME_MINS 1U #define HEAT_DISINFECT_R2_TO_R1_TIME_MINS 1U #define MINUTES_TO_MS_CONVERSION 60000U #define HEAT_DISINFECT_EVAC_RECIRC_PATH_TIME_MS 4000U //TODo do we need this? Change this to the amount of time the composite pumps will run #define HEAT_DISINFECT_RECIRC_PATH_TIME_MS ( HEAT_DISINFECT_RECIRC_PATH_TIME_MINS * MINUTES_TO_MS_CONVERSION ) #define HEAT_DISINFECT_R1_TO_R2_TIME_MS ( HEAT_DISINFECT_R1_TO_R2_TIME_MINS * MINUTES_TO_MS_CONVERSION ) #define HEAT_DISINFECT_R2_TO_R1_TIME_MS ( HEAT_DISINFECT_R2_TO_R1_TIME_MINS * MINUTES_TO_MS_CONVERSION ) #define HEAT_DISINFECT_TARGET_CYCLES 5U #define HEAT_DISINFECT_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) #define DRAIN_PUMP_TARGET_DELTA_PRESSURE 0U #define DRAIN_PUMP_EVACUATE_FLUID_TARGET_RPM 2800U #define DRAIN_PUMP_DISINFECT_DRAIN_PATH_TARGET_RPM 1500U #define RO_PUMP_TARGET_FLOW_RATE_LPM 0.9 #define FULL_RESERVOIRS_WEIGHT_GRAMS 500U //TODO Change this value #define EMPTY_RESERVOIRS_WEIGHT_GRAMS 200U //TODO Change this value // ********** private data ********** /// Heat disinfect evacuate/fill states typedef enum heat_disinfect_internal_states { INTERNAL_HEAT_DISINFECT_STATE_OFF = 0, INTERNAL_HEAT_DISINFECT_STATE_FILL_WITH_WATER, INTERNAL_HEAT_DISINFECT_STATE_EVACUATE_RECIRC_PATH, INTERNAL_HEAT_DISINFECT_STATE_EVACUATE_RESERVOIR_1, INTERNAL_HEAT_DISINFECT_STATE_EVACUATE_RESERVOIR_2, INTERNAL_HEAT_DISINFECT_STATE_COMPLETE, NUM_OF_INTERNAL_STATES } INTERNAL_HEAT_DISINFECT_STATE_T; static INTERNAL_HEAT_DISINFECT_STATE_T heatDisinfectInternalState = INTERNAL_HEAT_DISINFECT_STATE_OFF; static DG_HEAT_DISINFECT_STATE_T heatDisinfectState = DG_HEAT_DISINFECT_STATE_START; ///< Currently active heat disinfect state. static U32 heatDisinfectElapsedTime = 0; static U32 stateTimer = 0; static U32 drainPumpTargetRPM = 0; static U32 heatDisinfectCurrentCycle = 0; static U32 heatDisinfectPublishCounter = 0; static OVERRIDE_F32_T heatDisinfectRecircDuration = { HEAT_DISINFECT_RECIRC_PATH_TIME_MS, HEAT_DISINFECT_RECIRC_PATH_TIME_MS, 0, 0 }; static OVERRIDE_F32_T heatDisinfectR1ToR2Duration = { HEAT_DISINFECT_R1_TO_R2_TIME_MS, HEAT_DISINFECT_R1_TO_R2_TIME_MS, 0, 0 }; static OVERRIDE_F32_T heatDisinfectR2ToR1Duration = { HEAT_DISINFECT_R2_TO_R1_TIME_MS, HEAT_DISINFECT_R2_TO_R1_TIME_MS, 0, 0 }; static OVERRIDE_U32_T heatDisinfectNoOfCyclesToRun = { HEAT_DISINFECT_TARGET_CYCLES, HEAT_DISINFECT_TARGET_CYCLES, 0, 0 }; static OVERRIDE_U32_T heatDisinfectDataPublishInterval = { HEAT_DISINFECT_DATA_PUB_INTERVAL, HEAT_DISINFECT_DATA_PUB_INTERVAL, 0, 0 }; // ********** private function prototypes ********** static INTERNAL_HEAT_DISINFECT_STATE_T handleHeatDisinfectOffState( void ); static INTERNAL_HEAT_DISINFECT_STATE_T handleHeatDisinfectFillWithWaterState( void ); static INTERNAL_HEAT_DISINFECT_STATE_T handleHeatDisinfectEvacRecircPathState( void ); static INTERNAL_HEAT_DISINFECT_STATE_T handleHeatDisifnectEvacReservoir1State( void ); static INTERNAL_HEAT_DISINFECT_STATE_T handleHeatDisinfectEvacReservoir2State( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectStart( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectEvacuateDialysateFillWithWater( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectHeatWater( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectRecirculationPath( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectReservoir1To2( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectReservoir2To1( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectDrainPath( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectFillWithWaterDeprimeReservoirs( void ); static void stopActuators( void ); static void setActuatorsToFillWater( void ); static BOOL isTemperatureInRange( void ); static void execHeatDisinfectInternalStates( void ); static void publishHeatDisinfectData ( void ); static U32 getPublishHeatDisinfectDataInterval( void ); static DATA_GET_PROTOTYPE( U32, getPublishHeatDisinfectDataInterval ); static DATA_GET_PROTOTYPE( F32, getRecirculationDuration ); static DATA_GET_PROTOTYPE( F32, getRSVR1ToRSVR2Duration ); static DATA_GET_PROTOTYPE( F32, getRSVR2ToRSVR1Duration ); static DATA_GET_PROTOTYPE( U32, getNoOfCyclesToRun ); /*********************************************************************//** * @brief * The initHeatDisinfectMode function initializes the heat disinfect Mode module. * @details * Inputs : none * Outputs : none * @return none *************************************************************************/ void initHeatDisinfectMode( void ) { heatDisinfectElapsedTime = 0; drainPumpTargetRPM = 0; heatDisinfectCurrentCycle = 0; heatDisinfectState = DG_HEAT_DISINFECT_STATE_START; } /*********************************************************************//** * @brief * The transitionToHeatDisinfectMode function prepares for transition * to heat disinfect mode. * @details * Inputs : none * Outputs : none * @return none *************************************************************************/ void transitionToHeatDisinfectMode( void ) { initHeatDisinfectMode(); stopActuators(); } /*********************************************************************//** * @brief * The execHeatDisinfectMode function executes the heat disinfect Mode * state machine. * @details * Inputs : none * Outputs : none * @return current state. *************************************************************************/ U32 execHeatDisinfectMode( void ) { switch ( heatDisinfectState ) { case DG_HEAT_DISINFECT_STATE_START: heatDisinfectState = handleHeatDisinfectStart(); break; case DG_HEAT_DISINFECT_EVACUATE_DIALYSATE_FILL_WITH_WATER: heatDisinfectState = handleHeatDisinfectEvacuateDialysateFillWithWater(); break; case DG_HEAT_DISINFECT_STATE_HEAT_WATER: heatDisinfectState = handleHeatDisinfectHeatWater(); break; case DG_HEAT_DISINFECT_STATE_DISINFECT_RECIRC_PATH: heatDisinfectState = handleHeatDisinfectRecirculationPath(); break; case DG_HEAT_DISINFECT_STATE_DISINFECT_RESERVOIR_1_TO_2: heatDisinfectState = handleHeatDisinfectReservoir1To2(); break; case DG_HEAT_DISINFECT_STATE_DISINFECT_RESERVOIR_2_TO_1: heatDisinfectState = handleHeatDisinfectReservoir2To1(); break; case DG_HEAT_DISINFECT_STATE_DISINFECT_DRAIN_PATH: heatDisinfectState = handleHeatDisinfectDrainPath(); break; case DG_HEAT_DISINFECT_STATE_FILL_WITH_WATER_DEPRIME_RESERVOIRS: heatDisinfectState = handleHeatDisinfectFillWithWaterDeprimeReservoirs(); break; case DG_HEAT_DISINFECT_STATE_COMPLETE: // Do nothing break; default: // TODO - s/w fault heatDisinfectState = DG_HEAT_DISINFECT_STATE_COMPLETE; break; } publishHeatDisinfectData(); return (U32)heatDisinfectState; } /*********************************************************************//** * @brief * The getCurrentHeatDisinfectState function returns the current state of the \n * heat disinfect mode. * @details * Inputs : heatState * Outputs : none * @return the current state of heat disinfect mode. *************************************************************************/ DG_HEAT_DISINFECT_STATE_T getCurrentHeatDisinfectState( void ) { return heatDisinfectState; } /*********************************************************************//** * @brief * The startDGHeatDisinfect function starts heat disinfect mode. * @details * Inputs : none * Outputs : none * @return state of run *************************************************************************/ BOOL startDGHeatDisinfect( void ) { // TODO: make sure DG is not in the middle of something and it is in standby initHeatDisinfectMode(); requestNewOperationMode( DG_MODE_HEAT ); return TRUE; // For now. Check whether it is the right request before switching } /*********************************************************************//** * @brief * The stopDGHeatDisinfect function stops heat disinfect mode. * @details * Inputs : heatDisinfectionState * Outputs : heatDisinfectionState * @return none *************************************************************************/ void stopDGHeatDisinfect( void ) { //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_EVACUATE_DIALYSATE_FILL_WITH_WATER; stopActuators(); drainPumpTargetRPM = DRAIN_PUMP_EVACUATE_FLUID_TARGET_RPM; heatDisinfectInternalState = INTERNAL_HEAT_DISINFECT_STATE_OFF; heatDisinfectElapsedTime = getMSTimerCount(); return state; } static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectEvacuateDialysateFillWithWater( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_EVACUATE_DIALYSATE_FILL_WITH_WATER; execHeatDisinfectInternalStates(); //TODO test to see if it is needed to be in an if statement if ( heatDisinfectInternalState == INTERNAL_HEAT_DISINFECT_STATE_COMPLETE ) { // Done with evacuation and fill, set the states to heat up water // 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; } static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectHeatWater( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_HEAT_WATER; 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 ) { // Set the states to disinfect 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_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; // 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, getRecirculationDuration() ) ) { // Set the state for reservoir 1 to 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_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 ); setDrainPumpTargetDeltaPressure( DRAIN_PUMP_TARGET_DELTA_PRESSURE ); setROPumpTargetFlowRate( RO_PUMP_TARGET_FLOW_RATE_LPM ); stateTimer = getMSTimerCount(); state = DG_HEAT_DISINFECT_STATE_DISINFECT_RESERVOIR_1_TO_2; } return state; } static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectReservoir1To2( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_DISINFECT_RESERVOIR_1_TO_2; // 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, getRSVR1ToRSVR2Duration() ) ) { // Set the state for reservoir 1 to 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_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 ); setDrainPumpTargetDeltaPressure( DRAIN_PUMP_TARGET_DELTA_PRESSURE ); setROPumpTargetFlowRate( RO_PUMP_TARGET_FLOW_RATE_LPM ); stateTimer = getMSTimerCount(); state = DG_HEAT_DISINFECT_STATE_DISINFECT_RESERVOIR_2_TO_1; } return state; } static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectReservoir2To1( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_DISINFECT_RESERVOIR_2_TO_1; // 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, getRSVR2ToRSVR1Duration() ) ) { // Set the state for reservoir 1 to 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_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 ); setDrainPumpTargetDeltaPressure( DRAIN_PUMP_TARGET_DELTA_PRESSURE ); setROPumpTargetFlowRate( RO_PUMP_TARGET_FLOW_RATE_LPM ); if ( ++heatDisinfectCurrentCycle > getNoOfCyclesToRun() ) { drainPumpTargetRPM = DRAIN_PUMP_DISINFECT_DRAIN_PATH_TARGET_RPM; heatDisinfectInternalState = INTERNAL_HEAT_DISINFECT_STATE_OFF; state = DG_HEAT_DISINFECT_STATE_DISINFECT_DRAIN_PATH; } else { 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 ); setROPumpTargetFlowRate( RO_PUMP_TARGET_FLOW_RATE_LPM ); stateTimer = getMSTimerCount(); state = DG_HEAT_DISINFECT_STATE_DISINFECT_RECIRC_PATH; } } return state; } static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectDrainPath( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_DISINFECT_DRAIN_PATH; execHeatDisinfectInternalStates(); //TODO test to see if it is needed to be in an if statement if ( heatDisinfectInternalState == INTERNAL_HEAT_DISINFECT_STATE_COMPLETE ) { drainPumpTargetRPM = DRAIN_PUMP_EVACUATE_FLUID_TARGET_RPM; heatDisinfectInternalState = INTERNAL_HEAT_DISINFECT_STATE_OFF; state = DG_HEAT_DISINFECT_STATE_FILL_WITH_WATER_DEPRIME_RESERVOIRS; } return state; } static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectFillWithWaterDeprimeReservoirs( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_FILL_WITH_WATER_DEPRIME_RESERVOIRS; execHeatDisinfectInternalStates(); //TODO test to see if it is needed to be in an if statement // Done with heat disinfect if ( heatDisinfectInternalState == INTERNAL_HEAT_DISINFECT_STATE_COMPLETE ) { state = DG_HEAT_DISINFECT_STATE_COMPLETE; } return state; } static void execHeatDisinfectInternalStates( void ) { switch ( heatDisinfectInternalState ) { case INTERNAL_HEAT_DISINFECT_STATE_OFF: heatDisinfectInternalState = handleHeatDisinfectOffState(); break; case INTERNAL_HEAT_DISINFECT_STATE_FILL_WITH_WATER: heatDisinfectInternalState = handleHeatDisinfectFillWithWaterState(); break; case INTERNAL_HEAT_DISINFECT_STATE_EVACUATE_RECIRC_PATH: heatDisinfectInternalState = handleHeatDisinfectEvacRecircPathState(); break; case INTERNAL_HEAT_DISINFECT_STATE_EVACUATE_RESERVOIR_1: heatDisinfectInternalState = handleHeatDisifnectEvacReservoir1State(); break; case INTERNAL_HEAT_DISINFECT_STATE_EVACUATE_RESERVOIR_2: heatDisinfectInternalState = handleHeatDisinfectEvacReservoir2State(); break; case INTERNAL_HEAT_DISINFECT_STATE_COMPLETE: // Do nothing break; default: heatDisinfectInternalState = INTERNAL_HEAT_DISINFECT_STATE_COMPLETE; break; } } static INTERNAL_HEAT_DISINFECT_STATE_T handleHeatDisinfectOffState( void ) { INTERNAL_HEAT_DISINFECT_STATE_T state = INTERNAL_HEAT_DISINFECT_STATE_OFF; // If the state is evacuate dialysate, start with evacuating recirculate path if ( heatDisinfectState == DG_HEAT_DISINFECT_EVACUATE_DIALYSATE_FILL_WITH_WATER ) { // 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_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 ); setROPumpTargetFlowRate( RO_PUMP_TARGET_FLOW_RATE_LPM ); stateTimer = getMSTimerCount(); // For evac recirc path. TODO later, it should be controlled using // the composite pump state = INTERNAL_HEAT_DISINFECT_STATE_EVACUATE_RECIRC_PATH; } else if ( heatDisinfectState == DG_HEAT_DISINFECT_STATE_FILL_WITH_WATER_DEPRIME_RESERVOIRS ) { setActuatorsToFillWater(); // Start the UV reactors to disinfect the water that // is being filled up startInletUVReactor(); startOutletUVReactor(); state = INTERNAL_HEAT_DISINFECT_STATE_FILL_WITH_WATER; } else if ( heatDisinfectState == DG_HEAT_DISINFECT_STATE_DISINFECT_DRAIN_PATH ) { // Set the actuators for draining the path signalROPumpHardStop(); 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_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_NC ); 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( drainPumpTargetRPM ); state = INTERNAL_HEAT_DISINFECT_STATE_EVACUATE_RESERVOIR_1; } return state; } static INTERNAL_HEAT_DISINFECT_STATE_T handleHeatDisinfectFillWithWaterState( void ) { INTERNAL_HEAT_DISINFECT_STATE_T state = INTERNAL_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 ) { if ( heatDisinfectState == DG_HEAT_DISINFECT_EVACUATE_DIALYSATE_FILL_WITH_WATER ) { stopActuators(); state = INTERNAL_HEAT_DISINFECT_STATE_COMPLETE; } else if ( heatDisinfectState == DG_HEAT_DISINFECT_STATE_FILL_WITH_WATER_DEPRIME_RESERVOIRS ) { 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 ); setROPumpTargetFlowRate( RO_PUMP_TARGET_FLOW_RATE_LPM ); stateTimer = getMSTimerCount(); state = INTERNAL_HEAT_DISINFECT_STATE_EVACUATE_RECIRC_PATH; } } return state; } static INTERNAL_HEAT_DISINFECT_STATE_T handleHeatDisinfectEvacRecircPathState( void ) { INTERNAL_HEAT_DISINFECT_STATE_T state = INTERNAL_HEAT_DISINFECT_STATE_EVACUATE_RECIRC_PATH; // TODO change this to composition pump mode 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 ( drainPumpTargetRPM ); state = INTERNAL_HEAT_DISINFECT_STATE_EVACUATE_RESERVOIR_1; } return state; } static INTERNAL_HEAT_DISINFECT_STATE_T handleHeatDisifnectEvacReservoir1State( void ) { INTERNAL_HEAT_DISINFECT_STATE_T state = INTERNAL_HEAT_DISINFECT_STATE_EVACUATE_RESERVOIR_1; F32 reservoir1Weight = getLoadCellFilteredWeight ( LOAD_CELL_A1 ); 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 ( drainPumpTargetRPM ); probably it is not needed TODO test this state = INTERNAL_HEAT_DISINFECT_STATE_EVACUATE_RESERVOIR_2; } return state; } static INTERNAL_HEAT_DISINFECT_STATE_T handleHeatDisinfectEvacReservoir2State( void ) { INTERNAL_HEAT_DISINFECT_STATE_T state = INTERNAL_HEAT_DISINFECT_STATE_EVACUATE_RESERVOIR_2; F32 reservoir2Weight = getLoadCellFilteredWeight ( LOAD_CELL_B1 ); if ( reservoir2Weight <= EMPTY_RESERVOIRS_WEIGHT_GRAMS ) { if ( heatDisinfectState == DG_HEAT_DISINFECT_EVACUATE_DIALYSATE_FILL_WITH_WATER ) { setActuatorsToFillWater(); state = INTERNAL_HEAT_DISINFECT_STATE_FILL_WITH_WATER; } else if ( heatDisinfectState == DG_HEAT_DISINFECT_STATE_FILL_WITH_WATER_DEPRIME_RESERVOIRS || heatDisinfectState == DG_HEAT_DISINFECT_STATE_DISINFECT_DRAIN_PATH ) { state = INTERNAL_HEAT_DISINFECT_STATE_COMPLETE; } } return state; } static void stopActuators( void ) { // De-energize all the valves 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 ); //TODO composition pumps signalROPumpHardStop(); signalDrainPumpHardStop(); stopInletUVReactor(); stopOutletUVReactor(); stopPrimaryHeater(); 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; } static void setActuatorsToFillWater( void ) { 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 ); } static U32 getPublishHeatDisinfectDataInterval() { U32 result = heatDisinfectDataPublishInterval.data; if ( OVERRIDE_KEY == heatDisinfectDataPublishInterval.override ) { result = heatDisinfectDataPublishInterval.ovData; } return result; } static void publishHeatDisinfectData ( void ) { if ( ++heatDisinfectPublishCounter >= getPublishHeatDisinfectDataInterval() ) { F32 elapsedtime = calcTimeSince( heatDisinfectElapsedTime ) / MINUTES_TO_MS_CONVERSION; broadcastHeatDisinfectData( (U32)heatDisinfectInternalState, elapsedtime, heatDisinfectCurrentCycle ); heatDisinfectPublishCounter = 0; } } BOOL testSetHeatDisinfectDataPublishIntervalOverride( U32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { U32 intvl = value / TASK_GENERAL_INTERVAL; result = TRUE; heatDisinfectDataPublishInterval.ovData = intvl; heatDisinfectDataPublishInterval.override = OVERRIDE_KEY; } return result; } BOOL testResetHeatDisinfectDataPublishIntervalOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; heatDisinfectDataPublishInterval.override = OVERRIDE_RESET; heatDisinfectDataPublishInterval.ovData = heatDisinfectDataPublishInterval.ovInitData; } return result; } BOOL testSetHeatDisinfectRecircDurationOverride( F32 recircMins ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { heatDisinfectRecircDuration.ovInitData = heatDisinfectRecircDuration.data; heatDisinfectRecircDuration.ovData = recircMins * MINUTES_TO_MS_CONVERSION; heatDisinfectRecircDuration.override = OVERRIDE_KEY; } return result; } BOOL testResetHeatDisinfectRecircDurationOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; heatDisinfectRecircDuration.ovData = heatDisinfectRecircDuration.ovInitData; heatDisinfectRecircDuration.override = OVERRIDE_RESET; } return result; } BOOL testSetHeatDisinfectR1ToR2DurationOverride( F32 R1ToR2Mins ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; heatDisinfectR1ToR2Duration.ovInitData = heatDisinfectR1ToR2Duration.data; heatDisinfectR1ToR2Duration.ovData = R1ToR2Mins * MINUTES_TO_MS_CONVERSION; heatDisinfectR1ToR2Duration.override = OVERRIDE_KEY; } return result; } BOOL testResetHeatDisinfectR1ToR2DurationOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; heatDisinfectR1ToR2Duration.ovData = heatDisinfectR1ToR2Duration.ovInitData; heatDisinfectR1ToR2Duration.override = OVERRIDE_RESET; } return result; } BOOL testSetHeatDisinfectionR2ToR1DurationOverride( F32 R2ToR1Mins ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; heatDisinfectR2ToR1Duration.ovInitData = heatDisinfectR2ToR1Duration.data; heatDisinfectR2ToR1Duration.ovData = R2ToR1Mins * MINUTES_TO_MS_CONVERSION; heatDisinfectR2ToR1Duration.override = OVERRIDE_KEY; } return result; } BOOL testResetHeatDisinfectionR2ToR1DurationOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; heatDisinfectR2ToR1Duration.ovData = heatDisinfectR2ToR1Duration.ovInitData; heatDisinfectR2ToR1Duration.override = OVERRIDE_RESET; } return result; } BOOL testSetHeatDisinfectNoOfCyclesOverride( U32 cycles ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; heatDisinfectNoOfCyclesToRun.ovInitData = heatDisinfectNoOfCyclesToRun.data; heatDisinfectNoOfCyclesToRun.ovData = cycles; heatDisinfectNoOfCyclesToRun.override = OVERRIDE_KEY; } return result; } BOOL testResetHeatDisinfectNoOfCyclesOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; heatDisinfectNoOfCyclesToRun.ovData = heatDisinfectNoOfCyclesToRun.ovInitData; heatDisinfectNoOfCyclesToRun.override = OVERRIDE_RESET; } return result; } static F32 getRecirculationDuration() { F32 result = heatDisinfectRecircDuration.data; if ( OVERRIDE_KEY == heatDisinfectRecircDuration.override ) { result = heatDisinfectRecircDuration.ovData; } return result; } static F32 getRSVR1ToRSVR2Duration() { F32 result = heatDisinfectR1ToR2Duration.data; if ( OVERRIDE_KEY == heatDisinfectR1ToR2Duration.override ) { result = heatDisinfectR1ToR2Duration.ovData; } return result; } static F32 getRSVR2ToRSVR1Duration() { F32 result = heatDisinfectR2ToR1Duration.data; if ( OVERRIDE_KEY == heatDisinfectR2ToR1Duration.override ) { result = heatDisinfectR2ToR1Duration.ovData; } return result; } static U32 getNoOfCyclesToRun() { U32 result = heatDisinfectNoOfCyclesToRun.data; if ( OVERRIDE_KEY == heatDisinfectNoOfCyclesToRun.override ) { result = heatDisinfectNoOfCyclesToRun.ovData; } return result; } /**@}*/