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