Index: firmware/App/Modes/ModeFlush.c =================================================================== diff -u -re82ddb85a3b3a1fc5d591d8cca0d006597fd94cf -r6127d594f1673bd75ffe7be22eec69a2f39e025d --- firmware/App/Modes/ModeFlush.c (.../ModeFlush.c) (revision e82ddb85a3b3a1fc5d591d8cca0d006597fd94cf) +++ firmware/App/Modes/ModeFlush.c (.../ModeFlush.c) (revision 6127d594f1673bd75ffe7be22eec69a2f39e025d) @@ -16,7 +16,6 @@ ***************************************************************************/ #include "ConcentratePumps.h" -#include "ConductivitySensors.h" #include "CPLD.h" #include "DrainPump.h" #include "FlowSensors.h" @@ -40,161 +39,118 @@ * @{ */ - // ********** private definitions ********** // General defines -#define MAX_ALLOWED_STATE_TRIALS 1 ///< Max allowed trials on a state. This is general among all the states. -#define CHEM_DISINFECT_FLUSH_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Mode chem disinfect data publish interval in counts. +#define FLUSH_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Mode flush data publish interval in counts. +#define RO_PUMP_TARGET_FLOW_RATE_LPM 0.8F ///< RO pump target flow rate during flush/fill in L/min. +#define RO_PUMP_MAX_PRESSURE_PSI 130 ///< Maximum RO pump pressure during flush/fill states in psi. +#define DRAIN_PUMP_TARGET_RPM 2400 ///< Drain pump target RPM during drain. -// Start state defines -#define MIN_INLET_PRESSURE_PSI 30.0F ///< Minimum water inlet pressure in psi. - // Drain R1 & R2 states defines -#define DRAIN_PUMP_TARGET_RPM 2400 ///< Drain pump target RPM during drain. -#define RSRVRS_INITIAL_FINAL_DRAIN_TIME_OUT_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 initial drain time out in milliseconds. -#define RSRVRS_INITIAL_DRAIN_TIME_OUT_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 initial drain time out in milliseconds. -#define DRAIN_WEIGHT_UNCHANGE_TIMEOUT ( 6 * MS_PER_SECOND ) ///< Time period of unchanged weight during draining before timeout. +#define DRAIN_WEIGHT_UNCHANGE_TIMEOUT ( 6 * MS_PER_SECOND ) ///< Time period of unchanged weight during draining before timeout. // Flush drain path state defines -#define FLUSH_DRAIN_WAIT_TIME_MS ( SEC_PER_MIN * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. -#define MAX_ALLOWED_FLUSH_DRAIN_PERIODS 2 ///< Number of flush drain periods to wait for inlet water to come in range -#define MIN_INLET_TEMPERATURE_C 20.0F ///< Minimum water inlet temperature in C. TODO original temperature was 25 C -#define MAX_INLET_CONDUCTIVITY_US_PER_CM 2000.0F ///< Maximum water inlet conductivity in us/cm -#define MIN_INLET_CONDUCTIVITY_US_PER_CM 100.0F ///< Minimum water inlet conductivity in us/cm +#define FLUSH_DRAIN_WAIT_TIME_MS ( 2 * 60 * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. -// Flush circulation path state defines -#define RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM 0.8F ///< RO pump target flow rate during flush/fill in L/min. -#define MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI 130 ///< Maximum RO pump pressure during flush/fill states in psi. -#define FLUSH_CICRCULATION_WAIT_TIME_MS ( 30 * MS_PER_SECOND ) ///< Flush/rinse circulation path wait time in milliseconds. +// Flush dialysate state defines +#define FLUSH_DIALYSATE_WAIT_TIME_MS ( 60 * MS_PER_SECOND ) ///< Flush dialysate wait time in milliseconds. -// Flush and drain R1 and R2 -#define RSRVRS_FULL_VOL_ML 1000.0F ///< Reservoirs 1 & 2 full volume in mL. TODo original value was 1900 -#define RSRVRS_FULL_STABLE_TIME_COUNT ( ( 4 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Reservoirs 1 & 2 full stable time in counts. -#define RSRVRS_FILL_UP_TIMEOUT_MS ( 5 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 full fill up timeout in ms. -#define RSRVRS_FLUSH_DRAIN_TIMEOUT_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 drain timeout in ms. -#define FLUSH_ADDITIONAL_TIME_MS ( 38 * MS_PER_SECOND ) ///< Additional time to flush after reservoir full -#define NUM_OF_RINSE_CYCLES 2 ///< Number of rinse cycles +// Flush concentrate straws state defines +#define FLUSH_CONCENTRATE_STRAWS_TIME_MS ( 3 * 60 * MS_PER_SECOND ) ///< Flush concentrate straws wait time in milliseconds. +#define ACID_PUMP_SPEED_ML_PER_MIN -30.0F ///< Acid pump speed in mL/min. -#define CONC_PUMP_FLUSH_SPEED_ML_PER_MIN 40.0 ///< Concentrate pump speed for flush -#define FLUSH_DISINFECTANT_LINE_WAIT_TIME_MS ( 2.5 * SEC_PER_MIN * MS_PER_SECOND ) ///< Time to flush disinfectant line in milliseconds. -#define FLUSH_UF_WAIT_TIME_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Time to flush UF in milliseconds. +// The bicarb pump is 2% faster than the acid pump to create a flow from acid to bicarb line during flush +#define BICARB_PUMP_SPEED_ML_PER_MIN 30.6F ///< Bicarb pump speed in mL/min. -/// Cancellation paths -typedef enum Cancellation_modes -{ - CANCELLATION_MODE_NONE = 0, ///< Cancellation mode none. - CANCELLATION_MODE_BASIC, ///< Cancellation mode basic. - CANCELLATION_MODE_WATER, ///< Cancellation mode water. - NUM_OF_CANCELLATION_MODES ///< Number of cancellation modes. -} CANCELLATION_MODE_T; +// Flush and drain R1 and R2 state defines +#define RSRVRS_FULL_VOL_ML 1800.0F ///< Reservoirs 1 & 2 full volume in mL. TODo original value was 1900 +#define RSRVRS_PARTIAL_FILL_VOL_ML 500.0F ///< Reservoirs 1 & 2 partial volume in mL. +#define RSRVRS_FULL_STABLE_TIME_COUNT ( ( 4 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Reservoirs 1 & 2 full stable time in counts. +#define RSRVRS_FILL_UP_TIMEOUT_MS ( 5 * 60 * MS_PER_SECOND ) ///< Reservoirs 1 & 2 full fill up timeout in ms. +#define RSRVRS_PARTIAL_FILL_TIMEOUT_MS ( 2 * 60 * MS_PER_SECOND ) ///< Reservoirs 1 & 2 partial fill up timeout in ms. +#define RSRVRS_DRAIN_TIMEOUT_MS ( 2 * 60 * MS_PER_SECOND ) ///< Reservoirs 1 & 2 drain timeout in ms. +#define FINAL_DRAIN_RO_PUMP_FLOW_LPM 0.6F ///< Final drain RO pump flow rate in L/min. This is used to flush the drain line during drain. -/// Non-volatile write structure -typedef struct -{ - BOOL hasDisFlushStatusBeenWrittenToNV; ///< Boolean flag to indicate whether the disinfect flush status been written to NV or not. - BOOL hasDisFlushCompleteDateBeenWrittenToNV; ///< Boolean flag to indicate whether the disinfect flush complete date been written to NV or not. -} DISINFECT_FLUSH_NV_OPS_T; +// Flush drain line state defines +#define FLUSH_DRAIN_LINE_VOLUME_L 0.1F ///< Water volume to flush in liters. +#define FLUSH_DRAIN_LINE_TIMEOUT_MS ( 1 * 60 * MS_PER_SECOND ) ///< Flush drain lines timeout in milliseconds. +// Flush circulation state defines +#define FLUSH_CIRCULATION_WAIT_TIME_MS ( 0.5F * 60 * MS_PER_SECOND ) ///< Flush circulation wait time in milliseconds. + +// Flush with fresh water state defines +#define FLUSH_WITH_FRESH_WATER_WAIT_TIME_MS ( 0.5F * 60 * MS_PER_SECOND ) ///< Flush with fresh water wait time in milliseconds. + // ********** private data ********** -static DG_CHEM_DISINFECT_FLUSH_STATE_T chemDisinfectFlushState = DG_CHEM_DISINFECT_FLUSH_STATE_START; ///< Currently active chemical disinfect state. -static DG_CHEM_DISINFECT_FLUSH_STATE_T prevChemDisinfectFlushState = DG_CHEM_DISINFECT_FLUSH_STATE_START; ///< Previous active chemical disinfect flush state before alarm. -static DG_CHEM_DISINFECT_UI_STATE_T chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_NOT_RUNNING; ///< Currently active chemical disinfect UI state. -static U32 overallChemDisinfectFlushTimerStart = 0; -static U32 stateTimer = 0; ///< Chemical disinfect state timer to be used in different states. -static U32 stateTrialCounter = 0; ///< Chemical disinfect state trial counter to be used for retries in different states. -static BOOL areTempSensorsInRange = FALSE; ///< Chemical disinfect temperature sensors in/out range flag. -static BOOL haveInletWaterChecksPassed = TRUE; ///< Inlet water pressure, temperature, and pressure in range flag -/// Boolean flag to check whether draining R1 and R2 is at the end of the chemical disinfect flush cycle or in the beginning. So the drain states can be reused. -static BOOL isThisLastDrain = FALSE; -static DG_RESERVOIR_STATUS_T rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; ///< Reservoir 1 status. -static DG_RESERVOIR_STATUS_T rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; ///< Reservoir 2 status. -static F32 R1ChemDisinfectFlushVol = 0.0; ///< Reservoir 1 full volume during chemical disinfect. -static F32 R2ChemDisinfectFlushVol = 0.0; ///< Reservoir 2 full volume during chemical disinfect. -static U32 chemDisinfectFlushTimer = 0; ///< Chemical disinfect timer. -static U32 rinseCycleCounter = 0; ///< Counter for rinse fill and drain cycles -static U32 rsrvrsVolMonitorTimer = 0; ///< Reservoir 1 & 2 volume monitor timers during chemical disinfect. -static BOOL areRsrvrsLeaking = FALSE; ///< Reservoir 1 & 2 leak check flag during chemical disinfect. -static U32 dataPublishCounter = 0; ///< Chemical Disinfect data publish counter. -static CANCELLATION_MODE_T cancellationMode = CANCELLATION_MODE_NONE; ///< Cancellation mode. -static U32 rsrvrFillStableTimeCounter; ///< Reservoirs fill stable time counter. -static ALARM_ID_T alarmDetectedPendingTrigger; ///< Chemical disinfect alarm to raise. -static U32 numberOfPostDisinfectRinses; ///< Number of times to rinse the fluid path after chemical disinfect. -static BOOL haveDrainParamsBeenInit[ NUM_OF_DG_RESERVOIRS ]; ///< Boolean flag to indicate whether the drain parameters have been reset or not. -static DISINFECT_FLUSH_NV_OPS_T disinfectFlushNVOps; ///< Disinfect flush non-volatile memory operations. +static DG_FLUSH_STATE_T flushState; ///< Current active flush state. +static DG_FLUSH_STATE_T prevFlushState; ///< Previous flush state. +static DG_FLUSH_UI_STATE_T flushUIState; ///< Current UI flush state. +static U32 rsrvrFillStableTimeCounter; ///< Reservoirs fill stable time counter. +static U32 overallFlushElapsedTimeStart; ///< Overall flush mode elapsed time start. +static U32 stateTimerStart; ///< State timer start. +static ALARM_ID_T alarmDetectedPendingTrigger; ///< Alarm ID that is detected and is pending to be triggered. +static DG_RESERVOIR_STATUS_T rsrvr1Status; ///< Reservoir 1 status. +static DG_RESERVOIR_STATUS_T rsrvr2Status; ///< Reservoir 2 status. +static BOOL isThisInitialDrain; ///< Initial drain boolean flag. +static U32 dataPublishCounter; ///< Flush data publish counter. +static BOOL hasWaterCancellationBeenSet; ///< Water cancellation set/not set boolean flag. +static F32 flushLinesVolumeL; ///< Volume of water pumped by RO pump during flush lines state. +static BOOL haveDrainParamsBeenInit[ NUM_OF_DG_RESERVOIRS ]; ///< Boolean flag to indicate whether the drain parameters have been reset or not. // ********** private function prototypes ********** -//static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushRemoveAcidBottleFromUIState( void ); -static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushStartState( void ); -static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushDrainR1State( void ); -static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushDrainR2State( void ); -static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushFlushDrainState( void ); -static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushFlushDisinfectantLineState( void ); -static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushFlushUFState( void ); -static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushFlushR2ToR1DrainR1State( void ); -static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushFlushR1ToR2DrainR2State( void ); -static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushCancelModeBasicPathState(void); -static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushCancelModeWaterPathState(void); -static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushCompleteState( void ); +static DG_FLUSH_STATE_T handleFlushModeStartState( void ); +static DG_FLUSH_STATE_T handleFlushModeDrainR1State( void ); +static DG_FLUSH_STATE_T handleFlushModeDrainR2State( void ); +static DG_FLUSH_STATE_T handleFlushModeFlushDrainState( void ); +static DG_FLUSH_STATE_T handleFlushModeFlushDialysateState( void ); +static DG_FLUSH_STATE_T handleFlushModeFlushConcentrateStrawsState( void ); +static DG_FLUSH_STATE_T handleFlushModeFlushR1ToR2State( void ); +static DG_FLUSH_STATE_T handleFlushModeFlushR2AndDrainR1State( void ); +static DG_FLUSH_STATE_T handleFlushModeFlushCirculationDrainLineState( void ); +static DG_FLUSH_STATE_T handleFlushModeFlushCirculationState( void ); +static DG_FLUSH_STATE_T handleFlushModeFlushWithFreshWaterState( void ); +static DG_FLUSH_STATE_T handleFlushModeCancelBasicPathState( void ); +static DG_FLUSH_STATE_T handleFlushModeCancelWaterPathState( void ); +static DG_FLUSH_STATE_T handleFlushModeComplete( void ); -static void failChemicalDisinfectFlush( void ); +static void failFlushMode( void ); static DG_RESERVOIR_STATUS_T getRsrvrFillStatus( DG_RESERVOIR_ID_T r, F32 targetVol, U32 timeout ); static DG_RESERVOIR_STATUS_T getRsrvrDrainStatus( DG_RESERVOIR_ID_T r, U32 drainSteadyStateTimeout, U32 timeout ); -static void publishChemicalDisinfectFlushData( void ); -static void monitorModeChemicalDisinfectFlush( void ); -static void writeDisinfectDataToNV( void ); +static void publishFlushData( void ); +static void monitorModeFlush( void ); /*********************************************************************//** * @brief - * The initChemicalDisinfectFlushMode function initializes the chemical - * disinfect flush mode module. + * The initFlushMode function initializes flush mode module. * @details Inputs: none - * @details Outputs: chemDisinfectFlushState, stateTimer, isThisLastDrain, - * stateTrialCounter, areTempSensorsInRange, rsrvr1Status, rsrvr2Status, - * overallChemDisinfectFlushTimer, - * cancellationMode, rsrvrFillStableTimeCounter, prevChemDisinfectFlushState - * numberOfPostDisinfectRinses, - * chemDisinfectFlushUIState, haveDrainParamsBeenInit, - * disinfectFlushNVOps + * @details Outputs: flushState, prevFlushState, rsrvrFillStableTimeCounter, + * overallFlushElapsedTime, isThisInitialDrain, dataPublishCounter, + * rsrvr1Status, rsrvr2Status, hasWaterCancellationBeenSet, + * flushLinesVolumeL, haveDrainParamsBeenInit, stateTimerStart * @return none - *************************************************************************/ -//void initChemicalDisinfectFlushMode( void ) -void initFlushMode(void) +*************************************************************************/ +void initFlushMode( void ) { - chemDisinfectFlushState = DG_CHEM_DISINFECT_FLUSH_STATE_START; - prevChemDisinfectFlushState = DG_CHEM_DISINFECT_FLUSH_STATE_START; - overallChemDisinfectFlushTimerStart = 0; - stateTimer = 0; - isThisLastDrain = FALSE; - stateTrialCounter = 0; - areTempSensorsInRange = FALSE; - haveInletWaterChecksPassed = TRUE; - rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; - rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; - cancellationMode = CANCELLATION_MODE_NONE; - rsrvrFillStableTimeCounter = 0; - numberOfPostDisinfectRinses = 0; - R1ChemDisinfectFlushVol = 0.0; - R2ChemDisinfectFlushVol = 0.0; - chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_NOT_RUNNING; - haveDrainParamsBeenInit[ DG_RESERVOIR_1 ] = FALSE; - haveDrainParamsBeenInit[ DG_RESERVOIR_2 ] = FALSE; - //disinfectFlushNVOps.hasFlushCompleteDateBeenWrittenToNV = FALSE; - //disinfectFlushNVOps.hasFlushStatusBeenWrittenToNV = FALSE; + // Initialize the variables + flushState = DG_FLUSH_STATE_START; + prevFlushState = DG_FLUSH_STATE_START; + flushUIState = FLUSH_UI_STATE_NOT_RUNNING; + rsrvrFillStableTimeCounter = 0; + overallFlushElapsedTimeStart = 0; + isThisInitialDrain = TRUE; + dataPublishCounter = 0; + rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; + rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; + hasWaterCancellationBeenSet = FALSE; + flushLinesVolumeL = 0.0; + haveDrainParamsBeenInit[ DG_RESERVOIR_1 ] = FALSE; + haveDrainParamsBeenInit[ DG_RESERVOIR_2 ] = FALSE; + stateTimerStart = 0; } -/******** -void initFlushMode( void ); // initialize this module -U32 transitionToFlushMode( void ); // prepares for transition to pre-treatment mode -U32 execFlushMode( void ); // execute the pre-treatment mode state machine (call from OperationModes) - -DG_FLUSH_STATE_T getCurrentFlushState( void ); // get the current state of the flush mode. - -BOOL stopDGFlush( void ); -*/ - /*********************************************************************//** * @brief * The transitionToFlushMode function prepares for transition to flush mode. @@ -211,10 +167,91 @@ setCPLDCleanLEDColor( CPLD_CLEAN_LED_BLUE ); - return chemDisinfectFlushState; + return flushState; } +/*********************************************************************//** + * @brief + * The execFlushMode function executes the flush mode state machine. + * @details Inputs: flushState + * @details Outputs: flushState + * @return current state +*************************************************************************/ +U32 execFlushMode( void ) +{ + monitorModeFlush(); + // Execute current flush state + switch ( flushState ) + { + case DG_FLUSH_STATE_START: + flushState = handleFlushModeStartState(); + break; + + case DG_FLUSH_STATE_DRAIN_R1: + flushState = handleFlushModeDrainR1State(); + break; + + case DG_FLUSH_STATE_DRAIN_R2: + flushState = handleFlushModeDrainR2State(); + break; + + case DG_FLUSH_STATE_FLUSH_DRAIN: + flushState = handleFlushModeFlushDrainState(); + break; + + case DG_FLUSH_STATE_FLUSH_DIALYSATE: + flushState = handleFlushModeFlushDialysateState(); + break; + + case DG_FLUSH_STATE_FLUSH_CONCENTRATE_STRAWS: + flushState = handleFlushModeFlushConcentrateStrawsState(); + break; + + case DG_FLUSH_STATE_FLUSH_R1_TO_R2: + flushState = handleFlushModeFlushR1ToR2State(); + break; + + case DG_FLUSH_STATE_FLUSH_R2_AND_DRAIN_R1: + flushState = handleFlushModeFlushR2AndDrainR1State(); + break; + + case DG_FLUSH_STATE_FLUSH_CIRCULATION_DRAIN_LINE: + flushState = handleFlushModeFlushCirculationDrainLineState(); + break; + + case DG_FLUSH_STATE_FLUSH_CIRCULATION: + flushState = handleFlushModeFlushCirculationState(); + break; + + case DG_FLUSH_STATE_FLUSH_WITH_FRESH_WATER: + flushState = handleFlushModeFlushWithFreshWaterState(); + break; + + case DG_FLUSH_STATE_CANCEL_BASIC_PATH: + flushState = handleFlushModeCancelBasicPathState(); + break; + + case DG_FLUSH_STATE_CANCEL_WATER_PATH: + flushState = handleFlushModeCancelWaterPathState(); + break; + + case DG_FLUSH_STATE_COMPLETE: + flushState = handleFlushModeComplete(); + break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_DG_FLUSH_INVALID_EXEC_STATE, flushState ) + flushState = DG_FLUSH_STATE_START; + break; + } + + // Publish the data + publishFlushData(); + + return (U32)flushState; +} + /*********************************************************************//** * @brief * The getCurrentFlushState function returns the current state of the flush @@ -225,7 +262,7 @@ *************************************************************************/ DG_FLUSH_STATE_T getCurrentFlushState( void ) { - return chemDisinfectFlushState; + return flushState; } /*********************************************************************//** @@ -255,684 +292,654 @@ return status; } -/*********************************************************************//** - * @brief - * The execChemicalDisinfectFlushMode function executes the chemical disinfect - * flush mode state machine. - * @details Inputs: none - * @details Outputs: Chemical disinfect flush mode state machine executed - * @return current state of chemical disinfect flush mode - *************************************************************************/ -//U32 execChemicalDisinfectFlushMode( void ) -U32 execFlushMode( void ) -{ - monitorModeChemicalDisinfectFlush(); +// ********** private functions ********** - switch ( chemDisinfectFlushState ) - { - case DG_CHEM_DISINFECT_FLUSH_STATE_START: - chemDisinfectFlushState = handleChemicalDisinfectFlushStartState(); - break; - - case DG_CHEM_DISINFECT_FLUSH_STATE_DISINFECTANT_DRAIN_R1: - chemDisinfectFlushState = handleChemicalDisinfectFlushDrainR1State(); - break; - - case DG_CHEM_DISINFECT_FLUSH_STATE_DISINFECTANT_DRAIN_R2: - chemDisinfectFlushState = handleChemicalDisinfectFlushDrainR2State(); - break; - - case DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_DRAIN: - chemDisinfectFlushState = handleChemicalDisinfectFlushFlushDrainState(); - break; - - case DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_DISINFECTANT_LINE: - chemDisinfectFlushState = handleChemicalDisinfectFlushFlushDisinfectantLineState(); - break; - - case DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_UF: - chemDisinfectFlushState = handleChemicalDisinfectFlushFlushUFState(); - break; - - case DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_R2_TO_R1_DRAIN_R1: - chemDisinfectFlushState = handleChemicalDisinfectFlushFlushR2ToR1DrainR1State(); - break; - - case DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_R1_TO_R2_DRAIN_R2: - chemDisinfectFlushState = handleChemicalDisinfectFlushFlushR1ToR2DrainR2State(); - break; - - case DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_BASIC_PATH: - chemDisinfectFlushState = handleChemicalDisinfectFlushCancelModeBasicPathState(); - break; - - case DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_WATER_PATH: - chemDisinfectFlushState = handleChemicalDisinfectFlushCancelModeWaterPathState(); - break; - - case DG_CHEM_DISINFECT_FLUSH_STATE_COMPLETE: - chemDisinfectFlushState = handleChemicalDisinfectFlushCompleteState(); - break; - - default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_DG_CHEM_DISINFECT_INVALID_EXEC_STATE, chemDisinfectFlushState ) - chemDisinfectFlushState = DG_CHEM_DISINFECT_FLUSH_STATE_START; - break; - } - - //publishChemicalDisinfectFlushData(); - - return chemDisinfectFlushState; -} - /*********************************************************************//** * @brief - * The handleChemicalDisinfectFlushStartState function handles the chemical - * disinfect flush start state. The state checks the inlet pressure and the - * difference in between TDi and TRo sensors and if they are not in - * range, it transitions to basic cancellation path. Otherwise, it - * transitions to the next state. - * @details Inputs: alarm, rsrvrFillStableTimeCounter, rsrvr1Status, - * stateTimer - * @details Outputs: alarm, rsrvrFillStableTimeCounter, rsrvr1Status, - * stateTimer, chemDisinfectFlushUIState - * @return next state of the chemical disinfect flush state machine + * The handleFlushModeStartState function handles the flush start state. + * If the sensors are in range, it transitions to the next state otherwise, + * it transitions to basic cancellation state. + * @details Inputs: stateTimerStart, rsrvr1Status + * @details Outputs: stateTimerStart, rsrvr1Status + * @return next state of the flush state machine *************************************************************************/ -static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushStartState( void ) +static DG_FLUSH_STATE_T handleFlushModeStartState( void ) { - DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_DISINFECTANT_DRAIN_R1; + DG_FLUSH_STATE_T state = DG_FLUSH_STATE_START; - // Set the chemical disinfect that is published on the UI - chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_NOT_RUNNING; + // Start overall flush timer + overallFlushElapsedTimeStart = getMSTimerCount(); - // Start overall chemical disinfect timer - overallChemDisinfectFlushTimerStart = getMSTimerCount(); - - // Set all the actuators to reset and de-energized state - deenergizeActuators(); - // Close VPi to prevent wasting water setValveState( VPI, VALVE_STATE_CLOSED ); // Set the actuators to drain R1 - setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); setValveState( VRD1, VALVE_STATE_OPEN ); + + // Set VPO + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC); + setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); - rsrvrFillStableTimeCounter = 0; - // Assume reservoir 1 is full and drain it - rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - stateTimer = getMSTimerCount(); + flushUIState = FLUSH_UI_STATE_DRAIN_DEVICE; + stateTimerStart = getMSTimerCount(); + rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; + state = DG_FLUSH_STATE_DRAIN_R1; return state; } /*********************************************************************//** * @brief - * The handleChemicalDisinfectFlushDrainR1State function handles the chemical - * disinfect flush drain R1 state. The state drains reservoir 1. If the - * transition is finished within the time, it transitions to the next state, - * otherwise, it transitions to basic cancellation path. - * @details Inputs: stateTimer, rsrvr1Status, rsrvr2Status, isThisLastDrain - * @details Outputs: stateTimer, rsrvr1Status, rsrvr2Status, - * ChemDisinfectFlushUIState - * @return next state of the chemical disinfect state machine + * The handleFlushModeDrainR1State function handles the drain reservoir 1. + * If the drain is completed within the defined time, it transitions to the + * next state, otherwise, it transitions to basic cancellation state. + * @details Inputs: stateTimerStart, rsrvr1Status,rsrvr2Status, isThisInitialDrain + * @details Outputs: stateTimerStart, rsrvr1Status, rsrvr2Status + * @return next state of the flush state machine *************************************************************************/ -static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushDrainR1State( void ) +static DG_FLUSH_STATE_T handleFlushModeDrainR1State( void ) { - DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_DISINFECTANT_DRAIN_R1; + DG_FLUSH_STATE_T state = DG_FLUSH_STATE_DRAIN_R1; - // Set the chemical disinfect that is published on the UI - chemDisinfectFlushUIState = CHEM_DISINFECT_UI_STATE_FLUSH_AFTER_DISINFECT; - if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr1Status ) { - rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_FINAL_DRAIN_TIME_OUT_MS ); + rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_DRAIN_TIMEOUT_MS ); } else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) { - // Assume reservoir 2 is full and drain it - rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; + if ( TRUE == isThisInitialDrain ) + { + // Request a tare for reservoir 1 + tareLoadCell( LOAD_CELL_RESERVOIR_1_PRIMARY ); + tareLoadCell( LOAD_CELL_RESERVOIR_1_BACKUP ); + } - tareLoadCell( LOAD_CELL_RESERVOIR_1_PRIMARY ); - tareLoadCell( LOAD_CELL_RESERVOIR_1_BACKUP ); - - // Done with draining R1 + // Close reservoir 1 drain setValveState( VRD1, VALVE_STATE_CLOSED ); + // Set the actuators to drain R2 + // NOTE: Drain pump is already on and VDr is already on drain state setValveState( VRD2, VALVE_STATE_OPEN ); - rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - state = DG_CHEM_DISINFECT_FLUSH_STATE_DISINFECTANT_DRAIN_R2; + // Set VPO + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC); - // Start the timer - stateTimer = getMSTimerCount(); + stateTimerStart = getMSTimerCount(); + rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; + state = DG_FLUSH_STATE_DRAIN_R2; } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { - prevChemDisinfectFlushState = state; - state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_BASIC_PATH; + state = DG_FLUSH_STATE_CANCEL_BASIC_PATH; } return state; } /*********************************************************************//** * @brief - * The handleChemicalDisinfectFlushDrainR2State function handles the chemical - * disinfect flush drain R2 state. The state drains reservoir 2. If the - * transition is finished within the time, it transitions to the next - * state, otherwise, it transitions to basic cancellation path. - * @details Inputs: stateTimer, rsrvr2Status, isThisLastDrain, - * stateTrialCounter - * @details Outputs: stateTimer, rsrvr2Status, stateTrialCounter, - * chemDisinfectFlushUIState - * @return next state of the chemical disinfect state machine + * The handleFlushModeDrainR2State function handles the drain reservoir 2. + * If the drain is completed within the defined time, it transitions to the + * next state, otherwise, it transitions to basic cancellation state. + * @details Inputs: stateTimerStart, rsrvr1Status, rsrvr2Status, isThisInitialDrain + * @details Outputs: stateTimerStart, rsrvr1Status, rsrvr2Status + * @return next state of the flush state machine *************************************************************************/ -static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushDrainR2State( void ) +static DG_FLUSH_STATE_T handleFlushModeDrainR2State( void ) { - DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_DISINFECTANT_DRAIN_R2; + DG_FLUSH_STATE_T state = DG_FLUSH_STATE_DRAIN_R2; - if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr2Status ) - { - rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_FINAL_DRAIN_TIME_OUT_MS ); - } - else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) - { - signalDrainPumpHardStop(); // Done with draining - if ( TRUE == isThisLastDrain ) - { - state = DG_CHEM_DISINFECT_FLUSH_STATE_COMPLETE; - } - else - { - tareLoadCell( LOAD_CELL_RESERVOIR_2_PRIMARY ); - tareLoadCell( LOAD_CELL_RESERVOIR_2_BACKUP ); - // ??? make sure load cell check is done in tareLoadCell or add that here? - - // Set valves for next state, flush drain - setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); - setValveState( VRD2, VALVE_STATE_CLOSED ); - setValveState( VPI, VALVE_STATE_OPEN ); + if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr2Status ) + { + rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_DRAIN_TIMEOUT_MS ); + } + else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) + { + // Done with draining + signalDrainPumpHardStop(); - stateTrialCounter = 0; - stateTimer = getMSTimerCount(); - state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_DRAIN; - } - } - else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) - { - prevChemDisinfectFlushState = state; - state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_BASIC_PATH; - } + if ( TRUE == isThisInitialDrain ) + { + tareLoadCell( LOAD_CELL_RESERVOIR_2_PRIMARY ); + tareLoadCell( LOAD_CELL_RESERVOIR_2_BACKUP ); + // Set the actuators to flush drain + setValveState( VPI, VALVE_STATE_OPEN ); + setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState( VRD2, VALVE_STATE_CLOSED ); + setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); + + state = DG_FLUSH_STATE_FLUSH_DRAIN; + } + else + { + // Set the actuators to pull fresh water in to drain the circulation line + setValveState( VPI, VALVE_STATE_OPEN ); + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); + setValveState( VRD2, VALVE_STATE_CLOSED ); + setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); + setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); + setROPumpTargetFlowRateLPM( FINAL_DRAIN_RO_PUMP_FLOW_LPM, RO_PUMP_MAX_PRESSURE_PSI ); + + // Turn on the UV reactors + turnOnUVReactor( INLET_UV_REACTOR ); + turnOnUVReactor( OUTLET_UV_REACTOR ); + + flushUIState = FLUSH_UI_STATE_FLUSH_RECIRCULATION_PATH; + state = DG_FLUSH_STATE_FLUSH_CIRCULATION_DRAIN_LINE; + } + + stateTimerStart = getMSTimerCount(); + } + else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) + { + state = DG_FLUSH_STATE_CANCEL_BASIC_PATH; + } + return state; } /*********************************************************************//** * @brief - * The handleChemicalDisinfectFlushFlushDrainState function handles the chemical - * disinfect flush drain state. The state flushes the drain line for a - * period of time and then measures the temperature and conductivity of - * water. If they are not within the range after the specified number of tries, - * it transitions to basic cancellation path, otherwise it transitions to the next state. - * @details Inputs: stateTimer, stateTrialCounter, alarm, - * prevChemDisinfectFlushState - * @details Outputs: stateTimer, stateTrialCounter, alarm, - * prevChemDisinfectFlushState - * @return next state of the chemical disinfect state machine + * The handleFlushModeFlushDrainState function handles the flush drain state. + * Once the flush drain time has elapsed, it transitions to the next state. + * @details Inputs: stateTimerStart + * @details Outputs: stateTimerStart + * @return next state of the flush state machine *************************************************************************/ -static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushFlushDrainState( void ) +static DG_FLUSH_STATE_T handleFlushModeFlushDrainState( void ) { - DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_DRAIN; + DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_DRAIN; - // TODO: check whether flush has already been completed within some time period, skip this state if it has - - // Check if flush time has elapsed - if ( TRUE == didTimeout( stateTimer, FLUSH_DRAIN_WAIT_TIME_MS ) ) + if ( TRUE == didTimeout( stateTimerStart, FLUSH_DRAIN_WAIT_TIME_MS ) ) { - if (haveInletWaterChecksPassed) - { - // set pumps and valves for next state, flush disinfectant line - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); - setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); - // Set the concentrate pump to run at a constant speed during priming in reverse - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, -1.0 * CONC_PUMP_FLUSH_SPEED_ML_PER_MIN ); - requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); - // Turn on the bicarb line with forward direction, to dispense the chemical and mix - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, CONC_PUMP_FLUSH_SPEED_ML_PER_MIN ); - requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); - turnOnUVReactor( INLET_UV_REACTOR ); - turnOnUVReactor( OUTLET_UV_REACTOR ); - - stateTimer = getMSTimerCount(); - state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_DISINFECTANT_LINE; - } - else - { - // If the number of failures have not exceeded the limit, try again. - stateTrialCounter++; - if ( stateTrialCounter < MAX_ALLOWED_FLUSH_DRAIN_PERIODS ) - { - stateTimer = getMSTimerCount(); - } - // Couldn't get a good water sample after a couple of trials and the disinfect flush cycle failed - else - { - alarmDetectedPendingTrigger = ALARM_ID_INLET_WATER_TEMPERATURE_IN_LOW_RANGE; //ALARM_ID_DG_NEW_WAT; - prevChemDisinfectFlushState = state; - state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_BASIC_PATH; - } - } + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); + setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLOW_RATE_LPM, RO_PUMP_MAX_PRESSURE_PSI ); + // Turn on the UV reactors + turnOnUVReactor( INLET_UV_REACTOR ); + turnOnUVReactor( OUTLET_UV_REACTOR ); + + stateTimerStart = getMSTimerCount(); + + state = DG_FLUSH_STATE_FLUSH_DIALYSATE; } return state; } /*********************************************************************//** * @brief - * The handleChemicalDisinfectFlushFlushDisinfectantLineState function handles the - * chemical disinfect flush flush disinfectant line state. The state flushes the - * disinfectant line for a period of time. After the flush if the temperature - * sensors are not within a certain degrees from each other, the state - * transitions to basic cancellation path, otherwise, it transitions to the - * next state. - * @details Inputs: stateTimer, stateTrialCounter, prevChemDisinfectFlushState - * alarm, areTempSensorsInRange, rsrvr1Status, rsrvr2Status - * @details Outputs: stateTimer, stateTrialCounter, prevChemDisinfectFlushState, - * alarm, areTempSensorsInRange, rsrvr1Status, rsrvr2Status - * @return next state of the chemical disinfect state machine - ************************************************************************/ -static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushFlushDisinfectantLineState( void ) + * The handleFlushModeFlushDialysateState function handles the flush + * dialysate state. Once the flush dialysate time has elapsed, it + * transitions to the next state. + * @details Inputs: stateTimerStart + * @details Outputs: stateTimerStart + * @return next state of the flush state machine + *************************************************************************/ +static DG_FLUSH_STATE_T handleFlushModeFlushDialysateState( void ) { - DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_DISINFECTANT_LINE; - - // Check if the flush disinfectant line time has elapsed - if ( TRUE == didTimeout( stateTimer, FLUSH_DISINFECTANT_LINE_WAIT_TIME_MS ) ) + DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_DIALYSATE; + + if ( TRUE == didTimeout( stateTimerStart, FLUSH_DIALYSATE_WAIT_TIME_MS ) ) { + // Turn the pumps on in reverse + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, ACID_PUMP_SPEED_ML_PER_MIN ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, BICARB_PUMP_SPEED_ML_PER_MIN ); - // set the pumps and valves for the next state, flush UF - setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); - setValveState( VRD2, VALVE_STATE_OPEN ); - setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); - - stateTimer = getMSTimerCount(); - state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_UF; + // Turn on the concentrate pumps + requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); + + stateTimerStart = getMSTimerCount(); + + state = DG_FLUSH_STATE_FLUSH_CONCENTRATE_STRAWS; } return state; } /*********************************************************************//** * @brief - * The handleChemicalDisinfectFlushFlushUFState function handles the - * chemical disinfect flush flush UF state. - * @details Inputs: stateTimer, rsrvr1Status, rsrvr2Status, - * prevChemDisinfectFlushState - * @details Outputs: stateTimer, rsrvr1Status, rsrvr2Status, - * prevChemDisinfectFlushState - * @return next state of the chemical disinfect state machine + * The handleFlushModeFlushDialysateState function handles the flush + * dialysate state. Once the flush dialysate time has elapsed, it + * transitions to the next state. + * @details Inputs: rsrvr1Status, rsrvr2Status, stateTimerStart + * @details Outputs: rsrvr1Status, rsrvr2Status, stateTimerStart + * @return next state of the flush state machine *************************************************************************/ -static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushFlushUFState( void ) +static DG_FLUSH_STATE_T handleFlushModeFlushConcentrateStrawsState( void ) { - DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_UF; + DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_CONCENTRATE_STRAWS; - // Check if the flush UFtime has elapsed - if ( TRUE == didTimeout( stateTimer, FLUSH_UF_WAIT_TIME_MS ) ) + if ( TRUE == didTimeout( stateTimerStart, FLUSH_CONCENTRATE_STRAWS_TIME_MS ) ) { - // set the pumps and valves for the next state, flush R2 to R1 and drain R1 - setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); - setValveState( VRD2, VALVE_STATE_CLOSED ); - setValveState( VRD1, VALVE_STATE_OPEN ); + // Done with flushing the concentrate pumps line + requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); - rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; - rinseCycleCounter = 0; - stateTimer = getMSTimerCount(); - state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_R2_TO_R1_DRAIN_R1; + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); + setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); + setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); + stateTimerStart = getMSTimerCount(); + + rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; + rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; + flushUIState = FLUSH_UI_STATE_FLUSH_RESERVOIRS; + state = DG_FLUSH_STATE_FLUSH_R1_TO_R2; } - + return state; } - /*********************************************************************//** * @brief - * The handleChemicalDisinfectFlushRinseR2ToR1AndDrainR1State function handles - * the chemical disinfect rinse R2 to R1 and drain R1 state. The state - * rinses reservoir 2 and drains reservoir 1 at the same time. If the drain - * process times out, it transitions to basic cancellation state, and - * if the rinse times out, it transitions to water cancellation state. - * If the drain and rinse are completed within the define time, it - * transitions to the next state. - * @details Inputs: rsrvr1Status, rsrvr2Status - * @details Outputs: stateTimer, rsrvr1Status, rsrvr2Status, - * prevChemDisinfectFlushState, alarmDetectedPendingTrigger - * @return next state of the chemical disinfect state machine + * The handleFlushModeFlushR1ToR2State function handles the flush + * reservoir 1 to reservoir 2 state. If any of the reservoirs flush within + * the defined period of time, it transitions to the next state, otherwise, + * it transitions to water cancellation state. If reservoir 2 is filled to + * 500 mL before reservoir 1 is filled, it transitions to water cancellation + * state. + * @details Inputs: rsrvr1Status, rsrvr2Status, stateTimerStart + * @details Outputs: rsrvr1Status, rsrvr2Status, stateTimerStart, + * prevFlushState, alarmDetectedPendingTrigger + * @return next state of the flush state machine *************************************************************************/ -static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushFlushR2ToR1DrainR1State( void ) +static DG_FLUSH_STATE_T handleFlushModeFlushR1ToR2State( void ) { - DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_R2_TO_R1_DRAIN_R1; - static BOOL rsrvr1Empty = FALSE; - static BOOL rsrvr2Full = FALSE; + DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_R1_TO_R2; - if ( FALSE == rsrvr1Empty ) + if ( DG_RESERVOIR_BELOW_TARGET == rsrvr1Status ) { - if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr1Status ) + rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_1, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS ); + + // Keep monitoring the status of reservoir 2 as the same time + rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_PARTIAL_FILL_TIMEOUT_MS ); + // Reservoir 2 cannot be filled before reservoir 1 is filled and is overflowing to reservoir 2. If reservoir 2 has already + // reached to target volume, it means reservoir 1's load cell might be reading incorrect values. This situation might continue + // until reservoir 2 is filled up and the tubing might expand or leak. + if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) { - rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_FLUSH_DRAIN_TIMEOUT_MS ); + prevFlushState = state; + alarmDetectedPendingTrigger = ALARM_ID_DG_INVALID_LOAD_CELL_VALUE; + state = DG_FLUSH_STATE_CANCEL_WATER_PATH; } - if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) - { - // Done with draining R1 - signalDrainPumpHardStop(); - setValveState( VRD1, VALVE_STATE_CLOSED ); - rsrvr1Empty = TRUE; - } - else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) - { - // reservoir 1 drain timeout - prevChemDisinfectFlushState = state; - state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_WATER_PATH; - } } - - if ( FALSE == rsrvr2Full ) + else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) { - // Reservoir 2 must be completely full if ( DG_RESERVOIR_BELOW_TARGET == rsrvr2Status ) { - rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS ); + rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_PARTIAL_FILL_TIMEOUT_MS ); } - if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) + else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) { - rsrvr2Full = TRUE; - stateTimer = getMSTimerCount(); + // Set the actuators to flush R2 and drain R1 state + setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); + setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); + setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); + setValveState( VRD1, VALVE_STATE_OPEN ); + + setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); + stateTimerStart = getMSTimerCount(); + + // Set both reservoirs' status + rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; + rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; + state = DG_FLUSH_STATE_FLUSH_R2_AND_DRAIN_R1; } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { - prevChemDisinfectFlushState = state; - state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_WATER_PATH; + state = DG_FLUSH_STATE_CANCEL_WATER_PATH; } } - - if ( ( TRUE == rsrvr2Full ) && ( TRUE == rsrvr1Empty ) && ( TRUE == didTimeout( stateTimer, FLUSH_ADDITIONAL_TIME_MS ) ) ) + else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { - // Set the valves to flush R1 to R2 and drain R2 - setValveState( VRD2, VALVE_STATE_OPEN ); - setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); - setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); - setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); - - // Turn on the drain pump to drain R2 - setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); - - // Set the reservoir status - rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; - rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_R1_TO_R2_DRAIN_R2; - + state = DG_FLUSH_STATE_CANCEL_WATER_PATH; } + return state; } /*********************************************************************//** * @brief - * The handleChemicalDisinfectFlushRinseR1ToR2AndDrainR2State function handles - * the chemical disinfect flush rinse R1 to R2 and drain R2 state. The state - * rinses reservoir 1 and drains reservoir 2 at the same time. If the drain - * process times out, it transitions to basic cancellation state, and - * if the rinse times out, it transitions to water cancellation state. - * If the drain and rinse are completed within the define time, it - * transitions to the next state. - * @details Inputs: rsrvr1Status, rsrvr2Status, rinseCycleCounter - * @details Outputs: stateTimer, rsrvr1Status, rsrvr2Status, - * prevChemDisinfectFlushState, alarmDetectedPendingTrigger, isThisLastDrain - * numberOfPostDisinfectRinses - * @return next state of the chemical disinfect state machine + * The handleFlushModeFlushR2AndDrainR1State function handles the flush + * reservoir 2 and drain reservoir 1 state. If reservoir 2 flushes within + * the defined period of time and reservoir 1 drains within the defined + * period of time, it transitions to the next state. If the flush times out, + * the function transitions to water cancellation state. If the drain times + * out the function transitions to basic cancellation state. If reservoir 1 + * is filled to 500 mL before reservoir 2 is filled, it transitions to + * water cancellation state. + * @details Inputs: rsrvr1Status, rsrvr2Status, stateTimerStart + * @details Outputs: rsrvr1Status, rsrvr2Status, stateTimerStart, + * prevFlushState, alarmDetectedPendingTrigger, isThisInitialDrain + * @return next state of the flush state machine *************************************************************************/ -static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushFlushR1ToR2DrainR2State( void ) +static DG_FLUSH_STATE_T handleFlushModeFlushR2AndDrainR1State( void ) { - DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_R1_TO_R2_DRAIN_R2; + DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_R2_AND_DRAIN_R1; - static BOOL rsrvr2Empty = FALSE; - static BOOL rsrvr1Full = FALSE; - - if ( FALSE == rsrvr2Empty ) + // If reservoir 1 is empty, turn off the drain pump + if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr1Status ) { - if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr2Status ) - { - rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_FLUSH_DRAIN_TIMEOUT_MS ); - } - if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) - { - // Done with draining R2 - signalDrainPumpHardStop(); - setValveState( VRD2, VALVE_STATE_CLOSED ); - rsrvr2Empty = TRUE; - } - else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) - { - // reservoir 2 drain timeout - prevChemDisinfectFlushState = state; - state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_WATER_PATH; - } + rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_DRAIN_TIMEOUT_MS ); } + else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) + { + // Done with draining R1 + signalDrainPumpHardStop(); + setValveState( VRD1, VALVE_STATE_CLOSED ); + } + // Reservoir 1 drain time out + else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) + { + state = DG_FLUSH_STATE_CANCEL_BASIC_PATH; + } - if ( FALSE == rsrvr1Full ) + // First reservoir 2 must be completely full but if reservoir 1 is filled before reservoir 2 is full, alarm + if ( DG_RESERVOIR_BELOW_TARGET == rsrvr2Status ) { - // Reservoir 1 must be completely full - if ( DG_RESERVOIR_BELOW_TARGET == rsrvr1Status ) + rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS ); + + U32 drainPumpRPM = getDrainPumpTargetRPM(); + // Keep monitoring the status of reservoir 1 as the same time + F32 volume = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); + // Reservoir 1 cannot be filled before reservoir 2 is filled and is overflowing to reservoir 1. If reservoir 1 has already + // reached to target volume, it means reservoir 2's load cell might be reading incorrect values. This situation might continue + // until reservoir 1 is filled up and the tubing might expand or leak. + // Before checking whether reservoir 1 is filled pre-maturely, we have to make sure reservoir 1 is drained completely to make + // sure the extra volume that is read is not because of previous water that is being drained currently and it is above 500 mL + if ( ( volume >= RSRVRS_PARTIAL_FILL_VOL_ML ) && ( 0 == drainPumpRPM ) ) { - rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS ); + prevFlushState = state; + alarmDetectedPendingTrigger = ALARM_ID_DG_INVALID_LOAD_CELL_VALUE; + state = DG_FLUSH_STATE_CANCEL_WATER_PATH; } + } + // Once reservoir 2 is full, reservoir 1 must be partially full + else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) + { + rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_1, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_PARTIAL_FILL_TIMEOUT_MS ); + + // Once R1 is partially full, transition to the next state if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) { - rsrvr1Full = TRUE; - stateTimer = getMSTimerCount(); + signalROPumpHardStop(); + setValveState( VRD1, VALVE_STATE_OPEN ); + setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); + setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); + + // Turn off the UV reactors prior to transitioning to drain states. + // In the drain states, there is not fluid flowing in the RO section so the reactors are turned off + turnOffUVReactor( INLET_UV_REACTOR ); + turnOffUVReactor( OUTLET_UV_REACTOR ); + + // Close VPi and VPd to drain + setValveState(VPI, VALVE_STATE_CLOSED); + setValveState(VPD, VALVE_STATE_DRAIN_C_TO_NO); + // Set VPO + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC); + + stateTimerStart = getMSTimerCount(); + isThisInitialDrain = FALSE; + rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; + flushUIState = FLUSH_UI_STATE_DRAIN_RESERVOIRS; + state = DG_FLUSH_STATE_DRAIN_R1; } - else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) + // Check if reservoir 1 fill timed out + else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { - prevChemDisinfectFlushState = state; - state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_WATER_PATH; + state = DG_FLUSH_STATE_CANCEL_WATER_PATH; } } - - if ( ( TRUE == rsrvr1Full ) && ( TRUE == rsrvr2Empty ) && ( TRUE == didTimeout( stateTimer, FLUSH_ADDITIONAL_TIME_MS ) ) ) + // Check if reservoir 2 fill time out + else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { - ++rinseCycleCounter; - if ( rinseCycleCounter < NUM_OF_RINSE_CYCLES ) - { - // Set the valves to flush R2 to R1 and drain R1 - setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); - setValveState( VRD1, VALVE_STATE_OPEN ); - setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); - setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); - setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); + state = DG_FLUSH_STATE_CANCEL_WATER_PATH; + } - // Turn on the drain pump to drain R2 - setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); + return state; +} - // Set the reservoir status - rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; - rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_R1_TO_R2_DRAIN_R2; - } - else - { - // Set the valves to drain R1 - setValveState( VPI, VALVE_STATE_CLOSED ); - setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); - setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); - setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); - setValveState( VRD1, VALVE_STATE_OPEN ); +/*********************************************************************//** + * @brief + * The handleFlushModeFlushCirculationDrainLineState function handles the + * flush drain line state. Once the drain line was flushed with sufficient + * water, it transitions to the next state. If the line is not drained + * within the defined time, it transitions to water cancellation state. + * @details Inputs: stateTimerStart, flushLinesVolumeL + * @details Outputs: stateTimerStart, flushLinesVolumeL, + * alarmDetectedPendingTrigger + * @return next state of the flush state machine + *************************************************************************/ +static DG_FLUSH_STATE_T handleFlushModeFlushCirculationDrainLineState( void ) +{ + DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_CIRCULATION_DRAIN_LINE; - // Turn on the drain pump to drain R2 - setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); + F32 waterFlowRate = getMeasuredFlowRateLPM( RO_FLOW_SENSOR ); + F32 waterVolume = ( ( waterFlowRate / SEC_PER_MIN ) / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ); - // Turn off CP1 and CP2 - requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); - requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); + // Integrate volume of water moved through line + flushLinesVolumeL += waterVolume; - //Turn off UV reactors - turnOffUVReactor( INLET_UV_REACTOR ); - turnOffUVReactor( OUTLET_UV_REACTOR ); + // When enough water volume has flowed to flush the lines, transition to flush circulation state + if ( flushLinesVolumeL >= FLUSH_DRAIN_LINE_VOLUME_L ) + { + // Set the actuators to transition to flush circulation + // The valves are set to do flush drain and flush circulation + setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState( VRC, VALVE_STATE_RECIRC_C_TO_NC ); + setValveState( VDR, VALVE_STATE_RECIRC_C_TO_NC ); + setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLOW_RATE_LPM, RO_PUMP_MAX_PRESSURE_PSI ); - // Set the reservoir status - rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; + stateTimerStart = getMSTimerCount(); - isThisLastDrain = TRUE; - state = DG_CHEM_DISINFECT_FLUSH_STATE_DISINFECTANT_DRAIN_R1; - } + state = DG_FLUSH_STATE_FLUSH_CIRCULATION; } + else if ( TRUE == didTimeout( stateTimerStart, FLUSH_DRAIN_LINE_TIMEOUT_MS ) ) + { + alarmDetectedPendingTrigger = ALARM_ID_DG_DRAIN_CIRCULATION_LINE_TIMEOUT; + // Could not reach to the defined drain line on time + state = DG_FLUSH_STATE_CANCEL_BASIC_PATH; + } return state; - } /*********************************************************************//** * @brief - * The handleChemicalDisinfectFlushCancelModeBasicPathState function handles the - * chemical disinfect cancel mode basic path state. The state sets the state - * to complete and raises an alarm. - * @details Inputs: none - * @details Outputs: cancellationMode, ChemDisinfectFlushUIState - * @return next state of the heat disinfect state machine + * The handleFlushModeFlushCirculationState function handles the flush + * circulation state. Once the flush circulation time has elapsed, it + * transitions to the next state. + * @details Inputs: stateTimerStart + * @details Outputs: stateTimerStart + * @return next state of the flush state machine *************************************************************************/ -static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushCancelModeBasicPathState( void ) +static DG_FLUSH_STATE_T handleFlushModeFlushCirculationState( void ) { - DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_BASIC_PATH; + DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_CIRCULATION; + if ( TRUE == didTimeout( stateTimerStart, FLUSH_CIRCULATION_WAIT_TIME_MS ) ) + { + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); + setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); - // Set the chemical disinfect that is published on the UI - chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_CANCEL_FLUSH; + stateTimerStart = getMSTimerCount(); - // Set the cancellation mode - cancellationMode = CANCELLATION_MODE_BASIC; + state = DG_FLUSH_STATE_FLUSH_WITH_FRESH_WATER; + } - failChemicalDisinfectFlush(); + return state; +} +/*********************************************************************//** + * @brief + * The handleFlushModeFlushWithFreshWaterState function handles the + * flush with fresh water state. It runs the circulation state with fresh + * water for the defined period of time. + * @details Inputs: stateTimerStart + * @details Outputs: none + * @return next state of the flush state machine + *************************************************************************/ +static DG_FLUSH_STATE_T handleFlushModeFlushWithFreshWaterState( void ) +{ + DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_WITH_FRESH_WATER; + + if ( TRUE == didTimeout( stateTimerStart, FLUSH_WITH_FRESH_WATER_WAIT_TIME_MS ) ) + { + deenergizeActuators(); + flushUIState = FLUSH_UI_STATE_COMPLETE; + state = DG_FLUSH_STATE_COMPLETE; + } + return state; } /*********************************************************************//** * @brief - * The handleChemicalDisinfectFlushCancelModeWaterPathState function handles the - * chemical disinfect flush cancel mode cold water path state. - * @details Inputs: rsrvr1Status, rsrvr2Status, cancellationMode, stateTimer - * @details Outputs: rsrvr1Status, rsrvr2Status, cancellationMode, stateTimer, - * ChemDisinfectFlushUIState - * @return next state of the chemical disinfect state machine + * The handleFlushModeCancelBasicPathState function handles the flush + * 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 flush state machine *************************************************************************/ -static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushCancelModeWaterPathState( void ) +static DG_FLUSH_STATE_T handleFlushModeCancelBasicPathState( void ) { - DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_WATER_PATH; + DG_FLUSH_STATE_T state = DG_FLUSH_STATE_CANCEL_BASIC_PATH; - // Set the chemical disinfect that is published on the UI - chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_CANCEL_FLUSH; + // Once the fault alarm is raised, the DG Software will + // deenergize all the actuators + failFlushMode(); - if ( CANCELLATION_MODE_NONE == cancellationMode ) + flushUIState = FLUSH_UI_STATE_CANCEL_FLUSH; + + return state; +} + +/*********************************************************************//** + * @brief + * The handleFlushModeCancelWaterPathState function handles the flush mode + * cancel water path state. The state drains the 2 reservoirs. If the drain + * times out, it transitions to basic cancellation path. + * @details Inputs: rsrvr1Status, rsrvr2Status, stateTimer, + * hasWaterCancellationBeenSet + * @details Outputs: rsrvr1Status, rsrvr2Status, stateTimer, + * hasWaterCancellationBeenSet + * @return next state of the flush state machine + *************************************************************************/ +static DG_FLUSH_STATE_T handleFlushModeCancelWaterPathState( void ) +{ + DG_FLUSH_STATE_T state = DG_FLUSH_STATE_CANCEL_WATER_PATH; + + if ( FALSE == hasWaterCancellationBeenSet ) { // Stop all the actuators first then decide who should run next deenergizeActuators(); - cancellationMode = CANCELLATION_MODE_WATER; - rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - - // The drain is set to start from reservoir 2 + // Set the actuators + setValveState( VPI, VALVE_STATE_CLOSED ); + setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRD2, VALVE_STATE_OPEN ); + + // Set both reservoirs to be considered as full + rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; + rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; + + // Water cancellation path was set + hasWaterCancellationBeenSet = TRUE; + + // The drain is set to start from reservoir 2 since all the actuators have been de-energized + // Start the drain pump setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); + flushUIState = FLUSH_UI_STATE_CANCEL_FLUSH; + // Start the timer for drain timeout - stateTimer = getMSTimerCount(); + stateTimerStart = getMSTimerCount(); } // If reservoir 2 is empty, set to drain reservoir 1 if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr2Status ) { // If the cancellation water path cannot be done, got to basic cancellation path - rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS ); + rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_DRAIN_TIMEOUT_MS ); if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) { - // Set the drain valve to reservoir 1 setValveState( VRD1, VALVE_STATE_OPEN ); setValveState( VRD2, VALVE_STATE_CLOSED ); } } - // Could not drain reservoir 2. Transition to basic cancellation path else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { - prevChemDisinfectFlushState = state; - state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_BASIC_PATH; + state = DG_FLUSH_STATE_CANCEL_BASIC_PATH; } // If reservoir 2 has already been drained and reservoir 1 is empty, reset and switch to complete if ( ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) && ( DG_RESERVOIR_ABOVE_TARGET == rsrvr1Status ) ) { - // If the cancellation water path cannot be done, got to basic cancellation path - rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_MS ); + // If the cancellation water path cannot be done, go to basic cancellation path + rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_DRAIN_TIMEOUT_MS ); if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) { - failChemicalDisinfectFlush(); + setValveState( VRD2, VALVE_STATE_CLOSED ); + // Done with draining + signalDrainPumpHardStop(); + + // Raise the alarm + failFlushMode(); } - // Could not drain reservoir 1. Transition to basic cancellation path - else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) - { - prevChemDisinfectFlushState = state; - state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_BASIC_PATH; - } } + else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) + { + state = DG_FLUSH_STATE_CANCEL_BASIC_PATH; + } return state; } /*********************************************************************//** * @brief - * The handleChemicalDisinfectFlushCompleteState function handles the chemical - * disinfect complete state. The state stops chemical disinfect and - * requests transition to mode standby. + * The handleFlushModeComplete function handles the complete state. * @details Inputs: none - * @details Outputs: ChemDisinfectFlushUIState - * @return next state of the chemical disinfect state machine + * @details Outputs: none + * @return next state of the flush state machine *************************************************************************/ -static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushCompleteState( void ) +static DG_FLUSH_STATE_T handleFlushModeComplete( void ) { - DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_COMPLETE; + DG_FLUSH_STATE_T state = DG_FLUSH_STATE_COMPLETE; - // Set the chemical disinfect that is published on the UI - chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_COMPLETE; + stopDGFlush(); - stopChemicalDisinfectFlush(); - return state; } /*********************************************************************//** * @brief - * The failChemicalDisinfectFlush function sets the alarm that failed the - * chemical disinfect mode. - * @details Inputs: alarmDetectedPendingTrigger, prevChemDisinfectFlushState + * The failFlushMode function sets the alarm that failed the flush mode. + * @details Inputs: alarm, prevHeatDisinfectState * @details Outputs: none * @return none *************************************************************************/ -static void failChemicalDisinfectFlush( void ) +static void failFlushMode( void ) { - SET_ALARM_WITH_1_U32_DATA( alarmDetectedPendingTrigger, prevChemDisinfectFlushState ) + SET_ALARM_WITH_1_U32_DATA( alarmDetectedPendingTrigger, prevFlushState ) } /*********************************************************************//** * @brief - * The getRsrvrFillStatus function checks whether the target reservoir - * is full or not. If the fill times out, it sets the state machine to - * complete and exits the chemical disinfect mode. - * @details Inputs: rsrvrFillStableTimeCounter, alarm, stateTimer, chemDisinfectFlushState - * @details Outputs: prevChemDisinfectFlushState + * The getRsrvrFillStatus function checks whether the target reservoir is + * full or not. If the fill times out, the function sets the status to did + * not reach to target. + * @details Inputs: rsrvrFillStableTimeCounter, alarm, stateTimer, flushState, + * prevFlushState + * @details Outputs: rsrvrFillStableTimeCounter, alarm, stateTimer * @param r is DG_RESERVOIR_1 or DG_RESERVOIR_2 * @param targetVol is the target fill volume - * @param timeout is the fill up timeout + * @param timeout is the fill up time out that is checked against * @return the status of the reservoirs during filling *************************************************************************/ static DG_RESERVOIR_STATUS_T getRsrvrFillStatus( DG_RESERVOIR_ID_T r, F32 targetVol, U32 timeout ) @@ -948,28 +955,34 @@ { volume = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); } - else - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_DG_RESERVOIR_SELECTED, r ) - } // Check the volume of the reservoir against the target volume if ( volume >= targetVol ) { if ( ++rsrvrFillStableTimeCounter >= RSRVRS_FULL_STABLE_TIME_COUNT ) { - status = DG_RESERVOIR_REACHED_TARGET; + status = DG_RESERVOIR_REACHED_TARGET; rsrvrFillStableTimeCounter = 0; // Set the state timer in case it needs to be used for another timeout check - stateTimer = getMSTimerCount(); + if ( ( DG_FLUSH_STATE_FLUSH_R2_AND_DRAIN_R1 == flushState) && ( DG_RESERVOIR_2 == r) ) + { + if ( rsrvr1Status == DG_RESERVOIR_REACHED_TARGET ) + { + stateTimerStart = getMSTimerCount(); + } + } + else + { + stateTimerStart = getMSTimerCount(); + } } } - else if ( TRUE == didTimeout( stateTimer, timeout ) ) + else if ( TRUE == didTimeout( stateTimerStart, timeout ) ) { - // Failed to fill ontime. Update the previous chemical disinfect state and transition to basic cancellation - prevChemDisinfectFlushState = chemDisinfectFlushState; + // Failed to fill on time + prevFlushState = flushState; alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_FILL_TIMEOUT; - status = DG_RESERVOIR_NOT_REACHED_TARGET; + status = DG_RESERVOIR_NOT_REACHED_TARGET; } return status; @@ -978,10 +991,11 @@ /*********************************************************************//** * @brief * The getRsrvrDrainStatus function returns the status of draining a - * reservoir. - * @details Inputs: stateTimer, chemDisinfectFlushState - * alarm - * @details Outputs: stateTimer, prevChemDisinfectFlushState, alarm + * reservoir. If the drain times out, it set the status to did not reach + * target. + * @details Inputs: rsrvrFillStableTimeCounter, alarm, stateTimer + * @details Outputs: rsrvrFillStableTimeCounter, alarm, stateTimer, + * prevFlushState * @param r is DG_RESERVOIR_1 or DG_RESERVOIR_2 * @param drainSteadyStateTimeout which is the time the reservoir's level * does not change and is steady state @@ -994,7 +1008,7 @@ DG_RESERVOIR_STATUS_T status = DG_RESERVOIR_ABOVE_TARGET; // If the drain parameters of the reservoir is not initialized, initialize them - if ( FALSE == haveDrainParamsBeenInit[ r ] ) + if ( FALSE == haveDrainParamsBeenInit [ r ] ) { initDrainParameters( r ); haveDrainParamsBeenInit[ r ] = TRUE; @@ -1004,162 +1018,84 @@ if ( TRUE == isDrainComplete ) { - // Set the state timer in case it needs to be used for another timeout check - stateTimer = getMSTimerCount(); + if ( ( DG_FLUSH_STATE_FLUSH_R2_AND_DRAIN_R1 == flushState) && ( DG_RESERVOIR_1 == r) ) + { + if ( ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status) && ( 0 == getDrainPumpTargetRPM() ) ) + { + stateTimerStart = getMSTimerCount(); + } + } + else + { + stateTimerStart = getMSTimerCount(); + } + haveDrainParamsBeenInit[ r ] = FALSE; - status = DG_RESERVOIR_REACHED_TARGET; + status = DG_RESERVOIR_REACHED_TARGET; } - else if ( TRUE == didTimeout( stateTimer, timeout ) ) + else if ( TRUE == didTimeout( stateTimerStart, timeout ) ) { - // Failed to drain on time. Update the previous chemical disinfect state - prevChemDisinfectFlushState = chemDisinfectFlushState; - haveDrainParamsBeenInit[ r ] = FALSE; - alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_DRAIN_TIMEOUT; - status = DG_RESERVOIR_NOT_REACHED_TARGET; + // Failed to drain on time + prevFlushState = flushState; + haveDrainParamsBeenInit [ r ] = FALSE; + alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_DRAIN_TIMEOUT; + status = DG_RESERVOIR_NOT_REACHED_TARGET; } return status; } - /*********************************************************************//** * @brief - * The publishChemicalDisinfectFlushData function publishes chemical disinfect - * flush data at the set interval. + * The publishFlushData function publishes the flush mode data at the set + * interval. * @details Inputs: dataPublishCounter * @details Outputs: dataPublishCounter * @return: none *************************************************************************/ - -static void publishChemicalDisinfectFlushData( void ) +static void publishFlushData( void ) { - - - if ( ++dataPublishCounter >= CHEM_DISINFECT_FLUSH_DATA_PUB_INTERVAL ) + if ( ++dataPublishCounter >= FLUSH_DATA_PUB_INTERVAL ) { - MODE_FLUSH_DATA_T data; - data.flushState = (U32)chemDisinfectFlushState; - data.overallElapsedTime = calcTimeSince( overallChemDisinfectFlushTimerStart ); - data.stateElapsedTime = calcTimeSince( stateTimer ); - data.drainLineVolume = 0; - data.flushUIState = (U32)chemDisinfectFlushUIState; + data.flushState = (U32)flushState; + data.overallElapsedTime = calcTimeSince( overallFlushElapsedTimeStart ); + data.stateElapsedTime = calcTimeSince( stateTimerStart ); + data.drainLineVolume = flushLinesVolumeL; + data.flushUIState = (U32)flushUIState; broadcastData( MSG_ID_DG_FLUSH_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( MODE_FLUSH_DATA_T ) ); dataPublishCounter = 0; } - /* - MODE_CHEMICAL_DISINFECT_FLUSH_DATA_T data; - MODE_CHEMICAL_DISINFECT_UI_DATA_T uiData; - - data.chemDisinfectFlushState = (U32)chemDisinfectFlushState; - data.stateElapsedTime = calcTimeSince( stateTimer ); - data.overallElapsedTime = calcTimeSince( overallChemDisinfectFlushTimer ); - data.cancellationMode = (U32)cancellationMode; - - // General data publish channel - broadcastData( MSG_ID_DG_CHEM_DISINFECT_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( MODE_CHEMICAL_DISINFECT_FLUSH_DATA_T ) ); - - // Publish data to UI - broadcastData( MSG_ID_DG_CHEM_DISINFECT_TIME_DATA, COMM_BUFFER_OUT_CAN_DG_2_UI, (U08*)&uiData, sizeof( MODE_CHEMICAL_DISINFECT_FLUSH_UI_DATA_T ) ); - - dataPublishCounter = 0; - }*/ } - /*********************************************************************//** * @brief - * The monitorModeChemicalDisinfectFlush 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. It also monitors inlet water conditions. - * @details Inputs: chemDisinfectState - * @details Outputs: prevChemDisinfectFlushState, chemDisinfectState, - * alarmDetectedPendingTrigger + * The monitorModeFlush 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: prevFlushState, flushState, alarmDetectedPendingTrigger * @return: none *************************************************************************/ -static void monitorModeChemicalDisinfectFlush( void ) +static void monitorModeFlush( void ) { - BOOL hasConductivityFailed = TRUE; - #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_CAPS_MONITOR ) != SW_CONFIG_ENABLE_VALUE ) #endif { - // If either the dialysate cap or the concentrate cap is open during any state, alarm 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 ConcCap = (U32)getSwitchStatus( CONCENTRATE_CAP ); - U32 DialysateCap = (U32)getSwitchStatus( DIALYSATE_CAP ); - prevChemDisinfectFlushState = chemDisinfectFlushState; - chemDisinfectFlushState = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_WATER_PATH; + U32 cap = (U32)( STATE_OPEN == getSwitchStatus( CONCENTRATE_CAP ) ? CONCENTRATE_CAP : DIALYSATE_CAP ); + prevFlushState = flushState; + flushState = DG_FLUSH_STATE_CANCEL_WATER_PATH; alarmDetectedPendingTrigger = ALARM_ID_DG_DIALYSATE_OR_CONC_CAP_NOT_IN_PROPER_POSITION; } } - - // In all states, check inlet temperature, inlet pressure, and inlet conductivity. - haveInletWaterChecksPassed= TRUE; - hasConductivityFailed = ( ( getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ) >= MAX_INLET_CONDUCTIVITY_US_PER_CM ) || - ( getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ) <= MIN_INLET_CONDUCTIVITY_US_PER_CM ) ); -#ifndef _RELEASE_ - if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_DISINFECT_CONDUCTIVITY_CHECK ) ) - { - hasConductivityFailed = FALSE; - } -#endif - if ( getTemperatureValue( TEMPSENSORS_INLET_PRIMARY_HEATER ) < MIN_INLET_TEMPERATURE_C || - hasConductivityFailed || - getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_INLET ) < MIN_INLET_PRESSURE_PSI) - { - // Inlet check failed, alarm unless in the start, drain, or flush drain states - haveInletWaterChecksPassed= FALSE; // set flag for flush drain state - switch( chemDisinfectFlushState ) - { - case DG_CHEM_DISINFECT_FLUSH_STATE_START: - case DG_CHEM_DISINFECT_FLUSH_STATE_DISINFECTANT_DRAIN_R1: - case DG_CHEM_DISINFECT_FLUSH_STATE_DISINFECTANT_DRAIN_R2: - case DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_DRAIN: - break; - - case DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_DISINFECTANT_LINE: - case DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_UF: - case DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_R2_TO_R1_DRAIN_R1: - case DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_R1_TO_R2_DRAIN_R2: - prevChemDisinfectFlushState = chemDisinfectFlushState; - alarmDetectedPendingTrigger = ALARM_ID_INLET_WATER_TEMPERATURE_IN_LOW_RANGE; //ALARM_ID_NEW_WAT; - chemDisinfectFlushState = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_WATER_PATH; - break; - } - } - - } - -/*********************************************************************//** - * @brief - * The writeDisinfectDataToNV function writes the disinfection data to the - * non-volatile memory. - * @details Inputs: disinfectNVOps - * @details Outputs: disinfectNVOps - * @return: none - *************************************************************************/ -static void writeDisinfectDataToNV( void ) -{ - ; ///< Boolean flag to indicate whether the disinfect flush status been written to NV or not. - BOOL ; - if ( FALSE == disinfectFlushNVOps.hasDisFlushCompleteDateBeenWrittenToNV ) - { - disinfectFlushNVOps.hasDisFlushCompleteDateBeenWrittenToNV = setDisinfectStatus( TRUE ); - } - - if ( FALSE == disinfectFlushNVOps.hasDisFlushStatusBeenWrittenToNV ) - { - disinfectFlushNVOps.hasDisFlushStatusBeenWrittenToNV = setLastDisinfectDate( USAGE_INFO_CHEMICAL_DISINFECT, getRTCTimestamp() ); - } } /**@}*/