Index: firmware/App/Modes/ModeHeatDisinfect.c =================================================================== diff -u -r96b5f969bbba7b44593c85c8ac003be0a2d87151 -r1475b55c0a91327f63a99ee5e40a7b55e0c43a06 --- firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 96b5f969bbba7b44593c85c8ac003be0a2d87151) +++ firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 1475b55c0a91327f63a99ee5e40a7b55e0c43a06) @@ -67,7 +67,7 @@ #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 +// The acid 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.0F ///< Bicarb concentrate pump speed in mL/min. // Flush and drain R1 and R2 Index: firmware/App/Modes/ModeHeatDisinfectActiveCool.c =================================================================== diff -u -rc6c9416de5dd88ebf26f8181f728989f77326976 -r1475b55c0a91327f63a99ee5e40a7b55e0c43a06 --- firmware/App/Modes/ModeHeatDisinfectActiveCool.c (.../ModeHeatDisinfectActiveCool.c) (revision c6c9416de5dd88ebf26f8181f728989f77326976) +++ firmware/App/Modes/ModeHeatDisinfectActiveCool.c (.../ModeHeatDisinfectActiveCool.c) (revision 1475b55c0a91327f63a99ee5e40a7b55e0c43a06) @@ -17,15 +17,20 @@ #include "ConcentratePumps.h" #include "CPLD.h" +#include "DrainPump.h" +#include "Heaters.h" +#include "LoadCell.h" #include "MessageSupport.h" #include "ModeFault.h" #include "ModeHeatDisinfectActiveCool.h" #include "OperationModes.h" +#include "Reservoirs.h" #include "ROPump.h" #include "Switches.h" #include "TaskGeneral.h" #include "TemperatureSensors.h" #include "Timers.h" +#include "UVReactors.h" #include "Valves.h" /** @@ -36,50 +41,95 @@ // ********** private data ********** #define HEAT_DISINFECT_ACTIVE_COOL_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Mode heat disinfect active cool data publish interval in counts. -#define ROF_COOL_DOWN_TARGET_FLOW_LPM 0.3F ///< RO filter cool down target flow in L/min. -#define HEAT_DISINFECT_ACTIVE_COOL_MAX_RO_PRESSURE_PSI 40 ///< Heat disinfect active cool maximum RO pressure in psi. -#define TARGET_THD_SENSOR_FOR_RINSING_C 44.0F ///< Target THd temperature sensor value before rinsing in C. -#define ROF_COOL_DOWN_CIRCULATION_TIME_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< RO filter cool down circulation timer in milliseconds. -#define ROF_COOL_DOWN_MAX_TIME_MS ( 300 * SEC_PER_MIN * MS_PER_SECOND ) ///< RO filter cool down maximum state time in milliseconds. +#define ACID_PUMP_SPEED_ML_PER_MIN 30.6F ///< Acid concentrate pump speed in mL/min. +// The acid 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.0F ///< Bicarb concentrate pump speed in mL/min. +#define RSRVR_FILL_TIMEOUT_MS ( 5 * SEC_PER_MIN * MS_PER_SECOND ) +#define TARGET_THD_SENSOR_FOR_RINSING_C 44.0F // TODO remove ///< Target THd temperature sensor value before rinsing in C. +#define ROF_COOL_DOWN_CIRCULATION_TIME_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) // TODO remove ///< RO filter cool down circulation timer in milliseconds. +#define ROF_COOL_DOWN_MAX_TIME_MS ( 300 * SEC_PER_MIN * MS_PER_SECOND ) // todo remove ///< RO filter cool down maximum state time in milliseconds. + +// Active cool down defines +#define ROF_ACTIVE_COOL_DOWN_TARGET_FLOW_LPM 0.3F ///< RO active cool down target flow in L/min. +#define ROF_ACTIVE_COOL_DOWN_MAX_PRESSURE_PSI 30 ///< RO active cool down maximum pressure in psi. + +#define ROF_ACTIVE_COOL_TARGET_RSRVR_FILL_ML 750.0F +#define ROF_ACTIVE_COOL_TARGET_TEMP_C 45.0F +#define ROF_ACTIVE_COOL_BELOW_TEMP_TIMEOUT_MS ( 30 * MS_PER_SECOND ) +#define ROF_ACTIVE_COOL_TARGET_DARIN_RPM 600 +#define ROF_ACTIVE_COOL_MIX_DRAIN_VALVE_ON_TIMEOUT_MS ( 5 * MS_PER_SECOND ) +#define ROF_ACTIVE_COOL_RSRVR_MIX_DRAIN_TIMEOUT_MS ( 2.5 * SEC_PER_MIN * MS_PER_SECOND ) +#define ROF_ACTIVE_COOL_MIX_DRAIN_STEADY_TIMEOUT_MS ( 15 * MS_PER_SECOND ) + static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T heatDisinfectActiveCoolState; ///< Mode heat disinfect active cool state. static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T heatDisinfectActiceCoolPrevState; ///< Mode heat disinfect active cool previous state. -static U32 stateTimer; ///< Mode heat disinfect active cool state timer. +static U32 stateStartTimeMS; ///< Mode heat disinfect active cool state timer in milliseconds. static U32 dataPublishCounter; ///< Mode heat disinfect active cool data publish counter. static U32 overallHeatDisinfectActiveCoolTimer; ///< Mode heat disinfect active cool over mode timer. -static U32 ROFCoolingTimer; ///< Mode heat disinfect active cool RO filter cooling timer. +static U32 ROFCoolingTimer; // TODO remove ///< Mode heat disinfect active cool RO filter cooling timer. static ALARM_ID_T alarmDetectedPendingTrigger; ///< Mode heat disinfect active cool pending alarm trigger. +static DIS_RSRVR_STATUS_T rsrvrsStatus; ///< Mode heat disinfect active cool reservoirs status. +static U32 tempBelowTargetStartTimeMS; ///< Mode heat disinfect active cool temperature below target time in milliseconds. // ********** private function prototypes ********** static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T handleHeatDisinfectActiveCoolStartState( void ); +static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T handleHeatDisinfectActiveCoolFillR1State( void ); +static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T handleHeatDisinfectActiveCoolMixDrainR1State( void ); +static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T handleHeatDisinfectActiveCoolFillR2State( void ); +static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T handleHeatDisinfectActiveCoolMixDrainR2State( void ); +static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T handleHeatDisinfectActiveCoolDrainR2FillR1ToR2State( void ); +static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T handleHeatDisinfectActiveCoolDrainR1FillR2ToR1State( void ); +static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T handleHeatDisinfectActiveCoolDrainR1State( void ); +static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T handleHeatDisinfectActiveCoolDrainR2State( void ); static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T handleHeatDisinfectActiveCoolCoolDownROFilterState( void ); static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T handleHeatDisinfectActiveCoolCompleteState( void ); +static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T handleHeatDisinfectActiveCoolCancelWaterPathState( void ); static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T handleHeatDisinfectActiveCoolCancelBasicPathState( void ); static void failHeatDisinfectActiveCool( void ); static void publishHeatDisinfectActiveCoolData( void ); static void monitorModeHeatDisinfectActiveCool( void ); +static void setHeatDisinfectActiveCoolActuators( DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T state ); +static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T checkRsrvrMgmtTimeout( DG_RESERVOIR_ID_T rsrvrID, DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T state ); +static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T checkRsrvrPartialFill( DG_RESERVOIR_ID_T rsrvrID, DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T state ); /*********************************************************************//** * @brief * The initHeatDisinfectActiveCoolMode function initializes the heat disinfect * active cool mode module. * @details Inputs: none - * @details Outputs: heatDisinfectActiveCoolState, stateTimer, dataPublishCounter, - * overallHeatDisinfectActiveCoolTimer, ROFCoolingTimer, alarmDetectedPendingTrigger - * heatDisinfectActiceCoolPrevState, + * @details Outputs: heatDisinfectActiveCoolState, stateStartTimeMS, + * dataPublishCounter, overallHeatDisinfectActiveCoolTimer, + * alarmDetectedPendingTrigger, heatDisinfectActiceCoolPrevState, rsrvrsStatus, + * tempBelowTargetStartTimeMS * @return none *************************************************************************/ void initHeatDisinfectActiveCoolMode( void ) { heatDisinfectActiveCoolState = DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_START; heatDisinfectActiceCoolPrevState = DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_START; - stateTimer = 0; + stateStartTimeMS = 0; dataPublishCounter = 0; overallHeatDisinfectActiveCoolTimer = 0; ROFCoolingTimer = 0; alarmDetectedPendingTrigger = ALARM_ID_NO_ALARM; + tempBelowTargetStartTimeMS = 0; + + // Initialize the reservoirs + rsrvrsStatus.rsrvrFillStableTime = 0; + rsrvrsStatus.rsrvrFillStableTimeoutMS = RSRVRS_FULL_STABLE_TIME_COUNT; + rsrvrsStatus.rsrvr[ DG_RESERVOIR_1 ].drainInit = FALSE; + rsrvrsStatus.rsrvr[ DG_RESERVOIR_1 ].loadCell = LOAD_CELL_RESERVOIR_1_PRIMARY; + rsrvrsStatus.rsrvr[ DG_RESERVOIR_1 ].rStatus = NUM_OF_DG_RESERVOIR_STATUS; + rsrvrsStatus.rsrvr[ DG_RESERVOIR_2 ].drainInit = FALSE; + rsrvrsStatus.rsrvr[ DG_RESERVOIR_2 ].loadCell = LOAD_CELL_RESERVOIR_2_PRIMARY; + rsrvrsStatus.rsrvr[ DG_RESERVOIR_2 ].rStatus = NUM_OF_DG_RESERVOIR_STATUS; + + // In the active cool mode the heaters are not turned on + stopHeater( DG_PRIMARY_HEATER ); + stopHeater( DG_TRIMMER_HEATER ); } /*********************************************************************//** @@ -120,11 +170,47 @@ heatDisinfectActiveCoolState = handleHeatDisinfectActiveCoolStartState(); break; + case DG_HEAT_DISINFECT_ACTIVE_COOL_FILL_R1_STATE: + heatDisinfectActiveCoolState = handleHeatDisinfectActiveCoolFillR1State(); + break; + + case DG_HEAT_DISINFECT_ACITVE_COOL_MIX_DRAIN_R1_STATE: + heatDisinfectActiveCoolState = handleHeatDisinfectActiveCoolMixDrainR1State(); + break; + + case DG_HEAT_DISINFECT_ACTIVE_COOL_FILL_R2_STATE: + heatDisinfectActiveCoolState = handleHeatDisinfectActiveCoolFillR2State(); + break; + + case DG_HEAT_DISINFECT_ACTIVE_COOL_MIX_DRAIN_R2_STATE: + heatDisinfectActiveCoolState = handleHeatDisinfectActiveCoolMixDrainR2State(); + break; + + case DG_HEAT_DISINFECT_ACTIVE_COOL_DRAIN_R2_FILL_R1_TO_R2_STATE: + heatDisinfectActiveCoolState = handleHeatDisinfectActiveCoolDrainR2FillR1ToR2State(); + break; + + case DG_HEAT_DISINFECT_ACTIVE_COOL_DRAIN_R1_FILL_R2_TO_R1_STATE: + heatDisinfectActiveCoolState = handleHeatDisinfectActiveCoolDrainR1FillR2ToR1State(); + break; + + case DG_HEAT_DISINFECT_ACTIVE_COOL_DRAIN_R1_STATE: + heatDisinfectActiveCoolState = handleHeatDisinfectActiveCoolDrainR1State(); + break; + + case DG_HEAT_DISINFECT_ACTIVE_COOL_DRAIN_R2_STATE: + heatDisinfectActiveCoolState = handleHeatDisinfectActiveCoolDrainR2State(); + break; + case DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_COOL_DOWN_RO_FILTER: heatDisinfectActiveCoolState = handleHeatDisinfectActiveCoolCoolDownROFilterState(); break; - case DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_CANCEL_BASIC_PATH: + case DG_HEAT_DISINFECT_ACTIVE_COOL_CANCEL_WATER_PATH_STATE: + heatDisinfectActiveCoolState = handleHeatDisinfectActiveCoolCancelWaterPathState(); + break; + + case DG_HEAT_DISINFECT_ACTIVE_COOL_CANCEL_BASIC_PATH_STATE: heatDisinfectActiveCoolState = handleHeatDisinfectActiveCoolCancelBasicPathState(); break; @@ -184,19 +270,87 @@ return status; } +DG_RESERVOIR_STATUS_T getDisinfectRsrvrFillStatus( DG_RESERVOIR_ID_T rsrvrID, DIS_RSRVR_STATUS_T *rsrvrStatus, F32 targetVolML, U32 fillTimeoutMS, U32 stateTimerMS ) +{ + DG_RESERVOIR_STATUS_T status = DG_RESERVOIR_BELOW_TARGET; + F32 volumeML = 0.0F; + + if ( rsrvrID < NUM_OF_DG_RESERVOIRS ) + { + volumeML = getLoadCellSmallFilteredWeight( rsrvrStatus->rsrvr[ rsrvrID ].loadCell ); + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_DG_RESERVOIR_SELECTED, rsrvrID ) + } + + if ( volumeML >= targetVolML ) + { + if ( ++rsrvrStatus->rsrvrFillStableTime >= rsrvrStatus->rsrvrFillStableTimeoutMS ) + { + rsrvrStatus->rsrvrFillStableTime = 0; + status = DG_RESERVOIR_REACHED_TARGET; + } + } + else if ( TRUE == didTimeout( stateTimerMS, fillTimeoutMS ) ) + { + status = DG_RESERVOIR_NOT_REACHED_TARGET; + } + + return status; +} + +DG_RESERVOIR_STATUS_T getDisinfectRsrvrDrainStatus( DG_RESERVOIR_ID_T rsrvrID, DIS_RSRVR_STATUS_T *rsrvrStatus, U32 drainSteadyTimeoutMS, U32 drainStateTimeoutMS, U32 stateTimerMS ) +{ + DG_RESERVOIR_STATUS_T status = DG_RESERVOIR_ABOVE_TARGET; + BOOL isDrainComplete = FALSE; + + if ( FALSE == rsrvrStatus->rsrvr[ rsrvrID ].drainInit ) + { + initDrainParameters( rsrvrID ); + rsrvrStatus->rsrvr[ rsrvrID ].drainInit = TRUE; + } + + // NOTE: the drain status should be checked once the reservoirs parameters are initialized. This is to make sure the + // the timers for stable drain time are initialized prior to using them again + isDrainComplete = hasTargetDrainVolumeBeenReached( rsrvrID, drainSteadyTimeoutMS ); + + if ( TRUE == isDrainComplete ) + { + rsrvrStatus->rsrvr[ rsrvrID ].drainInit = FALSE; + status = DG_RESERVOIR_REACHED_TARGET; + } + else if ( TRUE == didTimeout( stateTimerMS, drainStateTimeoutMS ) ) + { + rsrvrStatus->rsrvr[ rsrvrID ].drainInit = FALSE; + status = DG_RESERVOIR_NOT_REACHED_TARGET; + } + + return status; +} + // ********** private functions ********** /*********************************************************************//** * @brief * The handleHeatDisinfectActiveCoolStartState function handles the heat * disinfect active cool start state. - * @details Inputs: anone - * @details Outputs: ROFCoolingTimer, stateTimer + * @details Inputs: none + * @details Outputs: overallHeatDisinfectActiveCoolTimer, stateTimer * @return next state of the heat disinfect active cool state machine *************************************************************************/ static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T handleHeatDisinfectActiveCoolStartState( void ) { - DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T state = DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_COOL_DOWN_RO_FILTER; + DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T state = DG_HEAT_DISINFECT_ACTIVE_COOL_FILL_R1_STATE; + setHeatDisinfectActiveCoolActuators( DG_HEAT_DISINFECT_ACTIVE_COOL_FILL_R1_STATE ); + + overallHeatDisinfectActiveCoolTimer = getMSTimerCount(); + stateStartTimeMS = getMSTimerCount(); + rsrvrsStatus.rsrvr[ DG_RESERVOIR_1 ].rStatus = DG_RESERVOIR_BELOW_TARGET; + tempBelowTargetStartTimeMS = getMSTimerCount(); + + /* TODO remove when cooling was at least tested once. + * DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T state = DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_COOL_DOWN_RO_FILTER; overallHeatDisinfectActiveCoolTimer = getMSTimerCount(); ROFCoolingTimer = 0; stateTimer = getMSTimerCount(); @@ -210,11 +364,120 @@ setValveState( VDR, VALVE_STATE_RECIRC_C_TO_NC ); setValveState( VRC, VALVE_STATE_RECIRC_C_TO_NC ); setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); - setROPumpTargetFlowRateLPM( ROF_COOL_DOWN_TARGET_FLOW_LPM, HEAT_DISINFECT_ACTIVE_COOL_MAX_RO_PRESSURE_PSI ); + setROPumpTargetFlowRateLPM( ROF_ACTIVE_COOL_DOWN_TARGET_FLOW_LPM, ROF_ACTIVE_COOL_DOWN_MAX_PRESSURE_PSI );*/ return state; } +// TODO add doxygen +static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T handleHeatDisinfectActiveCoolFillR1State( void ) +{ + DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T state = DG_HEAT_DISINFECT_ACTIVE_COOL_FILL_R1_STATE; + F32 THdTemperatureC = getTemperatureValue( TEMPSENSORS_HEAT_DISINFECT ); + + if ( THdTemperatureC > ROF_ACTIVE_COOL_TARGET_TEMP_C ) + { + tempBelowTargetStartTimeMS = getMSTimerCount(); + } + + if ( DG_RESERVOIR_BELOW_TARGET == rsrvrsStatus.rsrvr[ DG_RESERVOIR_1 ].rStatus ) + { + rsrvrsStatus.rsrvr[ DG_RESERVOIR_1 ].rStatus = getDisinfectRsrvrFillStatus( DG_RESERVOIR_1, &rsrvrsStatus, ROF_ACTIVE_COOL_TARGET_RSRVR_FILL_ML, + RSRVR_FILL_TIMEOUT_MS, stateStartTimeMS ); + } + else if ( DG_RESERVOIR_REACHED_TARGET == rsrvrsStatus.rsrvr[ DG_RESERVOIR_1 ].rStatus ) + { + if ( TRUE == didTimeout( tempBelowTargetStartTimeMS, ROF_ACTIVE_COOL_BELOW_TEMP_TIMEOUT_MS ) ) + { + setHeatDisinfectActiveCoolActuators( DG_HEAT_DISINFECT_ACTIVE_COOL_DRAIN_R2_FILL_R1_TO_R2_STATE ); + tempBelowTargetStartTimeMS = 0; + stateStartTimeMS = getMSTimerCount(); + state = DG_HEAT_DISINFECT_ACTIVE_COOL_DRAIN_R2_FILL_R1_TO_R2_STATE; + } + else + { + deenergizeActuators( NO_PARK_CONC_PUMPS ); + rsrvrsStatus.rsrvr[ DG_RESERVOIR_1 ].rStatus = DG_RESERVOIR_ABOVE_TARGET; + tempBelowTargetStartTimeMS = 0; + stateStartTimeMS = getMSTimerCount(); + state = DG_HEAT_DISINFECT_ACITVE_COOL_MIX_DRAIN_R1_STATE; + } + } + + state = checkRsrvrMgmtTimeout( DG_RESERVOIR_1, state ); + + return state; +} + +static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T handleHeatDisinfectActiveCoolMixDrainR1State( void ) +{ + DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T state = DG_HEAT_DISINFECT_ACITVE_COOL_MIX_DRAIN_R1_STATE; + + if ( ( TRUE == didTimeout( stateStartTimeMS, ROF_ACTIVE_COOL_MIX_DRAIN_VALVE_ON_TIMEOUT_MS ) ) && ( FALSE == isDrainPumpOn() ) ) + { + setHeatDisinfectActiveCoolActuators( DG_HEAT_DISINFECT_ACITVE_COOL_MIX_DRAIN_R1_STATE ); + } + else if ( ( DG_RESERVOIR_ABOVE_TARGET == rsrvrsStatus.rsrvr[ DG_RESERVOIR_1 ].rStatus ) && ( TRUE == isDrainPumpOn() ) ) + { + rsrvrsStatus.rsrvr[ DG_RESERVOIR_1 ].rStatus = getDisinfectRsrvrDrainStatus( DG_RESERVOIR_1, &rsrvrsStatus, + ROF_ACTIVE_COOL_MIX_DRAIN_STEADY_TIMEOUT_MS, + ROF_ACTIVE_COOL_RSRVR_MIX_DRAIN_TIMEOUT_MS, stateStartTimeMS ); + } + else if ( DG_RESERVOIR_REACHED_TARGET == rsrvrsStatus.rsrvr[ DG_RESERVOIR_1 ].rStatus ) + { + setHeatDisinfectActiveCoolActuators( DG_HEAT_DISINFECT_ACTIVE_COOL_FILL_R2_STATE ); + rsrvrsStatus.rsrvr[ DG_RESERVOIR_2 ].rStatus = DG_RESERVOIR_BELOW_TARGET; + stateStartTimeMS = getMSTimerCount(); + state = DG_HEAT_DISINFECT_ACTIVE_COOL_FILL_R2_STATE; + } + + state = checkRsrvrMgmtTimeout( DG_RESERVOIR_1, state ); + + return state; +} + +static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T handleHeatDisinfectActiveCoolFillR2State( void ) +{ + DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T state = DG_HEAT_DISINFECT_ACTIVE_COOL_FILL_R2_STATE; + + return state; +} + +static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T handleHeatDisinfectActiveCoolMixDrainR2State( void ) +{ + DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T state = DG_HEAT_DISINFECT_ACTIVE_COOL_MIX_DRAIN_R2_STATE; + + return state; +} + +static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T handleHeatDisinfectActiveCoolDrainR2FillR1ToR2State( void ) +{ + DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T state = DG_HEAT_DISINFECT_ACTIVE_COOL_DRAIN_R2_FILL_R1_TO_R2_STATE; + + return state; +} + +static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T handleHeatDisinfectActiveCoolDrainR1FillR2ToR1State( void ) +{ + DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T state = DG_HEAT_DISINFECT_ACTIVE_COOL_DRAIN_R1_FILL_R2_TO_R1_STATE; + + return state; +} + +static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T handleHeatDisinfectActiveCoolDrainR1State( void ) +{ + DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T state = DG_HEAT_DISINFECT_ACTIVE_COOL_DRAIN_R1_STATE; + + return state; +} + +static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T handleHeatDisinfectActiveCoolDrainR2State( void ) +{ + DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T state = DG_HEAT_DISINFECT_ACTIVE_COOL_DRAIN_R2_STATE; + + return state; +} + /*********************************************************************//** * @brief * The handleHeatDisinfectActiveCoolCoolDownROFilterState function handles @@ -258,14 +521,14 @@ setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); signalROPumpHardStop(); - stateTimer = getMSTimerCount(); + stateStartTimeMS = getMSTimerCount(); state = DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_COMPLETE; } - else if ( ( TRUE == didTimeout( stateTimer, ROF_COOL_DOWN_MAX_TIME_MS ) ) ) + else if ( ( TRUE == didTimeout( stateStartTimeMS, ROF_COOL_DOWN_MAX_TIME_MS ) ) ) { heatDisinfectActiceCoolPrevState = state; alarmDetectedPendingTrigger = ALARM_ID_DG_HEAT_DISINFECT_ACTIVE_COOL_TIME_OUT; - state = DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_CANCEL_BASIC_PATH; + state = DG_HEAT_DISINFECT_ACTIVE_COOL_CANCEL_BASIC_PATH_STATE; } return state; @@ -288,6 +551,13 @@ return state; } +static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T handleHeatDisinfectActiveCoolCancelWaterPathState( void ) +{ + DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T state = DG_HEAT_DISINFECT_ACTIVE_COOL_CANCEL_WATER_PATH_STATE; + + return state; +} + /*********************************************************************//** * @brief * The handleHeatDisinfectActiveCoolCancelBasicPathState function handles the @@ -299,7 +569,7 @@ *************************************************************************/ static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T handleHeatDisinfectActiveCoolCancelBasicPathState( void ) { - DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T state = DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_CANCEL_BASIC_PATH; + DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T state = DG_HEAT_DISINFECT_ACTIVE_COOL_CANCEL_BASIC_PATH_STATE; failHeatDisinfectActiveCool(); @@ -341,7 +611,7 @@ data.heatDisinfectActivCoolState = (U32)heatDisinfectActiveCoolState; data.overallElapsedTime = calcTimeSince( overallHeatDisinfectActiveCoolTimer ); - data.stateElapsedTime = calcTimeSince( stateTimer ); + data.stateElapsedTime = calcTimeSince( stateStartTimeMS ); data.cancellationMode = 0; broadcastData( MSG_ID_DG_HEAT_DISINFECT_ACTIVE_COOL_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( MODE_HEAT_DISINFECT_ACTIVE_COOL_DATA_T ) ); @@ -372,11 +642,203 @@ // will not be raising the alarm at end of the cancel water path. The recoverable alarm is raised here in this function U32 cap = (U32)( STATE_OPEN == getSwitchStatus( CONCENTRATE_CAP ) ? CONCENTRATE_CAP : DIALYSATE_CAP ); heatDisinfectActiceCoolPrevState = heatDisinfectActiveCoolState; - heatDisinfectActiveCoolState = DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_CANCEL_BASIC_PATH; + heatDisinfectActiveCoolState = DG_HEAT_DISINFECT_ACTIVE_COOL_CANCEL_BASIC_PATH_STATE; alarmDetectedPendingTrigger = ALARM_ID_DG_DIALYSATE_OR_CONC_CAP_NOT_IN_PROPER_POSITION; } } } +/*********************************************************************//** + * @brief + * The setHeatDisinfectActiveCoolActuators function sets all the actuators + * of the provided state. + * @details Inputs: none + * @details Outputs: none + * @return: none + *************************************************************************/ +static void setHeatDisinfectActiveCoolActuators( DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T state ) +{ + switch ( state ) + { + case DG_HEAT_DISINFECT_ACTIVE_COOL_FILL_R1_STATE: + // Valves + setValveState( VPI, VALVE_STATE_OPEN ); + setValveState( VBF, VALVE_STATE_CLOSED ); + setValveState( VSP, VALVE_STATE_CLOSED ); + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); + setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState( VRC, VALVE_STATE_RECIRC_C_TO_NC ); + setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); + setValveState( VRD1, VALVE_STATE_CLOSED ); + setValveState( VRD2, VALVE_STATE_CLOSED ); + setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); + setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); + // UV reactors + turnOnUVReactor( INLET_UV_REACTOR ); + turnOffUVReactor( OUTLET_UV_REACTOR ); + // Concentrate pumps + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, ACID_PUMP_SPEED_ML_PER_MIN ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, BICARB_PUMP_SPEED_ML_PER_MIN ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); + // RO pump + setROPumpTargetFlowRateLPM( ROF_ACTIVE_COOL_DOWN_TARGET_FLOW_LPM, ROF_ACTIVE_COOL_DOWN_MAX_PRESSURE_PSI ); + // Drain pump + signalDrainPumpHardStop(); + break; + + case DG_HEAT_DISINFECT_ACITVE_COOL_MIX_DRAIN_R1_STATE: + // Valves + setValveState( VPI, VALVE_STATE_OPEN ); + setValveState( VBF, VALVE_STATE_CLOSED ); + setValveState( VSP, VALVE_STATE_CLOSED ); + setValveState( VPD, VALVE_STATE_DRAIN_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_R1_C_TO_NO ); + 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 ); + // UV reactors + turnOnUVReactor( INLET_UV_REACTOR ); + turnOffUVReactor( OUTLET_UV_REACTOR ); + // Concentrate pumps + requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID , NO_PARK_CONC_PUMPS ); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB , NO_PARK_CONC_PUMPS ); + // RO pump + signalROPumpHardStop(); + // Drain pump + setDrainPumpTargetRPM( ROF_ACTIVE_COOL_TARGET_DARIN_RPM ); + break; + + case DG_HEAT_DISINFECT_ACTIVE_COOL_FILL_R2_STATE: + // Valves + setValveState( VPI, VALVE_STATE_OPEN ); + setValveState( VBF, VALVE_STATE_CLOSED ); + setValveState( VSP, VALVE_STATE_CLOSED ); + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); + setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState( VRC, VALVE_STATE_RECIRC_C_TO_NC ); + setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); + setValveState( VRD1, VALVE_STATE_CLOSED ); + setValveState( VRD2, VALVE_STATE_CLOSED ); + setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); + setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); + // UV reactors + turnOnUVReactor( INLET_UV_REACTOR ); + turnOffUVReactor( OUTLET_UV_REACTOR ); + // Concentrate pumps + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, ACID_PUMP_SPEED_ML_PER_MIN ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, BICARB_PUMP_SPEED_ML_PER_MIN ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); + // RO pump + setROPumpTargetFlowRateLPM( ROF_ACTIVE_COOL_DOWN_TARGET_FLOW_LPM, ROF_ACTIVE_COOL_DOWN_MAX_PRESSURE_PSI ); + // Drain pump + signalDrainPumpHardStop(); + break; + + case DG_HEAT_DISINFECT_ACTIVE_COOL_MIX_DRAIN_R2_STATE: + break; + + case DG_HEAT_DISINFECT_ACTIVE_COOL_DRAIN_R2_FILL_R1_TO_R2_STATE: + // Valves + setValveState( VPI, VALVE_STATE_OPEN ); + setValveState( VBF, VALVE_STATE_CLOSED ); + setValveState( VSP, VALVE_STATE_CLOSED ); + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); + setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState( VRC, VALVE_STATE_RECIRC_C_TO_NC ); + setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); + setValveState( VRD1, VALVE_STATE_CLOSED ); + setValveState( VRD2, VALVE_STATE_OPEN ); + setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); + setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); + // UV reactors + turnOnUVReactor( INLET_UV_REACTOR ); + turnOffUVReactor( OUTLET_UV_REACTOR ); + // Concentrate pumps + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, ACID_PUMP_SPEED_ML_PER_MIN ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, BICARB_PUMP_SPEED_ML_PER_MIN ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); + // RO pump + setROPumpTargetFlowRateLPM( ROF_ACTIVE_COOL_DOWN_TARGET_FLOW_LPM, ROF_ACTIVE_COOL_DOWN_MAX_PRESSURE_PSI ); + // Drain pump + signalDrainPumpHardStop(); + break; + + case DG_HEAT_DISINFECT_ACTIVE_COOL_DRAIN_R1_FILL_R2_TO_R1_STATE: + break; + + case DG_HEAT_DISINFECT_ACTIVE_COOL_DRAIN_R1_STATE: + break; + + case DG_HEAT_DISINFECT_ACTIVE_COOL_DRAIN_R2_STATE: + break; + + case DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_START: + case DG_HEAT_DISINFECT_ACTIVE_COOL_CANCEL_WATER_PATH_STATE: + case DG_HEAT_DISINFECT_ACTIVE_COOL_CANCEL_BASIC_PATH_STATE: + case DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_COMPLETE: + // Do nothing the actuators in the above states are handled in a different part of code + break; + } +} + +static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T checkRsrvrMgmtTimeout( DG_RESERVOIR_ID_T rsrvrID, DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T state ) +{ + if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvrsStatus.rsrvr[ rsrvrID ].rStatus ) + { + heatDisinfectActiceCoolPrevState = state; + state = DG_HEAT_DISINFECT_ACTIVE_COOL_CANCEL_WATER_PATH_STATE; + } + + return state; +} + +static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T checkRsrvrPartialFill( DG_RESERVOIR_ID_T rsrvrID, DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T state ) +{ + F32 THdTemperatureC = getTemperatureValue( TEMPSENSORS_HEAT_DISINFECT ); + + if ( THdTemperatureC > ROF_ACTIVE_COOL_TARGET_TEMP_C ) + { + tempBelowTargetStartTimeMS = getMSTimerCount(); + } + + if ( DG_RESERVOIR_BELOW_TARGET == rsrvrsStatus.rsrvr[ rsrvrID ].rStatus ) + { + rsrvrsStatus.rsrvr[ rsrvrID ].rStatus = getDisinfectRsrvrFillStatus( rsrvrID, &rsrvrsStatus, ROF_ACTIVE_COOL_TARGET_RSRVR_FILL_ML, + RSRVR_FILL_TIMEOUT_MS, stateStartTimeMS ); + } + else if ( DG_RESERVOIR_REACHED_TARGET == rsrvrsStatus.rsrvr[ rsrvrID ].rStatus ) + { + if ( TRUE == didTimeout( tempBelowTargetStartTimeMS, ROF_ACTIVE_COOL_BELOW_TEMP_TIMEOUT_MS ) ) + { + stateStartTimeMS = getMSTimerCount(); + state = ( DG_HEAT_DISINFECT_ACTIVE_COOL_FILL_R1_STATE == state ? + DG_HEAT_DISINFECT_ACTIVE_COOL_DRAIN_R1_FILL_R2_TO_R1_STATE : DG_HEAT_DISINFECT_ACTIVE_COOL_DRAIN_R2_FILL_R1_TO_R2_STATE ); + setHeatDisinfectActiveCoolActuators( state ); + } + else + { + deenergizeActuators( NO_PARK_CONC_PUMPS ); + rsrvrsStatus.rsrvr[ rsrvrID ].rStatus = DG_RESERVOIR_ABOVE_TARGET; + stateStartTimeMS = getMSTimerCount(); + state = ( DG_HEAT_DISINFECT_ACTIVE_COOL_FILL_R1_STATE == state ? + DG_HEAT_DISINFECT_ACITVE_COOL_MIX_DRAIN_R1_STATE : DG_HEAT_DISINFECT_ACTIVE_COOL_MIX_DRAIN_R2_STATE ); + } + } + + state = checkRsrvrMgmtTimeout( rsrvrID, state ); + + return state; +} + /**@}*/ Index: firmware/App/Modes/ModeHeatDisinfectActiveCool.h =================================================================== diff -u -r6499ea25921fcf67826fa0c35bb03caf411ba542 -r1475b55c0a91327f63a99ee5e40a7b55e0c43a06 --- firmware/App/Modes/ModeHeatDisinfectActiveCool.h (.../ModeHeatDisinfectActiveCool.h) (revision 6499ea25921fcf67826fa0c35bb03caf411ba542) +++ firmware/App/Modes/ModeHeatDisinfectActiveCool.h (.../ModeHeatDisinfectActiveCool.h) (revision 1475b55c0a91327f63a99ee5e40a7b55e0c43a06) @@ -32,6 +32,8 @@ // ********** public definitions ********** +#define RSRVRS_FULL_STABLE_TIME_COUNT ( ( 4 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Reservoirs 1 & 2 full stable time in counts. + /// Heat disinfect active cool data publish struct typedef struct { @@ -41,6 +43,20 @@ U32 cancellationMode; ///< Heat disinfect active cool cancellation mode. } MODE_HEAT_DISINFECT_ACTIVE_COOL_DATA_T; +typedef struct +{ + LOAD_CELL_ID_T loadCell; + BOOL drainInit; + DG_RESERVOIR_STATUS_T rStatus; +} DIS_MODE_RSRVR_T; + +typedef struct +{ + DIS_MODE_RSRVR_T rsrvr[ NUM_OF_DG_RESERVOIRS ]; + U32 rsrvrFillStableTime; + U32 rsrvrFillStableTimeoutMS; +} DIS_RSRVR_STATUS_T; + // ********** public function prototypes ********** void initHeatDisinfectActiveCoolMode( void ); // Initialize this module @@ -51,6 +67,9 @@ BOOL stopDGHeatDisinfectActiveCool( void ); // Stop DG heat disinfect +DG_RESERVOIR_STATUS_T getDisinfectRsrvrFillStatus( DG_RESERVOIR_ID_T rsrvrID, DIS_RSRVR_STATUS_T *rsrvrStatus, F32 targetVolML, U32 fillTimeoutMS, U32 stateTimerMS ); +DG_RESERVOIR_STATUS_T getDisinfectRsrvrDrainStatus( DG_RESERVOIR_ID_T rsrvrID, DIS_RSRVR_STATUS_T *rsrvrStatus, U32 drainSteadyTimeoutMS, U32 drainStateTimeoutMS, U32 stateTimerMS ); + /**@}*/ #endif