/************************************************************************** * * Copyright (c) 2019-2022 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 ModeGenIdle.c * * @author (last) Dara Navaei * @date (last) 10-Dec-2021 * * @author (original) Quang Nguyen * @date (original) 06-Aug-2021 * ***************************************************************************/ #include "ConcentratePumps.h" #include "ConductivitySensors.h" #include "DrainPump.h" #include "FPGA.h" #include "Heaters.h" #include "ModeFill.h" #include "ModeGenIdle.h" #include "NVDataMgmt.h" #include "OperationModes.h" #include "Pressures.h" #include "Reservoirs.h" #include "ROPump.h" #include "SystemComm.h" #include "TaskGeneral.h" #include "TemperatureSensors.h" #include "Timers.h" #include "UVReactors.h" #include "Valves.h" /** * @addtogroup DGRecirculateMode * @{ */ // ********** private definitions ********** #define TARGET_RO_PRESSURE_PSI 130 ///< Target pressure for RO pump. #define TARGET_RO_FLOW_RATE_L 0.3 ///< Target flow rate for RO pump. #define TARGET_FLUSH_WATER_RO_FLOW_RATE_L 0.3 ///< Target flow rate for RO pump. TODO: determine the flow rate /// The time of HD lost comm before DG transition back to standby. #define HD_LOST_COMM_TIMEOUT_MS (5 * SEC_PER_MIN * MS_PER_SECOND ) // ********** private data ********** static DG_GEN_IDLE_MODE_STATE_T genIdleState; ///< Currently active generation idle state. static DG_GEN_IDLE_MODE_BAD_FILL_STATE_T badFillState; ///< Current active bad fill state. static F32 flushWaterVolumeL = 0.0; ///< Volume of water pumped by RO pump during flush water state. static U32 hdLostCommStartTime_ms = 0; ///< Lost communication with HD start time in ms. // ********** private function prototypes ********** static DG_GEN_IDLE_MODE_STATE_T handleIdleStartState( void ); static DG_GEN_IDLE_MODE_STATE_T handleFlushWaterState( void ); static DG_GEN_IDLE_MODE_STATE_T handleBadFillState( void ); // This state has sub-states 1.0 to 1.4 static DG_GEN_IDLE_MODE_BAD_FILL_STATE_T handleFirstDrainState( void ); // idle 1.0 static DG_GEN_IDLE_MODE_BAD_FILL_STATE_T handleFlushFillState( void ); // idle 1.1 static DG_GEN_IDLE_MODE_BAD_FILL_STATE_T handleSecondDrainState( void ); // idle 1.2 static DG_GEN_IDLE_MODE_BAD_FILL_STATE_T handleRefillState( void ); // idle 1.3 static DG_GEN_IDLE_MODE_BAD_FILL_STATE_T handleClearAlarmState( void ); // idle 1.4 /*********************************************************************//** * @brief * The initGenIdleMode function initializes the generation idle mode module. * @details Inputs: none * @details Outputs: Generation idle mode module initialized * @return none *************************************************************************/ void initGenIdleMode( void ) { genIdleState = DG_GEN_IDLE_MODE_STATE_START; badFillState = DG_HANDLE_BAD_FILL_STATE_FIRST_DRAIN; flushWaterVolumeL = 0.0; hdLostCommStartTime_ms = 0; } /*********************************************************************//** * @brief * The transitionToGenIdleMode function prepares for transition to generation idle mode. * @details Inputs: none * @details Outputs: Re-initialized generation idle mode * @return initial state *************************************************************************/ U32 transitionToGenIdleMode( void ) { // Re-initialize each time we transition to generation idle mode initGenIdleMode(); // Set initial actuator states setValveState( VSP, VALVE_STATE_CLOSED ); setValveState( VPI, VALVE_STATE_OPEN ); setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); setValveState( VRD1, VALVE_STATE_CLOSED ); setValveState( VRD2, VALVE_STATE_CLOSED ); setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); signalDrainPumpHardStop(); requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); // UV reactors on turnOnUVReactor( INLET_UV_REACTOR ); turnOnUVReactor( OUTLET_UV_REACTOR ); // NOTE: The target flow rate should be set prior to setting the start primary heater // because the initial guess in the heaters driver needs the target flow to calculate // the new PWMs for the main and small primary heaters #ifndef DISABLE_FLOW_CONTROL_TREATMENT setROPumpTargetFlowRateLPM( TARGET_FLUSH_WATER_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); setHeaterTargetTemperature( DG_PRIMARY_HEATER, getPrimaryHeaterTargetTemperature() ); startHeater( DG_PRIMARY_HEATER ); #endif return genIdleState; } /*********************************************************************//** * @brief * The getCurrentGenIdleState function returns the current state of the * generation idle mode. * @details Inputs: genIdleState * @details Outputs: none * @return the current state of generation idle mode *************************************************************************/ DG_GEN_IDLE_MODE_STATE_T getCurrentGenIdleState( void ) { return genIdleState; } /*********************************************************************//** * @brief * The requestDGStop function handles an HD request to stop (return to standby mode). * @details Inputs: none * @details Outputs: DG standby mode requested * @return TRUE if request accepted, FALSE if not. *************************************************************************/ BOOL requestDGStop( void ) { BOOL result = TRUE; requestNewOperationMode( DG_MODE_STAN ); return result; } /*********************************************************************//** * @brief * The execGenIdleMode function executes the generation idle mode state machine. * @details Inputs: genIdleState * @details Outputs: Check water quality, generation idle mode state machine executed * @return current state *************************************************************************/ U32 execGenIdleMode( void ) { // Check inlet water conductivity, temperature, pressure, and RO rejection ratio checkInletWaterConductivity(); checkInletWaterTemperature(); checkInletPressure(); checkRORejectionRatio(); // Transition to standby mode when HD is not communicating if ( TRUE == isHDCommunicating() ) { hdLostCommStartTime_ms = getMSTimerCount(); } else { if ( TRUE == didTimeout( hdLostCommStartTime_ms, HD_LOST_COMM_TIMEOUT_MS ) ) { requestNewOperationMode( DG_MODE_STAN ); } } // Execute current generation idle state switch ( genIdleState ) { case DG_GEN_IDLE_MODE_STATE_START: genIdleState = handleIdleStartState(); break; case DG_GEN_IDLE_MODE_STATE_FLUSH_WATER: genIdleState = handleFlushWaterState(); break; case DG_GEN_IDLE_MODE_STATE_HANDLE_BAD_FILL: genIdleState = handleBadFillState(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_GEN_IDLE_MODE_INVALID_EXEC_STATE, genIdleState ) genIdleState = DG_GEN_IDLE_MODE_STATE_START; break; } return (U32)genIdleState; } /*********************************************************************//** * @brief * The handleIdleStartState function executes the start state of the * generation idle mode state machine. * @details Inputs: none * @details Outputs: none * @return the next state *************************************************************************/ static DG_GEN_IDLE_MODE_STATE_T handleIdleStartState( void ) { DG_GEN_IDLE_MODE_STATE_T result = DG_GEN_IDLE_MODE_STATE_START; if ( TRUE == isBadFill() ) // bad fill due to conductivity is out of range and assume bottles need prime { result = DG_GEN_IDLE_MODE_STATE_HANDLE_BAD_FILL ; } else { result = DG_GEN_IDLE_MODE_STATE_FLUSH_WATER; } return result; } /*********************************************************************//** * @brief * The handleFlushWaterState function executes the flush water state * generation idle mode state machine. * @details Inputs: none * @details Outputs: none * @return the next state *************************************************************************/ static DG_GEN_IDLE_MODE_STATE_T handleFlushWaterState( void ) { DG_GEN_IDLE_MODE_STATE_T result = DG_GEN_IDLE_MODE_STATE_FLUSH_WATER; return result; } /*********************************************************************//** * @brief * The handleBadFillState function executes the bad fill state of the * generation idle mode state machine. * @details Inputs: none * @details Outputs: badFillState * @return the next state *************************************************************************/ static DG_GEN_IDLE_MODE_STATE_T handleBadFillState( void ) { DG_GEN_IDLE_MODE_STATE_T result = DG_GEN_IDLE_MODE_STATE_HANDLE_BAD_FILL; // Execute current bad fill state switch ( badFillState ) { case DG_HANDLE_BAD_FILL_STATE_START: badFillState = DG_HANDLE_BAD_FILL_STATE_FIRST_DRAIN; break; case DG_HANDLE_BAD_FILL_STATE_FIRST_DRAIN: // idle 1.0 badFillState = handleFirstDrainState(); break; case DG_HANDLE_BAD_FILL_STATE_FLUSH_FILL: // idle 1.1 badFillState = handleFlushFillState(); break; case DG_HANDLE_BAD_FILL_STATE_SECOND_DRAIN: // idle 1.2 badFillState = handleSecondDrainState(); break; case DG_HANDLE_BAD_FILL_STATE_REFILL: badFillState = handleRefillState(); // idle 1.3 break; case DG_HANDLE_BAD_FILL_STATE_CLEAR_ALARM: badFillState = handleClearAlarmState(); // idle 1.4 break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_GEN_IDLE_MODE_INVALID_EXEC_STATE, genIdleState ) badFillState = DG_HANDLE_BAD_FILL_STATE_START; break; } return result; } /*********************************************************************//** * @brief * The handleFirstDrainState function executes the first drain state of the * handle bad fill state machine. * @details Inputs: none * @details Outputs: none * @return the next state *************************************************************************/ static DG_GEN_IDLE_MODE_BAD_FILL_STATE_T handleFirstDrainState( void ) { DG_GEN_IDLE_MODE_BAD_FILL_STATE_T result = DG_HANDLE_BAD_FILL_STATE_FIRST_DRAIN; requestNewOperationMode( DG_MODE_DRAI ); // go to drain mode to empty bad dialysate because this is a bad fill result = DG_HANDLE_BAD_FILL_STATE_FLUSH_FILL; // after first drain is completed, go to next sub-state return result; } /*********************************************************************//** * @brief * The handleFlushFillState function executes the flush fill state of the * handle bad fill state machine. * @details Inputs: none * @details Outputs: none * @return the next state *************************************************************************/ static DG_GEN_IDLE_MODE_BAD_FILL_STATE_T handleFlushFillState( void ) { DG_GEN_IDLE_MODE_BAD_FILL_STATE_T result = DG_HANDLE_BAD_FILL_STATE_FLUSH_FILL; requestNewOperationMode( DG_MODE_FILL ); // When fill is completed, it goes to generation idle mode (DG_GEN_IDLE_MODE_STATE_START) result = DG_HANDLE_BAD_FILL_STATE_SECOND_DRAIN; // (idle 1.2) return result; } /*********************************************************************//** * @brief * The handleSecondDrainState function executes the second drain state of the * handle bad fill state machine. * @details Inputs: none * @details Outputs: none * @return the next state *************************************************************************/ static DG_GEN_IDLE_MODE_BAD_FILL_STATE_T handleSecondDrainState( void ) { DG_GEN_IDLE_MODE_BAD_FILL_STATE_T result = DG_HANDLE_BAD_FILL_STATE_SECOND_DRAIN; requestNewOperationMode( DG_MODE_DRAI ); // go to drain mode to empty bad dialysate because this is a bad fill result = DG_HANDLE_BAD_FILL_STATE_REFILL; // after second drain completed, go to refill sub-state (idle 1.3) return result; } /*********************************************************************//** * @brief * The handleRefillState function executes refill state of the handle bad * fill state machine. * @details Inputs: none * @details Outputs: none * @return the next state *************************************************************************/ static DG_GEN_IDLE_MODE_BAD_FILL_STATE_T handleRefillState( void ) { DG_GEN_IDLE_MODE_BAD_FILL_STATE_T result = DG_HANDLE_BAD_FILL_STATE_REFILL; requestNewOperationMode( DG_MODE_FILL ); result = DG_HANDLE_BAD_FILL_STATE_CLEAR_ALARM; // (idle 1.4) return result; } /*********************************************************************//** * @brief * The handleClearAlarmState function executes the clear alarm state of the * handle bad fill state machine. * @details Inputs: none * @details Outputs: none * @return the next state *************************************************************************/ static DG_GEN_IDLE_MODE_BAD_FILL_STATE_T handleClearAlarmState( void ) { DG_GEN_IDLE_MODE_BAD_FILL_STATE_T result = DG_HANDLE_BAD_FILL_STATE_CLEAR_ALARM; // clear wait for dialysate alarm condition to allow resume clearAlarmCondition( ALARM_ID_CREATING_DIALYSATE_PLEASE_WAIT ); // resume option will appear requestNewOperationMode( DG_MODE_GENE ); // go to generation idle mode return result; } /**@}*/