Index: firmware/App/Modes/ModeChemicalDisinfect.c =================================================================== diff -u -r622eebf6fb7f1c6c232ffd82bc072dd30a7b3f94 -rd7be59e36db5e9899b02dd0bfadadc50fed934c0 --- firmware/App/Modes/ModeChemicalDisinfect.c (.../ModeChemicalDisinfect.c) (revision 622eebf6fb7f1c6c232ffd82bc072dd30a7b3f94) +++ firmware/App/Modes/ModeChemicalDisinfect.c (.../ModeChemicalDisinfect.c) (revision d7be59e36db5e9899b02dd0bfadadc50fed934c0) @@ -1,17 +1,17 @@ /************************************************************************** * -* Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +* Copyright (c) 2020-2022 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * -* @file ModeChemicalDisinfect.c +* @file ModeChemicalDisinfect.c * -* @author (last) Quang Nguyen -* @date (last) 01-Sep-2020 +* @author (last) Bill Bracken +* @date (last) 22-Aug-2022 * -* @author (original) Sean -* @date (original) 04-Apr-2020 +* @author (original) Sean +* @date (original) 04-Apr-2020 * ***************************************************************************/ @@ -24,10 +24,12 @@ #include "ModeChemicalDisinfect.h" #include "ModeFault.h" #include "ModeStandby.h" +#include "NVDataMgmt.h" #include "OperationModes.h" #include "Pressures.h" #include "Reservoirs.h" #include "ROPump.h" +#include "RTC.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "TemperatureSensors.h" @@ -47,60 +49,60 @@ #define CHEM_DISINFECT_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.0 ///< Minimum water inlet pressure in psi. -#define MAX_START_STATE_TEMP_SENSORS_DIFF_C 3.0 ///< Max start state TDi and TRo difference tolerance in C. +#define MIN_INLET_PRESSURE_PSI 30.0F ///< Minimum water inlet pressure in psi. +#define MAX_START_STATE_TEMP_SENSORS_DIFF_C 3.0F ///< Max start state TDi and TRo difference tolerance in C. // Drain R1 & R2 states defines -#define DRAIN_PUMP_TARGET_RPM 2100 ///< Drain pump target RPM during drain. -#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_PUMP_TARGET_RPM 2400 ///< Drain pump target RPM during drain. +#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 ( SEC_PER_MIN * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. -#define MIN_INLET_TEMPERATURE_C 15.0 ///< Minimum water inlet temperature in C. TODO original temperature was 25 C -#define MAX_INLET_CONDUCTIVITY_US_PER_CM 2000.0 ///< Maximum water inlet conductivity in us/cm +#define MIN_INLET_TEMPERATURE_C 15.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 // Flush circulation path state defines -#define RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM 0.8 ///< RO pump target flow rate during flush/fill in L/min. TODO original flow was 0.8 +#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. TODO original time was 30 seconds -#define MAX_FLUSH_CIRC_TEMP_SENSOR_DIFF_C 50.0 ///< Maximum flush circulation temperature difference tolerance in C. TODO original difference was 3.0 degrees -#define NUM_OF_TEMP_SENSORS_TO_AVG 4.0 ///< Number of temperature sensors to average to check the difference. +#define FLUSH_CICRCULATION_WAIT_TIME_MS ( 30 * MS_PER_SECOND ) ///< Flush/rinse circulation path 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 4.0F ///< Number of temperature sensors to average to check the difference. // Flush and drain R1 and R2 -#define RSRVRS_FULL_VOL_ML 1680.0 ///< Reservoirs 1 & 2 full volume in mL. TODo original value was 1900 -#define RSRVRS_PARTIAL_FILL_VOL_ML 500.0 ///< Reservoirs 1 & 2 partial volume in mL. +#define RSRVRS_FULL_VOL_ML 1850.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 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 full fill up timeout in ms. TODO original value was 5 mins +#define RSRVRS_FILL_UP_TIMEOUT_MS ( 5 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 full fill up timeout in ms. #define RSRVRS_500ML_FILL_UP_TIMEOUT_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 partial fill up timeout in ms. #define RSRVRS_DRAIN_TIMEOUT_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 drain timeout in ms. // R1 to R2 & R2 to R1 chemical disinfect circulation -#define CHEM_DISINFECT_TARGET_RO_FLOW_LPM 0.9 ///< Chemical disinfect target RO flow rate in L/min. TODO original value was 0.8 +#define CHEM_DISINFECT_TARGET_RO_FLOW_LPM 0.8F ///< 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_TARGET_DRAIN_PRES_PSI 10.0 ///< Chemical disinfect target drain outlet pressure in psi. -#define CHEM_DISINFECT_TIME_MS ( 20 * SEC_PER_MIN * MS_PER_SECOND ) ///< Chemical disinfect time for each section in milliseconds. TODO original time was 10 minutes -#define CHEM_DISINFECT_START_TEMP_TIMOUT_MS ( 4 * MIN_PER_HOUR * SEC_PER_MIN * MS_PER_SECOND ) ///< Chemical disinfect reaching to minimum temperature timeout in milliseconds. TODO figure out this timeout -#define RSRVRS_TARGET_VOL_OUT_TIMEOUT_MS ( 0.5 * 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.0 ///< Reservoirs 1 & 2 maximum allowed volume change when full during chemical disinfect. TODO original value is 100 mL +#define CHEM_DISINFECT_TARGET_DRAIN_PRES_PSI 12.0 ///< Chemical disinfect target drain outlet pressure in psi. +#define CHEM_DISINFECT_TIME_MS ( 36 * 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_TIMOUT_MS ( 4 * MIN_PER_HOUR * SEC_PER_MIN * MS_PER_SECOND ) ///< Chemical disinfect reaching to minimum temperature timeout in milliseconds. +#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 CONC_PUMP_PRIME_SPEED_ML_PER_MIN 40.0 ///< Concentrate pump prime speed in ml/min. -#define MIN_ACID_CONDUCTIVITY_US_PER_CM 2000.0 ///< Minimum conductivity that indicates acid is in the line in uS/cm. +#define CONC_PUMP_PRIME_SPEED_ML_PER_MIN 40.0F ///< Concentrate pump prime speed in ml/min. +#define MIN_ACID_CONDUCTIVITY_US_PER_CM 2000.0F ///< Minimum conductivity that indicates acid is in the line in uS/cm. #define PRIME_ACID_STEADY_CONDUCTIVITY_TIME_MS ( ( 2 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Minimum time that a steady conductivity of acid must be read in milliseconds. // Fill with disinfectant and water -#define MIN_RO_FLOW_FOR_CONC_PUMP_MIXING_LPM 0.3 ///< 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. // Fill heat up -#define CHEM_DISINFECT_TARGET_TEMPERATURE_C 21.0 ///< Chemical disinfect target water temperature in C. +#define CHEM_DISINFECT_TARGET_TEMPERATURE_C 21.0F ///< Chemical disinfect target water temperature in C. // TODO this used to 30.0 // Post disinfect rinses -#define NUM_OF_POST_DISINFECT_RINSES 1 ///< Number of rinses after a chemical disinfect. +#define NUM_OF_POST_DISINFECT_RINSES 12 ///< Number of rinses after a chemical disinfect. -static const F32 ACID_TO_WATER_MIXING_RATIO = ( 1.0 / 70.0 ); ///< Acid to water mixing ratio for chemical disinfect. +static const F32 ACID_TO_WATER_MIXING_RATIO = ( 1.0F / 70.0F ); ///< Acid to water mixing ratio for chemical disinfect. /// Cancellation paths typedef enum Cancellation_modes @@ -126,7 +128,7 @@ static DG_CHEM_DISINFECT_STATE_T chemDisinfectState = DG_CHEM_DISINFECT_STATE_START; ///< Currently active chemical disinfect state. static DG_CHEM_DISINFECT_STATE_T prevChemDisinfectState = DG_CHEM_DISINFECT_STATE_START; ///< Previous active heat disinfect state before alarm. -static DG_CHEM_DISINFECT_UI_STATE_T chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_NOT_RUNNING; ///< Currently active chemical disinfect UI state. +static DG_CHEM_DISINFECT_UI_STATE_T chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_NOT_RUNNING; ///< Currently active chemical disinfect UI state. static U32 overallChemDisinfectTimer = 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. @@ -143,10 +145,11 @@ 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 = 0; ///< Reservoirs fill stable time counter. +static U32 rsrvrFillStableTimeCounter; ///< Reservoirs fill stable time counter. static ALARM_ID_T alarmDetectedPendingTrigger; ///< Chemical disinfect alarm to raise. -static U32 numberOfPostDisinfectRinses = NUM_OF_POST_DISINFECT_RINSES; ///< Number of times to rinse the fluid path after chemical disinfect. -static U32 primeAcidSteadyStateCounter = 0; +static U32 numberOfPostDisinfectRinses; ///< Number of times to rinse the fluid path after chemical disinfect. +static U32 primeAcidSteadyStateCounter = 0; ///< Prime acid steady state counter. +static BOOL haveDrainParamsBeenInit[ NUM_OF_DG_RESERVOIRS ]; ///< Boolean flag to indicate whether the drain parameters have been reset or not. // ********** private function prototypes ********** @@ -181,6 +184,7 @@ static DG_RESERVOIR_STATUS_T getRsrvrDrainStatus( DG_RESERVOIR_ID_T r, U32 drainSteadyStateTimeout, U32 timeout ); static CHEM_DISINFECT_STATUS_T getChemicalDisinfectStatus( void ); static void publishChemicalDisinfectData( void ); +static void monitorModeChemicalDisinfect( void ); /*********************************************************************//** * @brief @@ -192,28 +196,30 @@ * R1ChemDisinfectVol, R2ChemDisinfectVol, overallChemDisinfectTimer, * cancellationMode, rsrvrFillStableTimeCounter, prevChemDisinfectState * isPartialDisinfectInProgress, numberOfPostDisinfectRinses, - * primeAcidSteadyStateCounter, chemDisinfectUIState + * primeAcidSteadyStateCounter, chemDisinfectUIState, haveDrainParamsBeenInit * @return none *************************************************************************/ void initChemicalDisinfectMode( void ) { - chemDisinfectState = DG_CHEM_DISINFECT_STATE_START; - prevChemDisinfectState = DG_CHEM_DISINFECT_STATE_START; - stateTimer = 0; - isThisLastDrain = FALSE; - stateTrialCounter = 0; - areTempSensorsInRange = FALSE; - rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; - rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; - R1ChemDisinfectVol = 0.0; - R2ChemDisinfectVol = 0.0; - overallChemDisinfectTimer = 0; - cancellationMode = CANCELLATION_MODE_NONE; - rsrvrFillStableTimeCounter = 0; - isPartialDisinfectInProgress = FALSE; - numberOfPostDisinfectRinses = NUM_OF_POST_DISINFECT_RINSES; - primeAcidSteadyStateCounter = 0; - chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_NOT_RUNNING; + chemDisinfectState = DG_CHEM_DISINFECT_STATE_START; + prevChemDisinfectState = DG_CHEM_DISINFECT_STATE_START; + stateTimer = 0; + isThisLastDrain = FALSE; + stateTrialCounter = 0; + areTempSensorsInRange = FALSE; + rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; + rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; + R1ChemDisinfectVol = 0.0; + R2ChemDisinfectVol = 0.0; + overallChemDisinfectTimer = 0; + cancellationMode = CANCELLATION_MODE_NONE; + rsrvrFillStableTimeCounter = 0; + isPartialDisinfectInProgress = FALSE; + numberOfPostDisinfectRinses = 0; + primeAcidSteadyStateCounter = 0; + chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_NOT_RUNNING; + haveDrainParamsBeenInit[ DG_RESERVOIR_1 ] = FALSE; + haveDrainParamsBeenInit[ DG_RESERVOIR_2 ] = FALSE; } /*********************************************************************//** @@ -243,6 +249,8 @@ *************************************************************************/ U32 execChemicalDisinfectMode( void ) { + monitorModeChemicalDisinfect(); + switch ( chemDisinfectState ) { case DG_CHEM_DISINFECT_STATE_START: @@ -421,28 +429,22 @@ // Set all the actuators to reset and de-energized state deenergizeActuators(); - // Reset the load cells lowest weight prior to starting the run - resetReservoirsLowestWeight(); - F32 ppiPressure = getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_INLET ); F32 THdTemp = getTemperatureValue( TEMPSENSORS_HEAT_DISINFECT ); F32 TPoTemp = getTemperatureValue( TEMPSENSORS_OUTLET_PRIMARY_HEATER ); // If the inlet pressure is less than the threshold and TDi and TRo difference is greater than 3 C, the cycle should be canceled if ( ( ppiPressure < MIN_INLET_PRESSURE_PSI ) && ( fabs( THdTemp - TPoTemp ) > MAX_START_STATE_TEMP_SENSORS_DIFF_C ) ) { - prevChemDisinfectState = state; + prevChemDisinfectState = state; alarmDetectedPendingTrigger = ALARM_ID_DG_CHEM_DISINFECT_INLET_PRES_AND_TEMP_SNSRS_OUT; - state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; + state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; } else { // Close VPi to prevent wasting water setValveState( VPI, VALVE_STATE_CLOSED ); - // Request a tare for reservoir 1 - tareReservoir(); - // Set the actuators to drain R1 setValveState( VRD1, VALVE_STATE_OPEN ); setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); @@ -498,10 +500,8 @@ setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); - // TODO turn on the concentrate pumps - // Set the RO pump to run at full pressure - setROPumpTargetFlowRate( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); + setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); // Done with final draining isThisLastDrain = FALSE; @@ -512,8 +512,8 @@ // Assume reservoir 2 is full and drain it rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - // Request a tare for reservoir 2 - tareReservoir(); + tareLoadCell( LOAD_CELL_RESERVOIR_1_PRIMARY ); + tareLoadCell( LOAD_CELL_RESERVOIR_1_BACKUP ); // Done with draining R1 setValveState( VRD1, VALVE_STATE_CLOSED ); @@ -568,18 +568,22 @@ } else { + tareLoadCell( LOAD_CELL_RESERVOIR_2_PRIMARY ); + tareLoadCell( LOAD_CELL_RESERVOIR_2_BACKUP ); + signalDrainPumpHardStop(); setValveState( VRD2, VALVE_STATE_CLOSED ); setValveState( VPI, VALVE_STATE_OPEN ); + stateTrialCounter = 0; - stateTimer = getMSTimerCount(); - state = DG_CHEM_DISINFECT_STATE_FLUSH_DRAIN; + stateTimer = getMSTimerCount(); + state = DG_CHEM_DISINFECT_STATE_FLUSH_DRAIN; } } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; + state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; } return state; @@ -605,15 +609,30 @@ // Check if flush time has elapsed if ( TRUE == didTimeout( stateTimer, FLUSH_DRAIN_WAIT_TIME_MS ) ) { + BOOL hasConductivityPassed = FALSE; + // If the inlet temperature and conductivity are in range, move onto the next state if ( ( getTemperatureValue( TEMPSENSORS_INLET_PRIMARY_HEATER ) > MIN_INLET_TEMPERATURE_C ) && ( getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ) <= MAX_INLET_CONDUCTIVITY_US_PER_CM ) ) { + hasConductivityPassed = TRUE; + } + +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_DISINFECT_CONDUCTIVITY_CHECK ) ) + { + hasConductivityPassed = TRUE; + } +#endif + + if ( TRUE == hasConductivityPassed ) + { setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); - setROPumpTargetFlowRate( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); - stateTimer = getMSTimerCount(); + setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); + + stateTimer = getMSTimerCount(); stateTrialCounter = 0; - state = DG_CHEM_DISINFECT_STATE_FLUSH_CIRCULATION; + state = DG_CHEM_DISINFECT_STATE_FLUSH_CIRCULATION; } // If the number of failures have not exceeded the limit, try again. else if ( stateTrialCounter < MAX_ALLOWED_STATE_TRIALS ) @@ -625,8 +644,8 @@ else { alarmDetectedPendingTrigger = ALARM_ID_DG_CHEM_DISINFECT_INLET_COND_AND_TEMP_OUT; - prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; + prevChemDisinfectState = state; + state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; } } @@ -679,34 +698,40 @@ else { alarmDetectedPendingTrigger = ALARM_ID_DG_TEMP_SENSORS_DIFF_OUT_OF_RANGE; - prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; + prevChemDisinfectState = state; + state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; } } else { areTempSensorsInRange = TRUE; - stateTimer = getMSTimerCount(); - // TODO Turn on the concentrate pumps and wait for 30 seconds + stateTimer = getMSTimerCount(); + + // Set the concentrate pump to run at a constant speed during priming in reverse + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, -1.0F * CONC_PUMP_PRIME_SPEED_ML_PER_MIN ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); } } // Only start the concentrate pumps if the temperature sensors are in range - if ( TRUE == areTempSensorsInRange ) + if ( ( TRUE == areTempSensorsInRange ) && ( TRUE == didTimeout( stateTimer, FLUSH_CICRCULATION_WAIT_TIME_MS ) ) ) { - // TODO: enable the timeout once the concentrate pumps are available. - //if ( TRUE == didTimeout( stateTimer, FLUSH_CICRCULATION_WAIT_TIME_MS ) ) - if ( TRUE ) - { - rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; - rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; + rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; + rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; - setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); - setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); - setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); - stateTimer = getMSTimerCount(); - state = DG_CHEM_DISINFECT_STATE_FLUSH_R1_AND_R2; - } + // Turn off the concentrate pumps + requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); + + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); + setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); + setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); + + // Turn on the bicarb line with forward direction, to dispense the chemical and mix + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, CONC_PUMP_PRIME_SPEED_ML_PER_MIN ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); + + stateTimer = getMSTimerCount(); + state = DG_CHEM_DISINFECT_STATE_FLUSH_R1_AND_R2; } return state; @@ -740,9 +765,9 @@ // until reservoir 2 is filled up and the tubing might expand or leak. if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) { - prevChemDisinfectState = state; + prevChemDisinfectState = state; alarmDetectedPendingTrigger = ALARM_ID_DG_INVALID_LOAD_CELL_VALUE; - state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; + state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } } // Once R1 is full, keep monitoring for R2 level and timeout @@ -764,18 +789,18 @@ // Set both reservoirs status rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; - state = DG_CHEM_DISINFECT_STATE_FLUSH_R2_AND_DRAIN_R1; + state = DG_CHEM_DISINFECT_STATE_FLUSH_R2_AND_DRAIN_R1; } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; + 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; + state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } return state; @@ -814,7 +839,7 @@ else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; + state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; } // First reservoir 2 must be completely full @@ -830,11 +855,11 @@ // 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 ( ( volume >= RSRVRS_PARTIAL_FILL_VOL_ML ) && ( 0 == drainPumpRPM ) ) { - prevChemDisinfectState = state; + prevChemDisinfectState = state; alarmDetectedPendingTrigger = ALARM_ID_DG_INVALID_LOAD_CELL_VALUE; - state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; + state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } } // Once R2 is full, R1 must be partially full @@ -856,20 +881,20 @@ setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); // Start the timer for drain timeout - stateTimer = getMSTimerCount(); + stateTimer = getMSTimerCount(); rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - state = DG_CHEM_DISINFECT_STATE_FLUSH_DRAIN_R2; + state = DG_CHEM_DISINFECT_STATE_FLUSH_DRAIN_R2; } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; + state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; + state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } return state; @@ -901,14 +926,14 @@ setValveState( VRD1, VALVE_STATE_OPEN ); setValveState( VRD2, VALVE_STATE_CLOSED ); // Start the timer for drain timeout - stateTimer = getMSTimerCount(); + stateTimer = getMSTimerCount(); rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - state = DG_CHEM_DISINFECT_STATE_FLUSH_DRAIN_R1; + state = DG_CHEM_DISINFECT_STATE_FLUSH_DRAIN_R1; } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; + state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; } return state; @@ -944,16 +969,16 @@ setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, CONC_PUMP_PRIME_SPEED_ML_PER_MIN ); // The bicarb line is used to inject the acid into the fluid path during chemical disinfect - requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); // TODO why do we need to turn off CP2 while we are going to turn it on immediately? // Start the timer for drain timeout stateTimer = getMSTimerCount(); - state = DG_CHEM_DISINFECT_STATE_PRIME_ACID_LINE; + state = DG_CHEM_DISINFECT_STATE_PRIME_ACID_LINE; } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; + state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; } return state; @@ -975,17 +1000,16 @@ static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectPrimeAcidLineState( void ) { DG_CHEM_DISINFECT_STATE_T state = DG_CHEM_DISINFECT_STATE_PRIME_ACID_LINE; + F32 cd2Conductivity = getConductivityValue( (U32)CONDUCTIVITYSENSORS_CD2_SENSOR ); // Set the chemical disinfect that is published on the UI chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_MIX_WATER_AND_ACID; - F32 cd2Conductivity = getConductivityValue( (U32)CONDUCTIVITYSENSORS_CD2_SENSOR ); - if ( cd2Conductivity <= MIN_ACID_CONDUCTIVITY_US_PER_CM ) { primeAcidSteadyStateCounter = 0; } - else if ( cd2Conductivity > MIN_ACID_CONDUCTIVITY_US_PER_CM ) + else { // Check if the acid conductivity value has been if ( ++primeAcidSteadyStateCounter >= PRIME_ACID_STEADY_CONDUCTIVITY_TIME_MS ) @@ -1004,23 +1028,23 @@ setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); // Turn on the RO pump - setROPumpTargetFlowRate( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); + setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); // Start heating the water while we are filling up the reservoirs setHeaterTargetTemperature( DG_PRIMARY_HEATER, CHEM_DISINFECT_TARGET_TEMPERATURE_C ); startHeater( DG_PRIMARY_HEATER ); rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; - - state = DG_CHEM_DISINFECT_STATE_FILL_WITH_WATER_AND_DISINFECTANT; + state = DG_CHEM_DISINFECT_STATE_FILL_WITH_WATER_AND_DISINFECTANT; } } if ( TRUE == didTimeout( stateTimer, PRIME_ACID_LINE_TIMEOUT_MS ) ) { - // TODO transition to cancellation path - prevChemDisinfectState = state; + prevChemDisinfectState = state; + state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; + alarmDetectedPendingTrigger = ALARM_ID_DG_CHEM_DISINFECT_PRIME_ACID_LINE_TIME_OUT; } return state; @@ -1045,7 +1069,7 @@ DG_CHEM_DISINFECT_STATE_T state = DG_CHEM_DISINFECT_STATE_FILL_WITH_WATER_AND_DISINFECTANT; // Get the flow rate that is used for mixing - F32 measuredROFlowRate = getMeasuredROFlowRate(); + F32 measuredROFlowRate = getMeasuredROFlowRateLPM(); // If the flow is less than the minimum, request the concentrate pump to be on but do // control it. @@ -1058,6 +1082,8 @@ F32 acidCP2PumpFlowRate = ACID_TO_WATER_MIXING_RATIO * measuredROFlowRate * ML_PER_LITER; setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, acidCP2PumpFlowRate ); + + requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); } // First reservoir 1 must be full @@ -1087,27 +1113,27 @@ // Set the drain pump to control mode setDrainPumpTargetOutletPressure( CHEM_DISINFECT_TARGET_DRAIN_PRES_PSI ); - setROPumpTargetFlowRate( CHEM_DISINFECT_TARGET_RO_FLOW_LPM, CHEM_DISINFECT_MAX_RO_PRESSURE_PSI ); + setROPumpTargetFlowRateLPM( CHEM_DISINFECT_TARGET_RO_FLOW_LPM, CHEM_DISINFECT_MAX_RO_PRESSURE_PSI ); // 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 R1ChemDisinfectVol = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); R2ChemDisinfectVol = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); - stateTimer = getMSTimerCount(); + stateTimer = getMSTimerCount(); rsrvrsVolMonitorTimer = getMSTimerCount(); - state = DG_CHEM_DISINFECT_STATE_REMOVE_ACID_BOTTLE_FROM_UI; + state = DG_CHEM_DISINFECT_STATE_REMOVE_ACID_BOTTLE_FROM_UI; } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; + 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; + state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } return state; @@ -1133,6 +1159,7 @@ chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_REMOVE_ACID; // TODO fill up. We should wait for the user until the acid bottle is removed and it is confirmed by the user + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, -1.0F * CONC_PUMP_PRIME_SPEED_ML_PER_MIN ); state = DG_CHEM_DISINFECT_STATE_DISINFECT_R1_TO_R2; return state; @@ -1167,7 +1194,9 @@ break; case CHEM_DISINFECT_COMPLETE: - //TODO turn off CP1 and CP2 + // Turn off the concentrate pumps + requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); + // Set the valves to transfer hot water from R1 to R2 and fill up R2. setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); setValveState( VRD1, VALVE_STATE_OPEN ); @@ -1178,8 +1207,8 @@ // to begin the transition of disinfectant water from R1 to R2. rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; - stateTimer = getMSTimerCount(); - state = DG_CHEM_DISINFECT_STATE_FILL_R2_WITH_DISINFECTANT; + stateTimer = getMSTimerCount(); + state = DG_CHEM_DISINFECT_STATE_FILL_R2_WITH_DISINFECTANT; break; default: @@ -1222,8 +1251,6 @@ R1ChemDisinfectVol = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); R2ChemDisinfectVol = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); - //TODO turn on CP1 and CP2 - state = DG_CHEM_DISINFECT_STATE_DISINFECT_R2_TO_R1; } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) @@ -1266,10 +1293,13 @@ case CHEM_DISINFECT_COMPLETE: // Turn off the heaters - // TODO turn off CP1 and CP2 stopHeater( DG_PRIMARY_HEATER ); stateTimer = getMSTimerCount(); - state = DG_CHEM_DISINFECT_STATE_COOL_DOWN_HEATERS; + state = DG_CHEM_DISINFECT_STATE_COOL_DOWN_HEATERS; + + // Set the disinfect flags + setDisinfectStatus( TRUE ); + setLastDisinfectDate( getRTCTimestamp() ); break; } @@ -1307,8 +1337,9 @@ setValveState( VRD1, VALVE_STATE_OPEN ); rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); + stateTimer = getMSTimerCount(); - state = DG_CHEM_DISINFECT_STATE_DISINFECTANT_DRAIN_R1; + state = DG_CHEM_DISINFECT_STATE_DISINFECTANT_DRAIN_R1; } } @@ -1343,14 +1374,15 @@ setValveState( VRD1, VALVE_STATE_CLOSED ); // Set the drain valve to reservoir 2 setValveState( VRD2, VALVE_STATE_OPEN ); + rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - stateTimer = getMSTimerCount(); - state = DG_CHEM_DISINFECT_STATE_DISINFECTANT_DRAIN_R2; + stateTimer = getMSTimerCount(); + state = DG_CHEM_DISINFECT_STATE_DISINFECTANT_DRAIN_R2; } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; + state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; } return state; @@ -1389,18 +1421,18 @@ setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); - setROPumpTargetFlowRate( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); + setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLUSH_FILL_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; stateTimer = getMSTimerCount(); - state = DG_CHEM_DISINFECT_STATE_RINSE_R1_TO_R2; + state = DG_CHEM_DISINFECT_STATE_RINSE_R1_TO_R2; } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; + state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; } return state; @@ -1432,9 +1464,9 @@ // until reservoir 2 is filled up and the tubing might expand or leak. if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) { - prevChemDisinfectState = state; + prevChemDisinfectState = state; alarmDetectedPendingTrigger = ALARM_ID_DG_INVALID_LOAD_CELL_VALUE; - state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; + state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } } else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) @@ -1452,19 +1484,19 @@ rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; - stateTimer = getMSTimerCount(); - state = DG_CHEM_DISINFECT_STATE_RINSE_R2_TO_R1_AND_DRAIN_R1; + stateTimer = getMSTimerCount(); + state = DG_CHEM_DISINFECT_STATE_RINSE_R2_TO_R1_AND_DRAIN_R1; } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; + 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; + state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } return state; @@ -1501,7 +1533,7 @@ else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; + state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; } // First reservoir 2 must be completely full @@ -1517,11 +1549,11 @@ // 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 ( ( volume >= RSRVRS_PARTIAL_FILL_VOL_ML ) && ( 0 == drainPumpRPM ) ) { - prevChemDisinfectState = state; + prevChemDisinfectState = state; alarmDetectedPendingTrigger = ALARM_ID_DG_INVALID_LOAD_CELL_VALUE; - state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; + state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } } // Once reservoir 2 is completely full, monitor reservoir 1 @@ -1543,19 +1575,19 @@ // Set the reservoir status rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - state = DG_CHEM_DISINFECT_STATE_RINSE_R1_TO_R2_AND_DRAIN_R2; - stateTimer = getMSTimerCount(); + state = DG_CHEM_DISINFECT_STATE_RINSE_R1_TO_R2_AND_DRAIN_R2; + stateTimer = getMSTimerCount(); } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; + state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; + state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } return state; @@ -1593,7 +1625,7 @@ else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; + state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; } // First reservoir 1 must be completely full @@ -1609,11 +1641,11 @@ // 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 ( ( volume >= RSRVRS_PARTIAL_FILL_VOL_ML ) && ( 0 == drainPumpRPM ) ) { - prevChemDisinfectState = state; + prevChemDisinfectState = state; alarmDetectedPendingTrigger = ALARM_ID_DG_INVALID_LOAD_CELL_VALUE; - state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; + state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } } // Once reservoir 1 is completely full, monitor reservoir 2 @@ -1623,22 +1655,28 @@ if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) { - // Done with filling, turn off the RO pump - signalROPumpHardStop(); - - setValveState( VRD2, VALVE_STATE_OPEN ); - // Turn on the drain pump to drain R2 - setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); - // If the number of post chemical disinfect rinses have finished, // transition to drain R1 state. Otherwise, start the next rinse. - if ( ++numberOfPostDisinfectRinses > NUM_OF_POST_DISINFECT_RINSES ) + if ( ++numberOfPostDisinfectRinses >= NUM_OF_POST_DISINFECT_RINSES ) { + // Done with filling, turn off the RO pump + signalROPumpHardStop(); + + // Set the rest of the valve to be in the de-enrgize mode + setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); + setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); + setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); + setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); + setValveState( VRD2, VALVE_STATE_OPEN ); + + // Turn on the drain pump to drain R2 + setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); + // Set the reservoir status - rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; + rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; // This is last drain isThisLastDrain = TRUE; - state = DG_CHEM_DISINFECT_STATE_DRAIN_R2; + state = DG_CHEM_DISINFECT_STATE_DRAIN_R2; } else { @@ -1651,21 +1689,21 @@ rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; - state = DG_CHEM_DISINFECT_STATE_RINSE_R2_TO_R1_AND_DRAIN_R1; + state = DG_CHEM_DISINFECT_STATE_RINSE_R2_TO_R1_AND_DRAIN_R1; } stateTimer = getMSTimerCount(); } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; + 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; + state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } return state; @@ -1720,9 +1758,7 @@ /*********************************************************************//** * @brief * The handleChemicalDisinfectCancelModeWaterPathState function handles the - * chemical disinfect cancel mode cold water path state. The state resets all - * the actuators. - * TODO fill up as the state goes + * chemical disinfect cancel mode cold water path state. * @details Inputs: rsrvr1Status, rsrvr2Status, cancellationMode, stateTimer * @details Outputs: rsrvr1Status, rsrvr2Status, cancellationMode, stateTimer, * chemDisinfectUIState @@ -1741,8 +1777,8 @@ deenergizeActuators(); cancellationMode = CANCELLATION_MODE_WATER; - rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; - rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; + rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; + rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; // The drain is set to start from reservoir 2 setValveState( VRD2, VALVE_STATE_OPEN ); @@ -1769,7 +1805,7 @@ else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; + state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; } // If reservoir 2 has already been drained and reservoir 1 is empty, reset and switch to complete @@ -1786,7 +1822,7 @@ else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; + state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; } } @@ -1862,18 +1898,18 @@ { if ( ++rsrvrFillStableTimeCounter >= RSRVRS_FULL_STABLE_TIME_COUNT ) { - status = DG_RESERVOIR_REACHED_TARGET; + status = DG_RESERVOIR_REACHED_TARGET; rsrvrFillStableTimeCounter = 0; // Set the state timer in case it needs to be used for another timeout check - stateTimer = getMSTimerCount(); + stateTimer = getMSTimerCount(); } } else if ( TRUE == didTimeout( stateTimer, timeout ) ) { // Failed to fill ontime. Update the previous chemical disinfect state and transition to basic cancellation - prevChemDisinfectState = chemDisinfectState; + prevChemDisinfectState = chemDisinfectState; alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_FILL_TIMEOUT; - status = DG_RESERVOIR_NOT_REACHED_TARGET; + status = DG_RESERVOIR_NOT_REACHED_TARGET; } return status; @@ -1897,20 +1933,29 @@ { 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 ] ) + { + initDrainParameters( r ); + haveDrainParamsBeenInit[ r ] = TRUE; + } + BOOL isDrainComplete = hasTargetDrainVolumeBeenReached( r, drainSteadyStateTimeout ); if ( TRUE == isDrainComplete ) { // Set the state timer in case it needs to be used for another timeout check - stateTimer = getMSTimerCount(); - status = DG_RESERVOIR_REACHED_TARGET; + stateTimer = getMSTimerCount(); + haveDrainParamsBeenInit[ r ] = FALSE; + status = DG_RESERVOIR_REACHED_TARGET; } else if ( TRUE == didTimeout( stateTimer, timeout ) ) { // Failed to drain on time. Update the previous chemical disinfect state and transition to basic cancellation - prevChemDisinfectState = chemDisinfectState; - alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_DRAIN_TIMEOUT; - status = DG_RESERVOIR_NOT_REACHED_TARGET; + prevChemDisinfectState = chemDisinfectState; + haveDrainParamsBeenInit[ r ] = FALSE; + alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_DRAIN_TIMEOUT; + status = DG_RESERVOIR_NOT_REACHED_TARGET; } return status; @@ -1931,7 +1976,8 @@ { CHEM_DISINFECT_STATUS_T status = CHEM_DISINFECT_IN_PROGRESS; - F32 ThdTemp = getTemperatureValue( TEMPSENSORS_HEAT_DISINFECT ); + // Update the variables + F32 ThdTemp = getTemperatureValue( TEMPSENSORS_HEAT_DISINFECT ); 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; @@ -1947,9 +1993,9 @@ // If the volume is out of range and it has timed out, exit else if ( TRUE == didTimeout( rsrvrsVolMonitorTimer, RSRVRS_TARGET_VOL_OUT_TIMEOUT_MS ) ) { - areRsrvrsLeaking = FALSE; + areRsrvrsLeaking = FALSE; alarmDetectedPendingTrigger = ALARM_ID_DG_RESERVOIR_LEAK_TIMEOUT; - status = CHEM_DISINFECT_RSRVRS_LEAK_TIMEOUT; + status = CHEM_DISINFECT_RSRVRS_LEAK_TIMEOUT; } } // Reservoirs are in range @@ -1969,8 +2015,8 @@ if ( TRUE == didTimeout( stateTimer, CHEM_DISINFECT_START_TEMP_TIMOUT_MS ) ) { // Heating up to minimum temperature for chemical disinfect failed - alarmDetectedPendingTrigger = ALARM_ID_DG_CHEM_DISINFECT_TARGET_TEMP_TIMEOUT; - status = CHEM_DISINFECT_HEAT_UP_TIMEOUT; + alarmDetectedPendingTrigger = ALARM_ID_DG_CHEM_DISINFECT_TARGET_TEMP_TIMEOUT; + status = CHEM_DISINFECT_HEAT_UP_TIMEOUT; } } else if ( ( isPartialDisinfectInProgress != TRUE ) && ( ThdTemp > CHEM_DISINFECT_TARGET_TEMPERATURE_C ) ) @@ -1984,7 +2030,7 @@ if ( ( TRUE == isPartialDisinfectInProgress ) && ( TRUE == didTimeout( chemDisinfectTimer, CHEM_DISINFECT_TIME_MS ) ) ) { // Done with this stage of chemical disnfect. Reset the variables - status = CHEM_DISINFECT_COMPLETE; + status = CHEM_DISINFECT_COMPLETE; isPartialDisinfectInProgress = FALSE; } @@ -2041,4 +2087,77 @@ } } +/*********************************************************************//** + * @brief + * The monitorModeChemicalDisinfect 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: chemDisinfectState + * @details Outputs: prevChemDisinfectState, chemDisinfectState, + * alarmDetectedPendingTrigger + * @return: none + *************************************************************************/ +static void monitorModeChemicalDisinfect( void ) +{ + BOOL isAlarmNeeded = FALSE; + + switch( chemDisinfectState ) + { + case DG_CHEM_DISINFECT_STATE_START: + case DG_CHEM_DISINFECT_STATE_DRAIN_R1: + case DG_CHEM_DISINFECT_STATE_DRAIN_R2: + case DG_CHEM_DISINFECT_STATE_FLUSH_DRAIN: + case DG_CHEM_DISINFECT_STATE_FLUSH_CIRCULATION: + case DG_CHEM_DISINFECT_STATE_FLUSH_R1_AND_R2: + case DG_CHEM_DISINFECT_STATE_FLUSH_R2_AND_DRAIN_R1: + case DG_CHEM_DISINFECT_STATE_FLUSH_DRAIN_R2: + case DG_CHEM_DISINFECT_STATE_FLUSH_DRAIN_R1: + if ( ( STATE_OPEN == getSwitchStatus( CONCENTRATE_CAP ) ) || ( STATE_OPEN == getSwitchStatus( DIALYSATE_CAP ) ) ) + { + isAlarmNeeded = TRUE; + } + break; + + case DG_CHEM_DISINFECT_STATE_PRIME_ACID_LINE: + case DG_CHEM_DISINFECT_STATE_FILL_WITH_WATER_AND_DISINFECTANT: + if ( ( STATE_CLOSED == getSwitchStatus( CONCENTRATE_CAP ) ) || ( STATE_OPEN == getSwitchStatus( DIALYSATE_CAP ) ) ) + { + isAlarmNeeded = TRUE; + } + break; + + case DG_CHEM_DISINFECT_STATE_DISINFECT_R1_TO_R2: + case DG_CHEM_DISINFECT_STATE_FILL_R2_WITH_DISINFECTANT: + case DG_CHEM_DISINFECT_STATE_DISINFECT_R2_TO_R1: + case DG_CHEM_DISINFECT_STATE_DISINFECTANT_DRAIN_R1: + case DG_CHEM_DISINFECT_STATE_DISINFECTANT_DRAIN_R2: + case DG_CHEM_DISINFECT_STATE_RINSE_R1_TO_R2: + case DG_CHEM_DISINFECT_STATE_RINSE_R2_TO_R1_AND_DRAIN_R1: + case DG_CHEM_DISINFECT_STATE_RINSE_R1_TO_R2_AND_DRAIN_R2: + case DG_CHEM_DISINFECT_STATE_RINSE_CIRCULATION: + case DG_CHEM_DISINFECT_STATE_COMPLETE: + if ( ( STATE_OPEN == getSwitchStatus( CONCENTRATE_CAP ) ) || ( STATE_OPEN == getSwitchStatus( DIALYSATE_CAP ) ) ) + { + isAlarmNeeded = TRUE; + } + break; + } + +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_CAPS_MONITOR ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { + if ( TRUE == isAlarmNeeded ) + { + // Set the variables to fail and go to cancel water path. Set the pending alarm to no alarm so the cancel water path + // will not be raising the alarm at end of the cancel water path. The recoverable alarm is raised here in this function + U32 ConcCap = (U32)getSwitchStatus( CONCENTRATE_CAP ); + U32 DialysateCap = (U32)getSwitchStatus( DIALYSATE_CAP ); + prevChemDisinfectState = chemDisinfectState; + chemDisinfectState = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; + alarmDetectedPendingTrigger = ALARM_ID_DG_DIALYSATE_OR_CONC_CAP_NOT_IN_PROPER_POSITION; + } + } +} + /**@}*/