Index: firmware/App/Modes/ModeChemicalDisinfect.c =================================================================== diff -u -rd8686d68bf29761ee329fc638264d2e60a5191c0 -re82ddb85a3b3a1fc5d591d8cca0d006597fd94cf --- firmware/App/Modes/ModeChemicalDisinfect.c (.../ModeChemicalDisinfect.c) (revision d8686d68bf29761ee329fc638264d2e60a5191c0) +++ firmware/App/Modes/ModeChemicalDisinfect.c (.../ModeChemicalDisinfect.c) (revision e82ddb85a3b3a1fc5d591d8cca0d006597fd94cf) @@ -48,7 +48,7 @@ // ********** private definitions ********** // General defines -#define MAX_ALLOWED_STATE_TRIALS 1 ///< Max allowed trials on a state. This is general among all the states. +#define MAX_ALLOWED_STATE_TRIALS 1 ///< Max allowed trials on a state. This is general among all the states. TODO: not used #define CHEM_DISINFECT_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Mode chem disinfect data publish interval in counts. // Start state defines @@ -59,83 +59,77 @@ #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 ( 30 * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. +#define FLUSH_DRAIN_WAIT_TIME_MS ( 30 * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. #define MIN_INLET_TEMPERATURE_C 20.0F ///< Minimum water inlet temperature in C. TODO: set to 24.0 #define MAX_INLET_TEMPERATURE_C 35.0F ///< Maximum water inlet temperature in C. #define MAX_INLET_CONDUCTIVITY_US_PER_CM 2000.0F ///< Maximum water inlet conductivity in us/cm -#define MIN_INLET_CONDUCTIVITY_US_PER_CM 0.0F ///< Minimum water inlet conductivity in us/cm +#define MIN_INLET_CONDUCTIVITY_US_PER_CM 0.0F ///< Minimum water inlet conductivity in us/cm #define MAX_ALLOWED_FLUSH_DRAIN_PERIODS 2 ///< Number of flush drain periods to wait for inlet water to come into range #define INLET_WATER_CHECK_FAILURE_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Timer for inlet water check failures before alarm + // Flush circulation path state defines #define RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM 0.5F ///< 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. #define FLUSH_CICRCULATION_ADDITIONAL_WAIT_TIME_MS ( 60 * MS_PER_SECOND ) ///< Flush/rinse circulation path additional wait time in milliseconds. #define MAX_FLUSH_CIRC_TEMP_SENSOR_DIFF_C 3.0F ///< Maximum flush circulation temperature difference tolerance in C. #define NUM_OF_TEMP_SENSORS_TO_AVG 2.0F ///< Number of temperature sensors to average to check the difference. -#define MAX_FLUSH_CIRC_CONDUCTIVITY_US_PER_CM 1000.0F ///< Maximum allowed conductivity in flush circulation state in us/cm TODO: set to 100.0 +#define MAX_FLUSH_CIRC_CONDUCTIVITY_US_PER_CM 1000.0F ///< Maximum allowed conductivity in flush circulation state in us/cm TODO: set to 100.0 #define MAX_ALLOWED_FLUSH_CIRC_PERIODS 3 ///< Number of flush circulation periods to wait for sensors to come into range -// 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_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 ( 6 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 full fill up timeout in ms. -#define RSRVRS_BOTH_FILL_UP_TIMEOUT_MS ( 12 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 partial fill up timeout in ms. -#define RSRVRS_PARTIAL_FILL_UP_TIMEOUT_MS ( 5 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 partial fill up timeout in ms. -#define RSRVRS_INITIAL_DRAIN_TIME_OUT_MS ( 3 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 initial drain time out in milliseconds. -#define RSRVRS_DRAIN_TIMEOUT_MS ( 3 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 drain timeout in ms. - -// R1 to R2 & R2 to R1 chemical disinfect circulation +// RO pump speed and pressure during entire disinfect cycle #define CHEM_DISINFECT_TARGET_RO_FLOW_LPM 0.5F ///< Chemical disinfect target RO flow rate in L/min. #define CHEM_DISINFECT_MAX_RO_PRESSURE_PSI 130 ///< Chemical disinfect maximum RO pressure in psi. -#define CHEM_DISINFECT_TIME_MS ( 7 * SEC_PER_MIN * MS_PER_SECOND ) ///< Chemical disinfect time for each section in milliseconds. TODO original time was 36 minutes -#define CHEM_DISINFECT_START_TEMP_TIMEOUT_MS ( 6 * SEC_PER_MIN * MS_PER_SECOND ) ///< Chemical disinfect reaching to minimum temperature timeout in milliseconds. -#define DRAIN_PUMP_VOLUME_CONTROL_RPM 1200 -#define RSRVR_DRAIN_CONTROL_MIN_VOLUME 1600.0F -#define RSRVR_DRAIN_CONTROL_MAX_VOLUME 1750.0F - -#define DRP_VOLUME_CONTROL_TARGET_VOLUME_ML 1000.0F -#define DRP_VOLUME_CONTROL_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) -#define DRP_VOLUME_CONTROL_P_COEFFICIENT -0.5F ///< P term for dialIn pump control. -#define DRP_VOLUME_CONTROL_I_COEFFICIENT 0.0F ///< P term for dialIn pump control. -#define MIN_DRP_VOLUME_CONTROL_RPM 200.0F -#define MAX_DRP_VOLUME_CONTROL_RPM 1500.0F - -// the next 4 not currently used -//#define CHEM_DISINFECT_TARGET_DRAIN_PRES_PSI 12.0 ///< Chemical disinfect target drain outlet pressure in psi. -#define RSRVRS_TARGET_VOL_OUT_TIMEOUT_MS ( 0.5F * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 maximum volume out of range timeout during chemical disinfect. TODO change this to 5 seconds -#define RSRVRS_MAX_TARGET_VOL_CHANGE_ML 600.0F ///< Reservoirs 1 & 2 maximum allowed volume change when full during chemical disinfect. TODO original value is 100 mL -#define POST_CHEM_DISINFECT_WAIT_TIME_MS ( 1 * SEC_PER_MIN * MS_PER_SECOND ) ///< Chemical disinfect final wait time before flushing the system in milliseconds. - // Prime acid line #define PRIME_ACID_LINE_TIMEOUT_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Priming acid line timeout in milliseconds. #define DISINFECTANT_PUMP_PRIME_SPEED_ML_PER_MIN 19.0F ///< Disinfectant pump prime speed in ml/min. -#define MIN_PRIME_ACID_CONDUCTIVITY_US_PER_CM 2.0F ///< Minimum conductivity that indicates acid is in the line in uS/cm. TODO: set to 600.0 +#define MIN_PRIME_ACID_CONDUCTIVITY_US_PER_CM 2.0F ///< Minimum conductivity that indicates acid is in the line in uS/cm. TODO: set to 600.0 #define PRIME_ACID_STEADY_CONDUCTIVITY_TIME_MS ( ( 10 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Minimum time that a steady conductivity of acid must be read in milliseconds. TODO: set to 10 sec #define RO_PUMP_TARGET_PRIME_DISINECTANT_FLOW_RATE_LPM 0.8F ///< ROP flow rate for disinfectant prime #define MAX_RO_PUMP_PRIME_DISINFECTANT_PRESSURE_PSI 130.0F ///< ROP max pressure for disinfectant prime -// Fill with disinfectant and water +// Stabilize disinfectant mixing and begin to fill tanks with disinfectant #define MAX_ALLOWED_DISINFECTANT_FLUSH_PERIODS 2 -#define MIN_RO_FLOW_FOR_CONC_PUMP_MIXING_LPM 0.3F ///< Minimum RO flow rate that is need to be able to turn on the concentrate pump for mixing. +#define MIN_RO_FLOW_FOR_CONC_PUMP_MIXING_LPM 0.3F ///< Minimum RO flow rate that is need to be able to turn on the concentrate pump for mixing. #define DISINFECTANT_PUMP_FILL_SPEED_ML_PER_MIN 7.5F ///< Disinfectant pump fill speed in ml/min. #define RO_PUMP_TARGET_FILL_DISINECTANT_FLOW_RATE_LPM 0.5F ///< ROP flow rate for disinfectant prime #define MAX_RO_PUMP_FILL_DISINFECTANT_PRESSURE_PSI 130.0F ///< ROP max pressure for disinfectant fill #define FLUSH_DISINFECTANT_INITIAL_WAIT_TIME ( 30 * MS_PER_SECOND ) ///< Initial time to wait for temperature and conductivity to reach target in disinfectant flush state -#define FLUSH_DISINFECTANT_ADDITIONAL_WAIT_TIME ( 60 * MS_PER_SECOND ) ///< Additional time to wait for temperature and conductivity to reach target in disinfectant flush state -#define MAX_DISINFECT_FLUSH_CYCLE_PERIODS 2 ///< Number of allowed periods to check conductivity and temperature in disinfectant flush state -#define MIN_DISINFECT_CONDUCTIVITY_US_PER_CM 5.0F ///< Minimum conductivity for mixed disinfect fluid in us/cm TODO: set to 150.0 -#define MAX_DISINFECT_CONDUCTIVITY_US_PER_CM 5000.0F ///< Minimum conductivity for mixed disinfect fluid in us/cm TODO: set to 650.0 +#define FLUSH_DISINFECTANT_ADDITIONAL_WAIT_TIME ( 60 * MS_PER_SECOND ) ///< Additional time to wait for temperature and conductivity to reach target in disinfectant flush state +#define MAX_DISINFECT_FLUSH_CYCLE_PERIODS 2 ///< Number of allowed periods to check conductivity and temperature in disinfectant flush state + +// Contuctivity and temperature absolute limits during disinfection +#define MIN_DISINFECT_CONDUCTIVITY_US_PER_CM 5.0F ///< Minimum conductivity for mixed disinfect fluid in us/cm TODO: set to 150.0 +#define MAX_DISINFECT_CONDUCTIVITY_US_PER_CM 5000.0F ///< Minimum conductivity for mixed disinfect fluid in us/cm TODO: set to 650.0 #define MIN_DISINFECT_TD2_TEMPERATURE_C 25.0F ///< Minimum temperature for mixed disinfect fluid at outlet of heater in dec C TODO: set to 35.0 #define MAX_DISINFECT_TD2_TEMPERATURE_C 45.0F ///< Maximum temperature for mixed disinfect fluid at outlet of heater in dec C TODO: set to 45.0 -// Fill heat up -#define CHEM_DISINFECT_TARGET_TEMPERATURE_C 30.0F ///< Chemical disinfect target water temperature in C. // TODO this used to 30.0 -#define CHEM_DISINFECT_HEATER_CONTROL_TEMPERATURE_C 40.0F ///< Chemical disinfect heater control water temperature in C. // TODO this used to 30.0 -#define DISINFECT_CYCLE_PERIOD_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Time for disinfectant filling and partial draining cycle -static const F32 ACID_TO_WATER_MIXING_RATIO = ( 1.0F / 70.0F ); ///< Acid to water mixing ratio for chemical disinfect. +// Initial disinfectant fill of R1 and R2 +#define RSRVRS_FULL_VOL_ML 1500.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 ( 6 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 full fill up timeout in ms. +#define RSRVRS_BOTH_FILL_UP_TIMEOUT_MS ( 12 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 partial fill up timeout in ms. +#define RSRVRS_PARTIAL_FILL_UP_TIMEOUT_MS ( 5 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 partial fill up timeout in ms. +#define RSRVRS_INITIAL_DRAIN_TIME_OUT_MS ( 3 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 initial drain time out in milliseconds. +#define RSRVRS_DRAIN_TIMEOUT_MS ( 3 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 drain timeout in ms. + +// Parameters controlling chemical disinfect +#define CHEM_DISINFECT_TIME_MS ( 12 * SEC_PER_MIN * MS_PER_SECOND ) ///< Chemical disinfect time in ms. +#define CHEM_DISINFECT_START_TEMP_TIMEOUT_MS ( 6 * SEC_PER_MIN * MS_PER_SECOND ) ///< Chemical disinfect reaching to minimum temperature timeout in milliseconds. +#define CHEM_DISINFECT_TARGET_TEMPERATURE_C 28.0F ///< Chemical disinfect target water temperature in C. // TODO this has not been decided +#define CHEM_DISINFECT_HEATER_CONTROL_TEMPERATURE_C 40.0F ///< Chemical disinfect heater control water temperature in C. // TODO this used to 30.0 +#define DISINFECT_CYCLE_PERIOD_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Time for each disinfectant filling and partial draining cycle + +// A PI control loop is used control the DRP speed while the tank is filling and draining, to maintain a constant level of disinfectant in the tank +#define DRP_VOLUME_CONTROL_TARGET_VOLUME_ML 1500.0F ///< Tank level to maintain using DRP volume control +#define DRP_VOLUME_CONTROL_INTERVAL_MS ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Update rate for DRP volume control in ms. +#define DRP_VOLUME_CONTROL_P_COEFFICIENT -0.8F ///< P term for DRP volume control. +#define DRP_VOLUME_CONTROL_I_COEFFICIENT 0.02F ///< I term for DRP volume control. +#define MIN_DRP_VOLUME_CONTROL_RPM 350.0F ///< Minimum DRP RPM for volume control. The minimum value allowed by the pump driver is 300 RPM +#define MAX_DRP_VOLUME_CONTROL_RPM 1500.0F ///< Maximum DRP RPM for volume control. The maximum recommended value is 2400 RPM + /// Cancellation paths typedef enum Cancellation_modes { @@ -193,7 +187,6 @@ 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 U32 flushCircWaitTime; ///< Variable time period to wait in flush circulation state to check sensor values static U32 flushDisinfectantWaitTime; ///< Variable time period to wait in disinfectant flush state to check sensor values static U32 primeAcidSteadyStateCounter = 0; ///< Prime acid steady state counter. @@ -215,6 +208,7 @@ static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectCancelModeBasicPathState(void); static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectCancelModeWaterPathState(void); static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectCompleteState(void); + static void failChemicalDisinfect( 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 ); @@ -464,15 +458,16 @@ } else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) { - // Assume reservoir 2 is full and drain it - rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - tareLoadCell( LOAD_CELL_RESERVOIR_1_PRIMARY ); tareLoadCell( LOAD_CELL_RESERVOIR_1_BACKUP ); // Done with draining R1 setValveState( VRD1, VALVE_STATE_CLOSED ); setValveState( VRD2, VALVE_STATE_OPEN ); + + // Assume reservoir 2 is full and drain it + rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; + state = DG_CHEM_DISINFECT_STATE_DRAIN_R2; } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) @@ -511,7 +506,7 @@ { // Set the chemical disinfect that is published on the UI // This is the final drain of chemical disinfect - chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_FLUSH_AFTER_DISINFECT; // ??? this may not be correct + chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_FLUSH_AFTER_DISINFECT; // ??? this may not be correct setValveState( VRD2, VALVE_STATE_CLOSED ); setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); state = DG_CHEM_DISINFECT_STATE_COMPLETE; @@ -564,7 +559,7 @@ { if ( TRUE == haveInletWaterChecksPassed ) { - // set pumps and valves for next state, flush disinfectant line + // 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 ); @@ -586,14 +581,14 @@ // 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; + //alarmDetectedPendingTrigger = ALARM_ID_DG_HEAT_DISINFECT_INLET_COND_AND_TEMP_OUT; // Do we need an alarm like this? + alarmDetectedPendingTrigger = ALARM_ID_INLET_WATER_TEMPERATURE_IN_LOW_RANGE; // Or a generic alarm? ALARM_ID_DG_NEW_WAT; prevChemDisinfectState = state; state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; } } } - return state; } @@ -634,26 +629,26 @@ if( ( TRUE == isTPoOut ) || ( TRUE == isTD2Out ) || ( TRUE == isCD2Out ) || ( TRUE == isCPoOut) ) { // Check if we have exceeded the number of trials. If not, try another time - ++stateTrialCounter; + ++stateTrialCounter; if ( stateTrialCounter < MAX_ALLOWED_FLUSH_CIRC_PERIODS ) { stateTimer = getMSTimerCount(); flushCircWaitTime = FLUSH_CICRCULATION_ADDITIONAL_WAIT_TIME_MS; } - // State failed. Cancel chemical disinfect mode - else - // determine which alarm it is, temperature or conductivity, one of them has to take precedence + + else // State failed. Cancel chemical disinfect mode + // determine which alarm it is, temperature or conductivity, one of them has to take precedence { - if ( ( TRUE == isTPoOut ) || ( TRUE == isTD2Out ) ) - { + if ( ( TRUE == isTPoOut ) || ( TRUE == isTD2Out ) ) + { alarmDetectedPendingTrigger = ALARM_ID_DG_TEMP_SENSORS_DIFF_OUT_OF_RANGE; - } - else - { + } + else + { alarmDetectedPendingTrigger = ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_HIGH_RANGE; //ALARM_ID_DG_NEW_CON; - } - prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; + } + prevChemDisinfectState = state; + state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; } } else @@ -665,8 +660,6 @@ requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); state = DG_CHEM_DISINFECT_STATE_PRIME_DISINFECTANT; stateTimer = getMSTimerCount(); - - } } @@ -691,42 +684,39 @@ DG_CHEM_DISINFECT_STATE_T state = DG_CHEM_DISINFECT_STATE_PRIME_DISINFECTANT; F32 cd2Conductivity = getConductivityValue( (U32)CONDUCTIVITYSENSORS_CD2_SENSOR ); - // Set the chemical disinfect that is published on the UI + // Set the chemical disinfect state that is published on the UI chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_MIX_WATER_AND_ACID; if ( cd2Conductivity <= MIN_PRIME_ACID_CONDUCTIVITY_US_PER_CM ) { primeAcidSteadyStateCounter = 0; } - else + // Check if the acid conductivity value has been above the threshold for the specified time period + else if ( ++primeAcidSteadyStateCounter >= PRIME_ACID_STEADY_CONDUCTIVITY_TIME_MS ) { - // Check if the acid conductivity value has been above the threshold for the specified time period - if ( ++primeAcidSteadyStateCounter >= PRIME_ACID_STEADY_CONDUCTIVITY_TIME_MS ) - { - // Turn off the concentrate pump - requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); + // Turn off the concentrate pump + requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); - // Prepare for filling the reservoirs and heating the water + // Prepare for filling the reservoirs and heating the water - setValveState( VRD1, VALVE_STATE_CLOSED ); - setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); - setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); + setValveState( VRD1, VALVE_STATE_CLOSED ); + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); + setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); - // Turn on the RO pump and concentrate pump - setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FILL_DISINECTANT_FLOW_RATE_LPM, MAX_RO_PUMP_FILL_DISINFECTANT_PRESSURE_PSI ); - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, DISINFECTANT_PUMP_FILL_SPEED_ML_PER_MIN ); - requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); + // Turn on the RO pump and concentrate pump + setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FILL_DISINECTANT_FLOW_RATE_LPM, MAX_RO_PUMP_FILL_DISINFECTANT_PRESSURE_PSI ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, DISINFECTANT_PUMP_FILL_SPEED_ML_PER_MIN ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); - // Start heating the water while we are filling up the reservoirs - setHeaterTargetTemperature( DG_PRIMARY_HEATER, CHEM_DISINFECT_HEATER_CONTROL_TEMPERATURE_C ); - startHeater( DG_PRIMARY_HEATER ); + // Start heating the water while we are filling up the reservoirs + setHeaterTargetTemperature( DG_PRIMARY_HEATER, CHEM_DISINFECT_HEATER_CONTROL_TEMPERATURE_C ); + startHeater( DG_PRIMARY_HEATER ); - flushDisinfectantWaitTime = FLUSH_DISINFECTANT_INITIAL_WAIT_TIME; - stateTrialCounter = 0; - state = DG_CHEM_DISINFECT_STATE_DISINFECTANT_FLUSH; - stateTimer = getMSTimerCount(); - } + flushDisinfectantWaitTime = FLUSH_DISINFECTANT_INITIAL_WAIT_TIME; + stateTrialCounter = 0; + state = DG_CHEM_DISINFECT_STATE_DISINFECTANT_FLUSH; + stateTimer = getMSTimerCount(); } if ( TRUE == didTimeout( stateTimer, PRIME_ACID_LINE_TIMEOUT_MS ) ) @@ -739,7 +729,6 @@ return state; } - /*********************************************************************//** * @brief * The handleChemicalDisinfectPrimeAcidLineState function handles the @@ -783,8 +772,6 @@ else { // No changes in valves and pumps for next state - //setValveState( VRD1, VALVE_STATE_OPEN ); // for testing, may prevent tubing breaks, TODO: remove - //setValveState( VRD2, VALVE_STATE_OPEN ); // for testing, may prevent tubing breaks, TODO: remove rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; stateTimer = getMSTimerCount(); @@ -813,13 +800,13 @@ { DG_CHEM_DISINFECT_STATE_T state = DG_CHEM_DISINFECT_STATE_FILL_WITH_DISINFECTANT; // First reservoir 1 must be full -// if ( DG_RESERVOIR_BELOW_TARGET == rsrvr1Status ) -// { -// rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_1, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS ); -// } + if ( DG_RESERVOIR_BELOW_TARGET == rsrvr1Status ) + { + rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_1, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS ); + } // Once reservoir 1 is full, check the status of reservoir 2 since the water overflows to reservoir 2 -// else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) -// { + else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) + { rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_FULL_VOL_ML, RSRVRS_BOTH_FILL_UP_TIMEOUT_MS ); // If R1 is not full, keep monitoring for R1 level and timeout @@ -836,31 +823,33 @@ // Set both reservoirs status rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - // Set the drain pump to control mode TODO: change to volume control mode - //setDrainPumpTargetOutletPressure( CHEM_DISINFECT_TARGET_DRAIN_PRES_PSI ); + // Set the drain pump to control mode controlDRPByReservoirVolume( DG_RESERVOIR_1, TRUE ); //Initialize the PI controller for DRP + /* ??? I am not sure whether we should monitor the reservoir volumes for leaks // Get the current volumes of R1 & R2. These values will be used to make sure the reservoirs' // volume does not change more than a certain amount during the actual chemical disinfect cycle + rsrvrsVolMonitorTimer = getMSTimerCount(); + */ R1ChemDisinfectVol = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); R2ChemDisinfectVol = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); chemDisinfectWarmupTimer = getMSTimerCount(); isPartialDisinfectInProgress = FALSE; stateTimer = getMSTimerCount(); - rsrvrsVolMonitorTimer = getMSTimerCount(); + state = DG_CHEM_DISINFECT_STATE_R2_DISINFECTANT_FILL_R1_DRAIN; } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { prevChemDisinfectState = state; state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } -// } -// else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) -// { -// prevChemDisinfectState = state; -// state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; -// } + } + else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) + { + prevChemDisinfectState = state; + state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; + } return state; } @@ -1207,20 +1196,32 @@ return status; } + +/*********************************************************************//** + * @brief + * The controlDRPByReservoirVolume function implements the volume control of the + * drain pump to maintain a specified volume in one of the reservoirs. + * @details Inputs: stateTimer, reservoir, initialize flag, control volume, + * tank volume, PI coefficients, min and max drain pump control RPM + * @details Outputs: stateTimer, chemDisinfectState, alarm + * @param r is DG_RESERVOIR_1 or DG_RESERVOIR_2 + * @param initialize determines whether the function initializes the controller or + * runs it + *************************************************************************/ static void controlDRPByReservoirVolume( DG_RESERVOIR_ID_T r, BOOL initialize ) { if ( TRUE == initialize ) { - // Initialize dialysate inlet flow PI controller + // Initialize drain pump volume control PI controller initializePIController( PI_CONTROLLER_ID_DRAIN_PUMP_VOLUME, MIN_DRP_VOLUME_CONTROL_RPM, DRP_VOLUME_CONTROL_P_COEFFICIENT, DRP_VOLUME_CONTROL_I_COEFFICIENT, MIN_DRP_VOLUME_CONTROL_RPM, MAX_DRP_VOLUME_CONTROL_RPM ); drpControlTimerCounter = getMSTimerCount(); resetPIController( PI_CONTROLLER_ID_DRAIN_PUMP_VOLUME, MIN_DRP_VOLUME_CONTROL_RPM ); setDrainPumpTargetRPM( MIN_DRP_VOLUME_CONTROL_RPM ); } - else if ( TRUE == didTimeout( drpControlTimerCounter, DRP_VOLUME_CONTROL_INTERVAL ) ) + else if ( TRUE == didTimeout( drpControlTimerCounter, DRP_VOLUME_CONTROL_INTERVAL_MS ) ) { // Control at set interval F32 tgtVolume = (F32)DRP_VOLUME_CONTROL_TARGET_VOLUME_ML; F32 actVolume; @@ -1235,37 +1236,13 @@ } else { - actVolume = tgtVolume + 500.0; - //SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_DG_RESERVOIR_SELECTED, r ) + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_DG_RESERVOIR_SELECTED, r ) } newRPM = runPIController( PI_CONTROLLER_ID_DRAIN_PUMP_VOLUME, tgtVolume, actVolume ); setDrainPumpTargetRPM( newRPM ); drpControlTimerCounter = getMSTimerCount(); } - - - -/* - if ( volume > RSRVR_DRAIN_CONTROL_MAX_VOLUME ) - { - // If volume is above target, turn pump on. - setDrainPumpTargetRPM( DRAIN_PUMP_VOLUME_CONTROL_RPM ); - } - else if ( volume < RSRVR_DRAIN_CONTROL_MIN_VOLUME ) - { - //if volume is below target, turn pump off. - signalDrainPumpHardStop(); - } - // TODO: somehow prevent both reservoirs from being full at the same time - //if ( volume > RSRVR_DRAIN_CONTROL_MAX_VOLUME ) - //{ - // //there is a problem with draining, alarm - // prevChemDisinfectState = chemDisinfectState; - // alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_DRAIN_TIMEOUT; //TODO: get correct alarm - // failChemicalDisinfect(); //TODO: fail in the correct way - //} -*/ } /*********************************************************************//** @@ -1284,14 +1261,16 @@ CHEM_DISINFECT_STATUS_T status = CHEM_DISINFECT_IN_PROGRESS; // Update the variables - F32 TdiTemp = getTemperatureValue( TEMPSENSORS_INLET_DIALYSATE ); - BOOL isR1OutOfRange = fabs( getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ) - R1ChemDisinfectVol ) > RSRVRS_MAX_TARGET_VOL_CHANGE_ML; - BOOL isR2OutOfRange = fabs( getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ) - R2ChemDisinfectVol ) > RSRVRS_MAX_TARGET_VOL_CHANGE_ML; - F32 cd2Conductivity = getConductivityValue( (U32)CONDUCTIVITYSENSORS_CD2_SENSOR ); - F32 TD2Temp = getTemperatureValue( TEMPSENSORS_CONDUCTIVITY_SENSOR_2 ); - BOOL isCD2OutofRange = ( cd2Conductivity < MIN_DISINFECT_CONDUCTIVITY_US_PER_CM || cd2Conductivity > MAX_DISINFECT_CONDUCTIVITY_US_PER_CM ); - BOOL isTD2OutofRange = ( TD2Temp < MIN_DISINFECT_TD2_TEMPERATURE_C || TD2Temp > MAX_DISINFECT_TD2_TEMPERATURE_C ); - /* + F32 TdiTemp = getTemperatureValue( TEMPSENSORS_INLET_DIALYSATE ); + + F32 cd2Conductivity = getConductivityValue( (U32)CONDUCTIVITYSENSORS_CD2_SENSOR ); + F32 TD2Temp = getTemperatureValue( TEMPSENSORS_CONDUCTIVITY_SENSOR_2 ); + BOOL isCD2OutofRange = ( cd2Conductivity < MIN_DISINFECT_CONDUCTIVITY_US_PER_CM || cd2Conductivity > MAX_DISINFECT_CONDUCTIVITY_US_PER_CM ); + BOOL isTD2OutofRange = ( TD2Temp < MIN_DISINFECT_TD2_TEMPERATURE_C || TD2Temp > MAX_DISINFECT_TD2_TEMPERATURE_C ); + + /* this section is for monitoring the tank volumes for possible leaks. It is currently disabled pending decision whether to use it + BOOL isR1OutOfRange = fabs( getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ) - R1ChemDisinfectVol ) > RSRVRS_MAX_TARGET_VOL_CHANGE_ML; + BOOL isR2OutOfRange = fabs( getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ) - R2ChemDisinfectVol ) > RSRVRS_MAX_TARGET_VOL_CHANGE_ML; // Check if either reservoir 1 or reservoir 2 are losing volume more than allowed volume if ( ( TRUE == isR1OutOfRange ) || ( TRUE == isR2OutOfRange ) ) { @@ -1310,23 +1289,29 @@ } } + // Reservoirs are in range else { areRsrvrsLeaking = FALSE; } */ + + // set the tank volumes for logging + R1ChemDisinfectVol = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); + R2ChemDisinfectVol = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); + // For the following checks, if multiple failures occur at the same time, the last one will take precedence // Check if the acid conductivity and temperature are within range if ( TRUE == isCD2OutofRange ) { - alarmDetectedPendingTrigger = ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_HIGH_RANGE; //ALARM_ID_DG_NEW_CON; - status = CHEM_DISINFECT_DISINFECTANT_CONDUCTIVITY_OUT_OF_RANGE; + alarmDetectedPendingTrigger = ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_HIGH_RANGE; //ALARM_ID_DG_NEW_CON; TODO + status = CHEM_DISINFECT_DISINFECTANT_CONDUCTIVITY_OUT_OF_RANGE; } if ( ( TRUE == isTD2OutofRange ) ) { - alarmDetectedPendingTrigger = ALARM_ID_DG_CHEM_DISINFECT_TARGET_TEMP_TIMEOUT; - status = CHEM_DISINFECT_HEATER_OUTLET_TEMPERATURE_OUT_OF_RANGE; + alarmDetectedPendingTrigger = ALARM_ID_DG_CHEM_DISINFECT_TARGET_TEMP_TIMEOUT; + status = CHEM_DISINFECT_HEATER_OUTLET_TEMPERATURE_OUT_OF_RANGE; } // If the coldest spot which is TDi is less than minimum chemical disinfect temperature, @@ -1350,16 +1335,16 @@ else if ( isPartialDisinfectInProgress != TRUE ) { // The temperature of the coldest spot is in range to start the disinfect timer - chemDisinfectTimer = getMSTimerCount(); - isPartialDisinfectInProgress = TRUE; + chemDisinfectTimer = getMSTimerCount(); + isPartialDisinfectInProgress = TRUE; } // If chemical disinfect temperature has been reached, check if this stage of chemical disinfect is done if ( ( TRUE == isPartialDisinfectInProgress ) && ( TRUE == didTimeout( chemDisinfectTimer, CHEM_DISINFECT_TIME_MS ) ) ) { // Done with this stage of chemical disinfect. Reset the variables - status = CHEM_DISINFECT_COMPLETE; - isPartialDisinfectInProgress = FALSE; + status = CHEM_DISINFECT_COMPLETE; + isPartialDisinfectInProgress = FALSE; } return status; @@ -1390,7 +1375,7 @@ ( DG_CHEM_DISINFECT_STATE_R1_DISINFECTANT_FILL_R2_DRAIN == chemDisinfectState ) ) { uiData.chemDisinfectTargetTime = CHEM_DISINFECT_TIME_MS; - uiData.chemDisinfectCountdownTime = calcTimeSince( chemDisinfectTimer ); //CHEM_DISINFECT_TIME_MS - calcTimeSince( chemDisinfectTimer ); + uiData.chemDisinfectCountdownTime = calcTimeSince( chemDisinfectTimer ); data.R1FillLevel = R1ChemDisinfectVol; data.R2FillLevel = R2ChemDisinfectVol; } @@ -1434,8 +1419,8 @@ 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 ) ) ) + // If the dialysate cap is open during any state, alarm + if ( 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 Index: firmware/App/Modes/ModeChemicalDisinfectFlush.c =================================================================== diff -u -rd8686d68bf29761ee329fc638264d2e60a5191c0 -re82ddb85a3b3a1fc5d591d8cca0d006597fd94cf --- firmware/App/Modes/ModeChemicalDisinfectFlush.c (.../ModeChemicalDisinfectFlush.c) (revision d8686d68bf29761ee329fc638264d2e60a5191c0) +++ firmware/App/Modes/ModeChemicalDisinfectFlush.c (.../ModeChemicalDisinfectFlush.c) (revision e82ddb85a3b3a1fc5d591d8cca0d006597fd94cf) @@ -23,7 +23,7 @@ #include "Heaters.h" #include "LoadCell.h" #include "MessageSupport.h" -#include "ModeChemicalDisinfect.h" +#include "ModeChemicalDisinfectFlush.h" #include "ModeFault.h" #include "ModeStandby.h" #include "NVDataMgmt.h" @@ -51,7 +51,7 @@ #define CHEM_DISINFECT_FLUSH_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Mode chem disinfect data publish interval in counts. // Start state defines -#define MIN_INLET_PRESSURE_PSI 30.0F ///< Minimum water inlet pressure in psi. +#define MIN_INLET_PRESSURE_PSI 10.0F ///< Minimum water inlet pressure in psi. // Drain R1 & R2 states defines #define DRAIN_PUMP_TARGET_RPM 2400 ///< Drain pump target RPM during drain. @@ -62,22 +62,23 @@ // 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 24.0F ///< Minimum water inlet temperature in C. TODO original temperature was 25 C +#define MIN_INLET_TEMPERATURE_C 10.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 MIN_INLET_CONDUCTIVITY_US_PER_CM 0.0F ///< Minimum water inlet conductivity in us/cm // 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 and drain R1 and R2 -#define RSRVRS_FULL_VOL_ML 1850.0F ///< Reservoirs 1 & 2 full volume in mL. TODo original value was 1900 +#define RSRVRS_FULL_VOL_ML 1650.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 +#define CHEM_DISINFECT_FLUSH_TIME_MS ( 12 * SEC_PER_MIN * MS_PER_SECOND ) ///< Chemical disinfect flush time in ms. TODO: get the correct time for the mode #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. @@ -101,38 +102,38 @@ // ********** 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 overallChemDisinfectFlushTimer = 0; ///< Chemical disinfect cycle total timer. -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 DG_CHEM_DISINFECT_FLUSH_STATE_T chemDisinfectFlushState = DG_CHEM_DISINFECT_FLUSH_STATE_START; ///< Currently active chemical disinfect flush 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_FLUSH_UI_STATE_T chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_NOT_RUNNING; ///< Currently active chemical disinfect flush UI state. +static U32 overallChemDisinfectFlushTimer = 0; ///< Chemical disinfect flush cycle total timer. +static U32 stateTimer = 0; ///< Chemical disinfect flush state timer to be used in different states. +static U32 stateTrialCounter = 0; ///< Chemical disinfect flush state trial counter to be used for retries in different states. +static BOOL areTempSensorsInRange = FALSE; ///< Chemical disinfect flush 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 F32 R1ChemDisinfectFlushVol = 0.0; ///< Reservoir 1 full volume during chemical disinfect flush. +static F32 R2ChemDisinfectFlushVol = 0.0; ///< Reservoir 2 full volume during chemical disinfect flush. +static U32 chemDisinfectFlushTimer = 0; ///< Chemical disinfect flush 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 U32 rsrvrsVolMonitorTimer = 0; ///< Reservoir 1 & 2 volume monitor timers during chemical disinfect flush. +static BOOL areRsrvrsLeaking = FALSE; ///< Reservoir 1 & 2 leak check flag during chemical disinfect flush. +static U32 dataPublishCounter = 0; ///< Chemical disinfect flush 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 ALARM_ID_T alarmDetectedPendingTrigger; ///< Chemical disinfect flush alarm to raise. +static U32 numberOfPostDisinfectRinses; ///< Number of times to rinse the fluid path after chemical disinfect flush. 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. // ********** 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 handleChemicalDisinfectFlushDisinfectantDrainR1State( void ); +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushDisinfectantDrainR2State( 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 ); @@ -147,7 +148,7 @@ 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 writeDisinfectFlushDataToNV( void ); /*********************************************************************//** * @brief @@ -166,7 +167,7 @@ void initChemicalDisinfectFlushMode( void ) { chemDisinfectFlushState = DG_CHEM_DISINFECT_FLUSH_STATE_START; - prevChemDisinfectFlushState = DG_CHEM_DISINFECT_FLUSH_STATE_START; + prevChemDisinfectFlushState = DG_CHEM_DISINFECT_FLUSH_STATE_START; stateTimer = 0; isThisLastDrain = FALSE; stateTrialCounter = 0; @@ -225,11 +226,11 @@ break; case DG_CHEM_DISINFECT_FLUSH_STATE_DISINFECTANT_DRAIN_R1: - chemDisinfectFlushState = handleChemicalDisinfectFlushDrainR1State(); + chemDisinfectFlushState = handleChemicalDisinfectFlushDisinfectantDrainR1State(); break; case DG_CHEM_DISINFECT_FLUSH_STATE_DISINFECTANT_DRAIN_R2: - chemDisinfectFlushState = handleChemicalDisinfectFlushDrainR2State(); + chemDisinfectFlushState = handleChemicalDisinfectFlushDisinfectantDrainR2State(); break; case DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_DRAIN: @@ -270,7 +271,7 @@ break; } - //publishChemicalDisinfectFlushData(); + publishChemicalDisinfectFlushData(); return chemDisinfectFlushState; } @@ -367,12 +368,12 @@ * ChemDisinfectFlushUIState * @return next state of the chemical disinfect state machine *************************************************************************/ -static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushDrainR1State( void ) +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushDisinfectantDrainR1State( void ) { DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_DISINFECTANT_DRAIN_R1; // Set the chemical disinfect that is published on the UI - chemDisinfectFlushUIState = CHEM_DISINFECT_UI_STATE_FLUSH_AFTER_DISINFECT; + chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_FLUSH_AFTER_DISINFECT; if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr1Status ) { @@ -416,7 +417,7 @@ * chemDisinfectFlushUIState * @return next state of the chemical disinfect state machine *************************************************************************/ -static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushDrainR2State( void ) +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushDisinfectantDrainR2State( void ) { DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_DISINFECTANT_DRAIN_R2; @@ -438,7 +439,7 @@ // ??? 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( VPO, VALVE_STATE_NOFILL_C_TO_NO ); setValveState( VRD2, VALVE_STATE_CLOSED ); setValveState( VPI, VALVE_STATE_OPEN ); @@ -480,7 +481,7 @@ { if (haveInletWaterChecksPassed) { - // set pumps and valves for next state, flush disinfectant line + // 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 @@ -489,14 +490,14 @@ // 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( INLET_UV_REACTOR ); turnOnUVReactor( OUTLET_UV_REACTOR ); - stateTimer = getMSTimerCount(); - state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_DISINFECTANT_LINE; + 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 ) @@ -506,11 +507,11 @@ // 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; + 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; + state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_BASIC_PATH; } - } + } } @@ -569,12 +570,12 @@ if ( TRUE == didTimeout( stateTimer, FLUSH_UF_WAIT_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( VRO, VALVE_STATE_R2_C_TO_NC ); setValveState( VRD2, VALVE_STATE_CLOSED ); setValveState( VRD1, VALVE_STATE_OPEN ); rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; + rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; rinseCycleCounter = 0; stateTimer = getMSTimerCount(); state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_R2_TO_R1_DRAIN_R1; @@ -591,7 +592,7 @@ * 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 + * If the drain and rinse are completed within the defined time, it * transitions to the next state. * @details Inputs: rsrvr1Status, rsrvr2Status * @details Outputs: stateTimer, rsrvr1Status, rsrvr2Status, @@ -615,7 +616,7 @@ // Done with draining R1 signalDrainPumpHardStop(); setValveState( VRD1, VALVE_STATE_CLOSED ); - rsrvr1Empty = TRUE; + rsrvr1Empty = TRUE; } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { @@ -647,18 +648,18 @@ if ( ( TRUE == rsrvr2Full ) && ( TRUE == rsrvr1Empty ) && ( TRUE == didTimeout( stateTimer, FLUSH_ADDITIONAL_TIME_MS ) ) ) { // 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 ); + 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 ); - // 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; - // 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_CHEM_DISINFECT_FLUSH_STATE_FLUSH_R1_TO_R2_DRAIN_R2; } return state; @@ -671,7 +672,7 @@ * 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 + * If the drain and rinse are completed within the defined time, it * transitions to the next state. * @details Inputs: rsrvr1Status, rsrvr2Status, rinseCycleCounter * @details Outputs: stateTimer, rsrvr1Status, rsrvr2Status, @@ -697,13 +698,13 @@ // Done with draining R2 signalDrainPumpHardStop(); setValveState( VRD2, VALVE_STATE_CLOSED ); - rsrvr2Empty = TRUE; + rsrvr2Empty = TRUE; } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { - // reservoir 2 drain timeout + // reservoir 2 drain timeout prevChemDisinfectFlushState = state; - state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_WATER_PATH; + state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_WATER_PATH; } } @@ -712,7 +713,7 @@ // Reservoir 1 must be completely full if ( DG_RESERVOIR_BELOW_TARGET == rsrvr1Status ) { - rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS ); + rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_1, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS ); } if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) { @@ -730,9 +731,9 @@ { ++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( 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 ); @@ -744,10 +745,10 @@ // 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; - } + state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_R2_TO_R1_DRAIN_R1; + } else - { + { // number of rinse cycles complete // Set the valves to drain R1 setValveState( VPI, VALVE_STATE_CLOSED ); setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); @@ -758,21 +759,22 @@ // Turn on the drain pump to drain R2 setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); - // Turn off CP1 and CP2 - requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); - requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); + // Turn off CP1 and CP2 and ROP + signalROPumpHardStop(); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); - //Turn off UV reactors - turnOffUVReactor( INLET_UV_REACTOR ); + //Turn off UV reactors + turnOffUVReactor( INLET_UV_REACTOR ); turnOffUVReactor( OUTLET_UV_REACTOR ); // Set the reservoir status rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - isThisLastDrain = TRUE; + isThisLastDrain = TRUE; state = DG_CHEM_DISINFECT_FLUSH_STATE_DISINFECTANT_DRAIN_R1; - } + } } return state; @@ -1019,30 +1021,32 @@ * @details Outputs: dataPublishCounter * @return: none *************************************************************************/ -/* needs work + static void publishChemicalDisinfectFlushData( void ) { if ( ++dataPublishCounter >= CHEM_DISINFECT_FLUSH_DATA_PUB_INTERVAL ) { MODE_CHEMICAL_DISINFECT_FLUSH_DATA_T data; - MODE_CHEMICAL_DISINFECT_UI_DATA_T uiData; + MODE_CHEMICAL_DISINFECT_FLUSH_UI_DATA_T uiData; data.chemDisinfectFlushState = (U32)chemDisinfectFlushState; data.stateElapsedTime = calcTimeSince( stateTimer ); data.overallElapsedTime = calcTimeSince( overallChemDisinfectFlushTimer ); data.cancellationMode = (U32)cancellationMode; + uiData.chemDisinfectFlushTargetTime = CHEM_DISINFECT_FLUSH_TIME_MS; + uiData.chemDisinfectFlushCountdownTime = calcTimeSince( overallChemDisinfectFlushTimer ); // 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 ) ); + broadcastData( MSG_ID_DG_CHEM_DISINFECT_FLUSH_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 ) ); + broadcastData( MSG_ID_DG_CHEM_DISINFECT_FLUSH_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 @@ -1120,10 +1124,8 @@ * @details Outputs: disinfectNVOps * @return: none *************************************************************************/ -static void writeDisinfectDataToNV( void ) +static void writeDisinfectFlushDataToNV( 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 ); Index: firmware/App/Modes/ModeChemicalDisinfectFlush.h =================================================================== diff -u -r12d64de03890be512d1ccaca5d258710f3de99bb -re82ddb85a3b3a1fc5d591d8cca0d006597fd94cf --- firmware/App/Modes/ModeChemicalDisinfectFlush.h (.../ModeChemicalDisinfectFlush.h) (revision 12d64de03890be512d1ccaca5d258710f3de99bb) +++ firmware/App/Modes/ModeChemicalDisinfectFlush.h (.../ModeChemicalDisinfectFlush.h) (revision e82ddb85a3b3a1fc5d591d8cca0d006597fd94cf) @@ -16,9 +16,21 @@ // ********** public definitions ********** +/// Chemical disinfect UI data +typedef struct +{ + U32 chemDisinfectFlushTargetTime; ///< Target time during chemical disinfect. + U32 chemDisinfectFlushCountdownTime; ///< Chemical disinfect count down time. +} MODE_CHEMICAL_DISINFECT_FLUSH_UI_DATA_T; + +// ********** public function prototypes ********** + void initChemicalDisinfectFlushMode( void ); // initialize this module -U32 transitionToChemicalDisinfectFlushMode( void ); // prepares for transition to chemical disinfection flush mode -U32 execChemicalDisinfectFlushMode( void ); // execute the chemical disinfection flush mode state machine (call from OperationModes) +U32 transitionToChemicalDisinfectFlushMode( void ); // prepares for transition to chemical disinfect flush mode +U32 execChemicalDisinfectFlushMode( void ); // execute the chemical disinfect flush mode state machine (call from OperationModes) +DG_CHEM_DISINFECT_FLUSH_STATE_T getCurrentChemicalDisinfectFlushState( void ); // get the current state of the chemical disinfect flush mode. +BOOL stopChemicalDisinfectFlush( void ); + #endif Index: firmware/App/Modes/ModeFlush.c =================================================================== diff -u -r19934ca6e36e2dcabd6a6083a9a1f15b1ed32189 -re82ddb85a3b3a1fc5d591d8cca0d006597fd94cf --- firmware/App/Modes/ModeFlush.c (.../ModeFlush.c) (revision 19934ca6e36e2dcabd6a6083a9a1f15b1ed32189) +++ firmware/App/Modes/ModeFlush.c (.../ModeFlush.c) (revision e82ddb85a3b3a1fc5d591d8cca0d006597fd94cf) @@ -16,6 +16,7 @@ ***************************************************************************/ #include "ConcentratePumps.h" +#include "ConductivitySensors.h" #include "CPLD.h" #include "DrainPump.h" #include "FlowSensors.h" @@ -39,118 +40,161 @@ * @{ */ + // ********** private definitions ********** // General defines -#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. +#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. +// Start state defines +#define MIN_INLET_PRESSURE_PSI 30.0F ///< Minimum water inlet pressure in psi. + // Drain R1 & R2 states defines -#define DRAIN_WEIGHT_UNCHANGE_TIMEOUT ( 6 * MS_PER_SECOND ) ///< Time period of unchanged weight during draining before timeout. +#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. // Flush drain path state defines -#define FLUSH_DRAIN_WAIT_TIME_MS ( 2 * 60 * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. +#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 -// Flush dialysate state defines -#define FLUSH_DIALYSATE_WAIT_TIME_MS ( 60 * MS_PER_SECOND ) ///< Flush dialysate 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 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. +// 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 -// 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. +#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. -// 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. +/// 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 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. +/// 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 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_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. +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. // ********** private function prototypes ********** -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 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 void failFlushMode( void ); +static void failChemicalDisinfectFlush( 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 publishFlushData( void ); -static void monitorModeFlush( void ); +static void publishChemicalDisinfectFlushData( void ); +static void monitorModeChemicalDisinfectFlush( void ); +static void writeDisinfectDataToNV( void ); /*********************************************************************//** * @brief - * The initFlushMode function initializes flush mode module. + * The initChemicalDisinfectFlushMode function initializes the chemical + * disinfect flush mode module. * @details Inputs: none - * @details Outputs: flushState, prevFlushState, rsrvrFillStableTimeCounter, - * overallFlushElapsedTime, isThisInitialDrain, dataPublishCounter, - * rsrvr1Status, rsrvr2Status, hasWaterCancellationBeenSet, - * flushLinesVolumeL, haveDrainParamsBeenInit, stateTimerStart + * @details Outputs: chemDisinfectFlushState, stateTimer, isThisLastDrain, + * stateTrialCounter, areTempSensorsInRange, rsrvr1Status, rsrvr2Status, + * overallChemDisinfectFlushTimer, + * cancellationMode, rsrvrFillStableTimeCounter, prevChemDisinfectFlushState + * numberOfPostDisinfectRinses, + * chemDisinfectFlushUIState, haveDrainParamsBeenInit, + * disinfectFlushNVOps * @return none -*************************************************************************/ -void initFlushMode( void ) + *************************************************************************/ +//void initChemicalDisinfectFlushMode( void ) +void initFlushMode(void) { - // 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; + 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; } +/******** +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. @@ -167,91 +211,10 @@ setCPLDCleanLEDColor( CPLD_CLEAN_LED_BLUE ); - return flushState; + return chemDisinfectFlushState; } -/*********************************************************************//** - * @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 @@ -262,7 +225,7 @@ *************************************************************************/ DG_FLUSH_STATE_T getCurrentFlushState( void ) { - return flushState; + return chemDisinfectFlushState; } /*********************************************************************//** @@ -292,654 +255,684 @@ return status; } -// ********** private functions ********** +/*********************************************************************//** + * @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(); + 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 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 + * 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 *************************************************************************/ -static DG_FLUSH_STATE_T handleFlushModeStartState( void ) +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushStartState( void ) { - DG_FLUSH_STATE_T state = DG_FLUSH_STATE_START; + DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_DISINFECTANT_DRAIN_R1; - // Start overall flush timer - overallFlushElapsedTimeStart = getMSTimerCount(); + // Set the chemical disinfect that is published on the UI + chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_NOT_RUNNING; + // 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 ); - flushUIState = FLUSH_UI_STATE_DRAIN_DEVICE; - stateTimerStart = getMSTimerCount(); - rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - state = DG_FLUSH_STATE_DRAIN_R1; + rsrvrFillStableTimeCounter = 0; + // Assume reservoir 1 is full and drain it + rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; + stateTimer = getMSTimerCount(); return state; } /*********************************************************************//** * @brief - * 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 + * 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 *************************************************************************/ -static DG_FLUSH_STATE_T handleFlushModeDrainR1State( void ) +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushDrainR1State( void ) { - DG_FLUSH_STATE_T state = DG_FLUSH_STATE_DRAIN_R1; + DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_DISINFECTANT_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_DRAIN_TIMEOUT_MS ); + rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_FINAL_DRAIN_TIME_OUT_MS ); } else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) { - if ( TRUE == isThisInitialDrain ) - { - // Request a tare for reservoir 1 - tareLoadCell( LOAD_CELL_RESERVOIR_1_PRIMARY ); - tareLoadCell( LOAD_CELL_RESERVOIR_1_BACKUP ); - } + // Assume reservoir 2 is full and drain it + rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - // Close reservoir 1 drain + tareLoadCell( LOAD_CELL_RESERVOIR_1_PRIMARY ); + tareLoadCell( LOAD_CELL_RESERVOIR_1_BACKUP ); + + // Done with draining R1 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 ); - // Set VPO - setValveState( VPO, VALVE_STATE_FILL_C_TO_NC); + rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; + state = DG_CHEM_DISINFECT_FLUSH_STATE_DISINFECTANT_DRAIN_R2; - stateTimerStart = getMSTimerCount(); - rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - state = DG_FLUSH_STATE_DRAIN_R2; + // Start the timer + stateTimer = getMSTimerCount(); } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { - state = DG_FLUSH_STATE_CANCEL_BASIC_PATH; + prevChemDisinfectFlushState = state; + state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_BASIC_PATH; } return state; } /*********************************************************************//** * @brief - * 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 + * 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 *************************************************************************/ -static DG_FLUSH_STATE_T handleFlushModeDrainR2State( void ) +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushDrainR2State( void ) { - DG_FLUSH_STATE_T state = DG_FLUSH_STATE_DRAIN_R2; + DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_DISINFECTANT_DRAIN_R2; - 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(); + 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 ( TRUE == isThisInitialDrain ) - { - tareLoadCell( LOAD_CELL_RESERVOIR_2_PRIMARY ); - tareLoadCell( LOAD_CELL_RESERVOIR_2_BACKUP ); + 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; + } - // 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 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 + * 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 *************************************************************************/ -static DG_FLUSH_STATE_T handleFlushModeFlushDrainState( void ) +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushFlushDrainState( void ) { - DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_DRAIN; + DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_DRAIN; - if ( TRUE == didTimeout( stateTimerStart, FLUSH_DRAIN_WAIT_TIME_MS ) ) + // 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 ) ) { - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); - setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLOW_RATE_LPM, RO_PUMP_MAX_PRESSURE_PSI ); + 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; + } + } - // 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 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 ) + * 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 ) { - DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_DIALYSATE; - - if ( TRUE == didTimeout( stateTimerStart, FLUSH_DIALYSATE_WAIT_TIME_MS ) ) + 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 ) ) { - // 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 ); - // Turn on the concentrate pumps - requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); - requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); - - stateTimerStart = getMSTimerCount(); - - state = DG_FLUSH_STATE_FLUSH_CONCENTRATE_STRAWS; + // 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; } return state; } /*********************************************************************//** * @brief - * 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 + * 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 *************************************************************************/ -static DG_FLUSH_STATE_T handleFlushModeFlushConcentrateStrawsState( void ) +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushFlushUFState( void ) { - DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_CONCENTRATE_STRAWS; + DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_UF; - if ( TRUE == didTimeout( stateTimerStart, FLUSH_CONCENTRATE_STRAWS_TIME_MS ) ) + // Check if the flush UFtime has elapsed + if ( TRUE == didTimeout( stateTimer, FLUSH_UF_WAIT_TIME_MS ) ) { - // Done with flushing the concentrate pumps line - requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); - requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); + // 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 ); - 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; + 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; } - + return state; } + /*********************************************************************//** * @brief - * 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 + * 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 *************************************************************************/ -static DG_FLUSH_STATE_T handleFlushModeFlushR1ToR2State( void ) +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushFlushR2ToR1DrainR1State( void ) { - DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_R1_TO_R2; + 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; - if ( DG_RESERVOIR_BELOW_TARGET == rsrvr1Status ) + if ( FALSE == rsrvr1Empty ) { - 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 ) + if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr1Status ) { - prevFlushState = state; - alarmDetectedPendingTrigger = ALARM_ID_DG_INVALID_LOAD_CELL_VALUE; - state = DG_FLUSH_STATE_CANCEL_WATER_PATH; + rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_FLUSH_DRAIN_TIMEOUT_MS ); } + 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; + } } - else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) + + if ( FALSE == rsrvr2Full ) { + // Reservoir 2 must be completely full if ( DG_RESERVOIR_BELOW_TARGET == rsrvr2Status ) { - rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_PARTIAL_FILL_TIMEOUT_MS ); + rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS ); } - else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) + if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) { - // 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; + rsrvr2Full = TRUE; + stateTimer = getMSTimerCount(); } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { - state = DG_FLUSH_STATE_CANCEL_WATER_PATH; + prevChemDisinfectFlushState = state; + state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_WATER_PATH; } } - else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) + + if ( ( TRUE == rsrvr2Full ) && ( TRUE == rsrvr1Empty ) && ( TRUE == didTimeout( stateTimer, FLUSH_ADDITIONAL_TIME_MS ) ) ) { - state = DG_FLUSH_STATE_CANCEL_WATER_PATH; - } + // 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; + + } return state; } /*********************************************************************//** * @brief - * 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 + * 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 *************************************************************************/ -static DG_FLUSH_STATE_T handleFlushModeFlushR2AndDrainR1State( void ) +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushFlushR1ToR2DrainR2State( void ) { - DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_R2_AND_DRAIN_R1; + DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_FLUSH_R1_TO_R2_DRAIN_R2; - // If reservoir 1 is empty, turn off the drain pump - if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr1Status ) - { - 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; - } + static BOOL rsrvr2Empty = FALSE; + static BOOL rsrvr1Full = FALSE; - // 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 ) + if ( FALSE == rsrvr2Empty ) { - 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 ) ) + if ( DG_RESERVOIR_ABOVE_TARGET == rsrvr2Status ) { - prevFlushState = state; - alarmDetectedPendingTrigger = ALARM_ID_DG_INVALID_LOAD_CELL_VALUE; - state = DG_FLUSH_STATE_CANCEL_WATER_PATH; + 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; + } } - // 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 ( FALSE == rsrvr1Full ) + { + // Reservoir 1 must be completely full + if ( DG_RESERVOIR_BELOW_TARGET == rsrvr1Status ) + { + rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS ); + } if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) { - 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; + rsrvr1Full = TRUE; + stateTimer = getMSTimerCount(); } - // Check if reservoir 1 fill timed out - else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) + else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { - state = DG_FLUSH_STATE_CANCEL_WATER_PATH; + prevChemDisinfectFlushState = state; + state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_WATER_PATH; } } - // Check if reservoir 2 fill time out - else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) - { - state = DG_FLUSH_STATE_CANCEL_WATER_PATH; - } - return state; -} - -/*********************************************************************//** - * @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; - - F32 waterFlowRate = getMeasuredFlowRateLPM( RO_FLOW_SENSOR ); - F32 waterVolume = ( ( waterFlowRate / SEC_PER_MIN ) / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ); - - // Integrate volume of water moved through line - flushLinesVolumeL += waterVolume; - - // When enough water volume has flowed to flush the lines, transition to flush circulation state - if ( flushLinesVolumeL >= FLUSH_DRAIN_LINE_VOLUME_L ) + if ( ( TRUE == rsrvr1Full ) && ( TRUE == rsrvr2Empty ) && ( TRUE == didTimeout( stateTimer, FLUSH_ADDITIONAL_TIME_MS ) ) ) { - // 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 ); + ++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 ); - stateTimerStart = getMSTimerCount(); + // Turn on the drain pump to drain R2 + setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); - 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; - } + // 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 ); - return state; -} + // Turn on the drain pump to drain R2 + setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); -/*********************************************************************//** - * @brief - * 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_FLUSH_STATE_T handleFlushModeFlushCirculationState( void ) -{ - DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_CIRCULATION; + // Turn off CP1 and CP2 + requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); - 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 ); + //Turn off UV reactors + turnOffUVReactor( INLET_UV_REACTOR ); + turnOffUVReactor( OUTLET_UV_REACTOR ); - stateTimerStart = getMSTimerCount(); + // Set the reservoir status + rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; + rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - state = DG_FLUSH_STATE_FLUSH_WITH_FRESH_WATER; + isThisLastDrain = TRUE; + state = DG_CHEM_DISINFECT_FLUSH_STATE_DISINFECTANT_DRAIN_R1; + } } 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 handleFlushModeCancelBasicPathState function handles the flush - * cancel mode basic path state. The state sets the state to complete and - * raises an alarm. + * 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: none - * @return next state of the flush state machine + * @details Outputs: cancellationMode, ChemDisinfectFlushUIState + * @return next state of the heat disinfect state machine *************************************************************************/ -static DG_FLUSH_STATE_T handleFlushModeCancelBasicPathState( void ) +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushCancelModeBasicPathState( void ) { - DG_FLUSH_STATE_T state = DG_FLUSH_STATE_CANCEL_BASIC_PATH; + DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_BASIC_PATH; - // Once the fault alarm is raised, the DG Software will - // deenergize all the actuators - failFlushMode(); - flushUIState = FLUSH_UI_STATE_CANCEL_FLUSH; + // Set the chemical disinfect that is published on the UI + chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_CANCEL_FLUSH; + // Set the cancellation mode + cancellationMode = CANCELLATION_MODE_BASIC; + + failChemicalDisinfectFlush(); + 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 + * 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 *************************************************************************/ -static DG_FLUSH_STATE_T handleFlushModeCancelWaterPathState( void ) +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushCancelModeWaterPathState( void ) { - DG_FLUSH_STATE_T state = DG_FLUSH_STATE_CANCEL_WATER_PATH; + DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_CANCEL_WATER_PATH; - if ( FALSE == hasWaterCancellationBeenSet ) + // Set the chemical disinfect that is published on the UI + chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_CANCEL_FLUSH; + + if ( CANCELLATION_MODE_NONE == cancellationMode ) { // Stop all the actuators first then decide who should run next deenergizeActuators(); - // Set the actuators - setValveState( VPI, VALVE_STATE_CLOSED ); - setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); - setValveState( VRD2, VALVE_STATE_OPEN ); + cancellationMode = CANCELLATION_MODE_WATER; + rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; + rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - // 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 + // The drain is set to start from reservoir 2 + setValveState( VRD2, VALVE_STATE_OPEN ); setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); - flushUIState = FLUSH_UI_STATE_CANCEL_FLUSH; - // Start the timer for drain timeout - stateTimerStart = getMSTimerCount(); + stateTimer = 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_DRAIN_TIMEOUT_MS ); + rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_INITIAL_DRAIN_TIME_OUT_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 ) { - state = DG_FLUSH_STATE_CANCEL_BASIC_PATH; + prevChemDisinfectFlushState = state; + state = DG_CHEM_DISINFECT_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, go to basic cancellation path - rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_DRAIN_TIMEOUT_MS ); + // 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 ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) { - setValveState( VRD2, VALVE_STATE_CLOSED ); - // Done with draining - signalDrainPumpHardStop(); - - // Raise the alarm - failFlushMode(); + failChemicalDisinfectFlush(); } + // 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 handleFlushModeComplete function handles the complete state. + * The handleChemicalDisinfectFlushCompleteState function handles the chemical + * disinfect complete state. The state stops chemical disinfect and + * requests transition to mode standby. * @details Inputs: none - * @details Outputs: none - * @return next state of the flush state machine + * @details Outputs: ChemDisinfectFlushUIState + * @return next state of the chemical disinfect state machine *************************************************************************/ -static DG_FLUSH_STATE_T handleFlushModeComplete( void ) +static DG_CHEM_DISINFECT_FLUSH_STATE_T handleChemicalDisinfectFlushCompleteState( void ) { - DG_FLUSH_STATE_T state = DG_FLUSH_STATE_COMPLETE; + DG_CHEM_DISINFECT_FLUSH_STATE_T state = DG_CHEM_DISINFECT_FLUSH_STATE_COMPLETE; - stopDGFlush(); + // Set the chemical disinfect that is published on the UI + chemDisinfectFlushUIState = CHEM_DISINFECT_FLUSH_UI_STATE_COMPLETE; + stopChemicalDisinfectFlush(); + return state; } /*********************************************************************//** * @brief - * The failFlushMode function sets the alarm that failed the flush mode. - * @details Inputs: alarm, prevHeatDisinfectState + * The failChemicalDisinfectFlush function sets the alarm that failed the + * chemical disinfect mode. + * @details Inputs: alarmDetectedPendingTrigger, prevChemDisinfectFlushState * @details Outputs: none * @return none *************************************************************************/ -static void failFlushMode( void ) +static void failChemicalDisinfectFlush( void ) { - SET_ALARM_WITH_1_U32_DATA( alarmDetectedPendingTrigger, prevFlushState ) + SET_ALARM_WITH_1_U32_DATA( alarmDetectedPendingTrigger, prevChemDisinfectFlushState ) } /*********************************************************************//** * @brief - * 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 + * 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 * @param r is DG_RESERVOIR_1 or DG_RESERVOIR_2 * @param targetVol is the target fill volume - * @param timeout is the fill up time out that is checked against + * @param timeout is the fill up timeout * @return the status of the reservoirs during filling *************************************************************************/ static DG_RESERVOIR_STATUS_T getRsrvrFillStatus( DG_RESERVOIR_ID_T r, F32 targetVol, U32 timeout ) @@ -955,34 +948,28 @@ { 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 - 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(); - } + stateTimer = getMSTimerCount(); } } - else if ( TRUE == didTimeout( stateTimerStart, timeout ) ) + else if ( TRUE == didTimeout( stateTimer, timeout ) ) { - // Failed to fill on time - prevFlushState = flushState; + // Failed to fill ontime. Update the previous chemical disinfect state and transition to basic cancellation + prevChemDisinfectFlushState = chemDisinfectFlushState; alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_FILL_TIMEOUT; - status = DG_RESERVOIR_NOT_REACHED_TARGET; + status = DG_RESERVOIR_NOT_REACHED_TARGET; } return status; @@ -991,11 +978,10 @@ /*********************************************************************//** * @brief * The getRsrvrDrainStatus function returns the status of draining a - * 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 + * reservoir. + * @details Inputs: stateTimer, chemDisinfectFlushState + * alarm + * @details Outputs: stateTimer, prevChemDisinfectFlushState, alarm * @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 @@ -1008,7 +994,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; @@ -1018,84 +1004,162 @@ if ( TRUE == isDrainComplete ) { - 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(); - } - + // Set the state timer in case it needs to be used for another timeout check + stateTimer = getMSTimerCount(); haveDrainParamsBeenInit[ r ] = FALSE; - status = DG_RESERVOIR_REACHED_TARGET; + status = DG_RESERVOIR_REACHED_TARGET; } - else if ( TRUE == didTimeout( stateTimerStart, timeout ) ) + else if ( TRUE == didTimeout( stateTimer, timeout ) ) { - // Failed to drain on time - prevFlushState = flushState; - haveDrainParamsBeenInit [ r ] = FALSE; - alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_DRAIN_TIMEOUT; - status = DG_RESERVOIR_NOT_REACHED_TARGET; + // 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; } return status; } + /*********************************************************************//** * @brief - * The publishFlushData function publishes the flush mode data at the set - * interval. + * The publishChemicalDisinfectFlushData function publishes chemical disinfect + * flush data at the set interval. * @details Inputs: dataPublishCounter * @details Outputs: dataPublishCounter * @return: none *************************************************************************/ -static void publishFlushData( void ) + +static void publishChemicalDisinfectFlushData( void ) { - if ( ++dataPublishCounter >= FLUSH_DATA_PUB_INTERVAL ) + + + if ( ++dataPublishCounter >= CHEM_DISINFECT_FLUSH_DATA_PUB_INTERVAL ) { + MODE_FLUSH_DATA_T data; - data.flushState = (U32)flushState; - data.overallElapsedTime = calcTimeSince( overallFlushElapsedTimeStart ); - data.stateElapsedTime = calcTimeSince( stateTimerStart ); - data.drainLineVolume = flushLinesVolumeL; - data.flushUIState = (U32)flushUIState; + data.flushState = (U32)chemDisinfectFlushState; + data.overallElapsedTime = calcTimeSince( overallChemDisinfectFlushTimerStart ); + data.stateElapsedTime = calcTimeSince( stateTimer ); + data.drainLineVolume = 0; + data.flushUIState = (U32)chemDisinfectFlushUIState; 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 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 + * 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 * @return: none *************************************************************************/ -static void monitorModeFlush( void ) +static void monitorModeChemicalDisinfectFlush( 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 cap = (U32)( STATE_OPEN == getSwitchStatus( CONCENTRATE_CAP ) ? CONCENTRATE_CAP : DIALYSATE_CAP ); - prevFlushState = flushState; - flushState = DG_FLUSH_STATE_CANCEL_WATER_PATH; + U32 ConcCap = (U32)getSwitchStatus( CONCENTRATE_CAP ); + U32 DialysateCap = (U32)getSwitchStatus( DIALYSATE_CAP ); + prevChemDisinfectFlushState = chemDisinfectFlushState; + chemDisinfectFlushState = DG_CHEM_DISINFECT_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() ); + } } /**@}*/ Index: firmware/App/Modes/ModeStandby.c =================================================================== diff -u -r0c296cef29037819be204c45a23d4d38a52b2718 -re82ddb85a3b3a1fc5d591d8cca0d006597fd94cf --- firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 0c296cef29037819be204c45a23d4d38a52b2718) +++ firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision e82ddb85a3b3a1fc5d591d8cca0d006597fd94cf) @@ -60,6 +60,7 @@ static BOOL pendingStartDGFlushRequest; ///< Flag indicating HD has requested DG start flush. static BOOL pendingStartDGHeatDisinfectRequest; ///< Flag indicating HD has requested DG start heat disinfect. static BOOL pendingStartDGChemicalDisinfectRequest; ///< Flag indicating HD has requested DG start chemical disinfect. +static BOOL pendingStartDGChemicalDisinfectFlushRequest; ///< Flag indicating HD has requested DG start chemical disinfect flush. static OVERRIDE_U32_T filterFlushTimePeriod = { FILTER_FLUSH_TIME_MS, FILTER_FLUSH_TIME_MS, 0, 0 }; ///< Filter flush time period in ms. @@ -214,7 +215,14 @@ requestNewOperationMode( DG_MODE_CHEM ); } + else if ( TRUE == pendingStartDGChemicalDisinfectFlushRequest ) + { + pendingStartDGChemicalDisinfectFlushRequest = FALSE; + requestNewOperationMode( DG_MODE_CHFL ); + } + + return state; } @@ -547,6 +555,56 @@ /*********************************************************************//** * @brief + * The startDGChemicalDisinfectFlush function starts chemical disinfect flush mode. + * @details Inputs: standbyState + * @details Outputs: none + * @return: TRUE if the switch was successful + *************************************************************************/ +BOOL startDGChemicalDisinfectFlush( void ) +{ + BOOL status = FALSE; + + // If DG is in standby mode and the standby mode is in Idle, request chemical disinfect + // Chemical disinfect cannot be run in solo mode because the user has to confirm that the acid is inserted or removed + if ( ( DG_MODE_STAN == getCurrentOperationMode() ) && ( DG_STANDBY_MODE_STATE_IDLE == standbyState ) ) + { + DG_CMD_RESPONSE_T cmdResponse; + + cmdResponse.commandID = DG_CMD_START_CHEM_DISINFECT_FLUSH; + cmdResponse.rejected = FALSE; + cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_NONE; + OPN_CLS_STATE_T concCap = getSwitchStatus( CONCENTRATE_CAP ); + OPN_CLS_STATE_T diaCap = getSwitchStatus( DIALYSATE_CAP ); + +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_CAPS_MONITOR ) ) + { + concCap = STATE_CLOSED; + diaCap = STATE_CLOSED; + } +#endif + + // When chemical disinfect is about to be started, both caps must be closed + if ( ( STATE_OPEN == concCap ) || ( STATE_OPEN == diaCap ) ) + { + cmdResponse.rejected = TRUE; + cmdResponse.rejectCode = ( STATE_OPEN == getSwitchStatus( DIALYSATE_CAP ) ? REQUEST_REJECT_REASON_DG_DIALYSATE_CAP_OPEN : + REQUEST_REJECT_REASON_DG_CONCENTRATE_CAP_OPEN ); + } + else + { + pendingStartDGChemicalDisinfectFlushRequest = TRUE; + status = TRUE; + } + + sendCommandResponseMsg( &cmdResponse ); + } + + return status; +} + +/*********************************************************************//** + * @brief * The getCurrentStandbyState function returns the current state of standby mode. * @details Inputs: standbyState * @details Outputs: none Index: firmware/App/Modes/ModeStandby.h =================================================================== diff -u -r025612ad77fe630889a364586de54bffe5262d56 -re82ddb85a3b3a1fc5d591d8cca0d006597fd94cf --- firmware/App/Modes/ModeStandby.h (.../ModeStandby.h) (revision 025612ad77fe630889a364586de54bffe5262d56) +++ firmware/App/Modes/ModeStandby.h (.../ModeStandby.h) (revision e82ddb85a3b3a1fc5d591d8cca0d006597fd94cf) @@ -55,7 +55,8 @@ BOOL testSetFilterFlushTimePeriodOverride( U32 value ); BOOL testResetFilterFlushTimePeriodOverride( void ); -BOOL startDGChemicalDisinfect( void ); // HD start chemical disinfect mode +BOOL startDGChemicalDisinfect( void ); // HD start chemical disinfect mode +BOOL startDGChemicalDisinfectFlush( void ); // HD start chemical disinfect flush mode /**@}*/ Index: firmware/App/Modes/OperationModes.c =================================================================== diff -u -r8c297279b7a80829a0dc70ab4bb6e58bc4ed8026 -re82ddb85a3b3a1fc5d591d8cca0d006597fd94cf --- firmware/App/Modes/OperationModes.c (.../OperationModes.c) (revision 8c297279b7a80829a0dc70ab4bb6e58bc4ed8026) +++ firmware/App/Modes/OperationModes.c (.../OperationModes.c) (revision e82ddb85a3b3a1fc5d591d8cca0d006597fd94cf) @@ -65,7 +65,7 @@ /* FAUL */{ DG_MODE_FAUL, DG_MODE_SERV, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG }, /* SERV */{ DG_MODE_FAUL, DG_MODE_SERV, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG }, /* INIT */{ DG_MODE_FAUL, DG_MODE_NLEG, DG_MODE_INIT, DG_MODE_STAN, DG_MODE_SOLO, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG }, - /* STAN */{ DG_MODE_FAUL, DG_MODE_SERV, DG_MODE_NLEG, DG_MODE_STAN, DG_MODE_SOLO, DG_MODE_GENE, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_FLUS, DG_MODE_HEAT, DG_MODE_CHEM, DG_MODE_NLEG }, + /* STAN */{ DG_MODE_FAUL, DG_MODE_SERV, DG_MODE_NLEG, DG_MODE_STAN, DG_MODE_SOLO, DG_MODE_GENE, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_FLUS, DG_MODE_HEAT, DG_MODE_CHEM, DG_MODE_CHFL /*DG_MODE_NLEG*/ }, /* SOLO */{ DG_MODE_FAUL, DG_MODE_SERV, DG_MODE_NLEG, DG_MODE_STAN, DG_MODE_SOLO, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_FLUS, DG_MODE_HEAT, DG_MODE_NLEG, DG_MODE_NLEG }, /* GENE */{ DG_MODE_FAUL, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_STAN, DG_MODE_NLEG, DG_MODE_GENE, DG_MODE_FILL, DG_MODE_DRAI, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG }, /* FILL */{ DG_MODE_FAUL, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_STAN, DG_MODE_NLEG, DG_MODE_GENE, DG_MODE_FILL, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG }, @@ -121,6 +121,7 @@ initFlushMode(); initHeatDisinfectMode(); initChemicalDisinfectMode(); + initChemicalDisinfectFlushMode(); } /*********************************************************************//** @@ -363,6 +364,7 @@ break; case DG_MODE_CHFL: currentSubMode = transitionToChemicalDisinfectFlushMode(); + break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_OP_MODES_INVALID_MODE_TO_TRANSITION_TO, (U32)newMode ) break; Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -r9cc5da6947aa143a10f95519eb7f366c1b095d61 -re82ddb85a3b3a1fc5d591d8cca0d006597fd94cf --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 9cc5da6947aa143a10f95519eb7f366c1b095d61) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision e82ddb85a3b3a1fc5d591d8cca0d006597fd94cf) @@ -877,6 +877,10 @@ handleStartStopDGChemicalDisinfect( message ); break; + case MSG_ID_DG_START_STOP_CHEM_DISINFECT_FLUSH: + handleStartStopDGChemicalDisinfectFlush( message ); + break; + case MSG_ID_UI_DG_SET_RTC_REQUEST: handleUIClockSyncRequest( message ); break; Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -r9cc5da6947aa143a10f95519eb7f366c1b095d61 -re82ddb85a3b3a1fc5d591d8cca0d006597fd94cf --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 9cc5da6947aa143a10f95519eb7f366c1b095d61) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision e82ddb85a3b3a1fc5d591d8cca0d006597fd94cf) @@ -1353,6 +1353,41 @@ } /*********************************************************************//** +* @brief +* The handleStartStopDGChemicalDisinfectFlush function handles a request to start +* or stop DG chemical disinfect flush mode. +* @details Inputs: none +* @details Outputs: message handled +* @param message a pointer to the message to handle +* @return none +*************************************************************************/ +BOOL handleStartStopDGChemicalDisinfectFlush( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + if ( message->hdr.payloadLen == sizeof(U32) ) + { + BOOL startingDGChemicalDisinfectFlush; + + memcpy( &startingDGChemicalDisinfectFlush, message->payload, sizeof(U32) ); + + if ( TRUE == startingDGChemicalDisinfectFlush ) + { + result = startDGChemicalDisinfectFlush(); + } + else + { + result = stopChemicalDisinfectFlush(); + } + } + + // Respond to request + sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_DG_2_HD, result ); + + return result; +} + +/*********************************************************************//** * @brief * The handleTestSetOpModeRequest function handles a request to set the * DG operation mode. Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -r9cc5da6947aa143a10f95519eb7f366c1b095d61 -re82ddb85a3b3a1fc5d591d8cca0d006597fd94cf --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 9cc5da6947aa143a10f95519eb7f366c1b095d61) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision e82ddb85a3b3a1fc5d591d8cca0d006597fd94cf) @@ -26,6 +26,7 @@ #include "LoadCell.h" #include "MessageSupport.h" #include "ModeChemicalDisinfect.h" +#include "ModeChemicalDisinfectFlush.h" #include "ModeFlush.h" #include "ModeHeatDisinfect.h" #include "MsgQueues.h" @@ -337,6 +338,9 @@ // MSG_ID_DG_START_STOP_CHEM_DSINFECT BOOL handleStartStopDGChemicalDisinfect( MESSAGE_T *message ); +// MSG_ID_DG_START_STOP_CHEM_DISINFECT_FLUSH +BOOL handleStartStopDGChemicalDisinfectFlush( MESSAGE_T *message ); + // MSG_ID_DG_OP_MODE_PUBLISH_INTERVAL_OVERRIDE void handleSetDGOpModeBroadcastIntervalOverrideRequest( MESSAGE_T *message );