#include "CPLD.h" #include "MessageSupport.h" #include "ModeFault.h" #include "ModeHeatDisinfectActiveCool.h" #include "OperationModes.h" #include "ROPump.h" #include "Switches.h" #include "TaskGeneral.h" #include "TemperatureSensors.h" #include "Timers.h" #include "Valves.h" /** * @addtogroup DGHeatDisinfectActiveCoolMode * @{ */ // ********** 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 ( 90 * SEC_PER_MIN * MS_PER_SECOND ) ///< RO filter cool down maximum state time in milliseconds. 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 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 ALARM_ID_T alarmDetectedPendingTrigger; ///< Mode heat disinfect active cool pending alarm trigger. // ********** private function prototypes ********** static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T handleHeatDisinfectActiveCoolStartState( 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 handleHeatDisinfectActiveCoolCancelBasicPathState( void ); static void failHeatDisinfectActiveCool( void ); static void publishHeatDisinfectActiveCoolData( void ); static void monitorModeHeatDisinfectActiveCool( void ); /*********************************************************************//** * @brief * The initHeatDisinfectActiveCoolMode function initializes the heat disinfect * active cool mode module. * @details Inputs: none * @details Outputs: heatDisinfectActiveCoolState, stateTimer, dataPublishCounter, * overallHeatDisinfectActiveCoolTimer, ROFCoolingTimer, alarmDetectedPendingTrigger * heatDisinfectActiceCoolPrevState, * @return none *************************************************************************/ void initHeatDisinfectActiveCoolMode( void ) { heatDisinfectActiveCoolState = DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_START; heatDisinfectActiceCoolPrevState = DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_START; stateTimer = 0; dataPublishCounter = 0; overallHeatDisinfectActiveCoolTimer = 0; ROFCoolingTimer = 0; alarmDetectedPendingTrigger = ALARM_ID_NO_ALARM; } /*********************************************************************//** * @brief * The transitionToHeatDisinfectActiveCoolMode function prepares for transition to * heat disinfect active cool mode * @details Inputs: none * @details Outputs: none * @return initial state *************************************************************************/ U32 transitionToHeatDisinfectActiveCoolMode( void ) { deenergizeActuators( NO_PARK_CONC_PUMPS ); initHeatDisinfectActiveCoolMode(); setCPLDCleanLEDColor( CPLD_CLEAN_LED_ORANGE ); return heatDisinfectActiveCoolState; } /*********************************************************************//** * @brief * The execHeatDisinfectActiveCoolMode function executes the heat disinfect * active cool mode state machine. * @details Inputs: heatDisinfectActiveCoolState * @details Outputs: heatDisinfectActiveCoolState * @return current state *************************************************************************/ U32 execHeatDisinfectActiveCoolMode( void ) { // TODO the inlet water check? monitorModeHeatDisinfectActiveCool(); switch( heatDisinfectActiveCoolState ) { case DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_START: heatDisinfectActiveCoolState = handleHeatDisinfectActiveCoolStartState(); 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: heatDisinfectActiveCoolState = handleHeatDisinfectActiveCoolCancelBasicPathState(); break; case DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_COMPLETE: heatDisinfectActiveCoolState = handleHeatDisinfectActiveCoolCompleteState(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_HEAT_DISINFECT_ACTIVE_COOL_INVALID_EXEC_STATE, heatDisinfectActiveCoolState ) heatDisinfectActiveCoolState = DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_START; break; } publishHeatDisinfectActiveCoolData(); return heatDisinfectActiveCoolState; } /*********************************************************************//** * @brief * The getCurrentHeatDisinfectActiveCoolState function returns the current * state of the heat disinfect active cool mode. * @details Inputs: heatDisinfectActiveCoolState * @details Outputs: none * @return the current state of heat disinfect active cool mode. *************************************************************************/ DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T getCurrentHeatDisinfectActiveCoolState( void ) { return heatDisinfectActiveCoolState; } /*********************************************************************//** * @brief * The stopDGHeatDisinfectActiveCool function stops heat disinfect active * cool mode. * @details Inputs: none * @details Outputs: none * @return TRUE is current operation mode is heat disinfect active cool, * otherwise FALSE *************************************************************************/ BOOL stopDGHeatDisinfectActiveCool( void ) { BOOL status = FALSE; // Check if the current operation mode is heat disinfect active cool if ( DG_MODE_HCOL == getCurrentOperationMode() ) { // Reset all the actuators deenergizeActuators( PARK_CONC_PUMPS ); // Transition to mode standby requestNewOperationMode( DG_MODE_STAN ); status = TRUE; } return status; } // ********** private functions ********** /*********************************************************************//** * @brief * The handleHeatDisinfectActiveCoolStartState function handles the heat * disinfect active cool start state. * @details Inputs: anone * @details Outputs: ROFCoolingTimer, 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; // De-energize all the valves that are not in the path anymore // and wait for the RO membrane to be cooled down. setValveState( VPI, VALVE_STATE_CLOSED ); setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); setValveState( VRD1, VALVE_STATE_CLOSED ); setValveState( VBF, VALVE_STATE_OPEN ); 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 ); ROFCoolingTimer = 0; stateTimer = getMSTimerCount(); return state; } /*********************************************************************//** * @brief * The handleHeatDisinfectActiveCoolCoolDownROFilterState function handles * the heat disinfect active cool cool down RO filter state. The state * monitors the temperature at THd and if it is less than 45 C, it transitions * to the next state. * @details Inputs: stateTimer, ROFCoolingTimer * @details Outputs: stateTimer, ROFcoolingTimer, heatDisinfectUIState, * heatDisinfectActiceCoolPrevState, heatDisinfectActiceCoolPrevState * @return next state of the heat disinfect active cool state machine *************************************************************************/ static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T handleHeatDisinfectActiveCoolCoolDownROFilterState( void ) { DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T state = DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_COOL_DOWN_RO_FILTER; // THd is the closet sensor to the RO filter and this temperature is monitored // until it is dropped below 45 C to be able to run fluid through the RO filter F32 THdTemp = getTemperatureValue( TEMPSENSORS_HEAT_DISINFECT ); if ( ( 0 == ROFCoolingTimer ) && ( THdTemp < TARGET_THD_SENSOR_FOR_RINSING_C ) ) { // Temperature is below target - perform mandatory cool down ROFCoolingTimer = getMSTimerCount(); } else if ( THdTemp >= TARGET_THD_SENSOR_FOR_RINSING_C ) { // Temperature is not below target - reset the timer and keep looking ROFCoolingTimer = 0; } if ( ( ROFCoolingTimer != 0 ) && ( TRUE == didTimeout( ROFCoolingTimer, ROF_COOL_DOWN_CIRCULATION_TIME_MS ) ) ) { // Temperature is below target, transition to next state setValveState( VPI, VALVE_STATE_OPEN ); setValveState( VBF, VALVE_STATE_CLOSED ); setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); setValveState( VRC, VALVE_STATE_RECIRC_C_TO_NC ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); signalROPumpHardStop(); stateTimer = getMSTimerCount(); state = DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_COMPLETE; } else if ( ( TRUE == didTimeout( stateTimer, 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; } return state; } /*********************************************************************//** * @brief * The handleHeatDisinfectActiveCoolCompleteState function handles the * heat disinfect active cool complete state. * @details Inputs: none * @details Outputs: none * @return next state of the heat disinfect active cool state machine *************************************************************************/ static DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T handleHeatDisinfectActiveCoolCompleteState( void ) { DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_T state = DG_HEAT_DISINFECT_ACTIVE_COOL_STATE_COMPLETE; stopDGHeatDisinfectActiveCool(); return state; } /*********************************************************************//** * @brief * The handleHeatDisinfectActiveCoolCancelBasicPathState function handles the * heat disinfect active cool cancel mode basic path state. The state sets * the state to complete and raises an alarm. * @details Inputs: none * @details Outputs: none * @return next state of the heat disinfect active cool state machine *************************************************************************/ 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; failHeatDisinfectActiveCool(); return state; } /*********************************************************************//** * @brief * The failHeatDisinfect function sets the alarm that failed the heat * disinfect mode. * @details Inputs: alarmDetectedPendingTrigger, prevHeatDisinfectState * @details Outputs: none * @return none *************************************************************************/ static void failHeatDisinfectActiveCool( void ) { // In the cleaning modes the alarms are triggered but the mode is not transitioned to fault automatically // so transition to fault mode is done here if ( alarmDetectedPendingTrigger != ALARM_ID_NO_ALARM ) { SET_ALARM_WITH_1_U32_DATA( alarmDetectedPendingTrigger, heatDisinfectActiceCoolPrevState ) } requestNewOperationMode( DG_MODE_FAUL ); } /*********************************************************************//** * @brief * The publishHeatDisinfectActiveCoolData function publishes heat disinfect * active cool data at the set interval. * @details Inputs: dataPublishCounter * @details Outputs: dataPublishCounter * @return: none *************************************************************************/ static void publishHeatDisinfectActiveCoolData( void ) { if ( ++dataPublishCounter >= HEAT_DISINFECT_ACTIVE_COOL_DATA_PUB_INTERVAL ) { MODE_HEAT_DISINFECT_ACTIVE_COOL_DATA_T data; data.heatDisinfectActivCoolState = (U32)heatDisinfectActiveCoolState; data.overallElapsedTime = calcTimeSince( overallHeatDisinfectActiveCoolTimer ); data.stateElapsedTime = calcTimeSince( stateTimer ); 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 ) ); dataPublishCounter = 0; } } /*********************************************************************//** * @brief * The monitorModeHeatDisinfectActiveCool function monitors the status of * the caps and sets the state of the state machine to water cancellation * path if the caps are not closed during the run. * @details Inputs: none * @details Outputs: heatDisinfectActiceCoolPrevState, * heatDisinfectActiceCoolPrevState, alarmDetectedPendingTrigger * @return: none *************************************************************************/ static void monitorModeHeatDisinfectActiveCool( void ) { #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_CAPS_MONITOR ) != SW_CONFIG_ENABLE_VALUE ) #endif { if ( ( STATE_OPEN == getSwitchStatus( CONCENTRATE_CAP ) ) || ( STATE_OPEN == getSwitchStatus( DIALYSATE_CAP ) ) ) { // Set the variables to fail and go to cancel water path. Set the pending alarm to no alarm so the cancel water path // 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; alarmDetectedPendingTrigger = ALARM_ID_DG_DIALYSATE_OR_CONC_CAP_NOT_IN_PROPER_POSITION; } } } /**@}*/