Index: firmware/App/Modes/ModeChemicalDisinfect.c =================================================================== diff -u -ra683ad9f7451beffab6c2b6b8c1049c4c167a6dc -r0c3dbf78f9cef9cc5fc424f7d930882bffb8779a --- firmware/App/Modes/ModeChemicalDisinfect.c (.../ModeChemicalDisinfect.c) (revision a683ad9f7451beffab6c2b6b8c1049c4c167a6dc) +++ firmware/App/Modes/ModeChemicalDisinfect.c (.../ModeChemicalDisinfect.c) (revision 0c3dbf78f9cef9cc5fc424f7d930882bffb8779a) @@ -60,6 +60,10 @@ // Flush drain path state defines #define FLUSH_DRAIN_WAIT_TIME_MS ( 60 * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. +// Deprime acid line state defines +#define DEPRIME_ACID_LINE_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Deprime acid line timeout in milliseconds. +#define DEPRIME_ACID_LINE_ACID_CONC_PUMP_SPEED_MLPM 30.0F ///< Deprime acid line acid concentrate pump speed in mL/min. + // Flush circulation path state defines #define RO_PUMP_TARGET_FLUSH_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. @@ -87,15 +91,15 @@ #define RO_PUMP_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 #define DISINFECTANT_MIX_RATIO_PRIME 19.0F ///< Disinfectant mixing ratio during prime, water/disinfectant. +#define PRIME_ACID_MINIMUM_PRIME_TIMEOUT_MS ( 20 * MS_PER_SECOND ) ///< Prime acid minimum prime timeout in milliseconds. // Stabilize disinfectant mixing state defines -#define MAX_ALLOWED_DISINFECTANT_FLUSH_PERIODS 2 ///< Number of allowed periods to check conductivity and temperature in disinfectant flush state +#define MAX_ALLOWED_DISINFECTANT_FLUSH_PERIODS 4 ///< Number of allowed periods to check conductivity and temperature in disinfectant flush state #define DISINFECTANT_PUMP_FILL_SPEED_ML_PER_MIN 7.61F ///< Default concentrate pump speed for mixing disinfectant. #define DISINFECTANT_MIX_RATIO_FILL 65.67F ///< Disinfectant mixing ratio during fill, water/disinfectant. #define RO_PUMP_FILL_DISINECTANT_FLOW_RATE_LPM 0.4F ///< 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_MS ( 30 * MS_PER_SECOND ) ///< Initial time to wait for temperature and conductivity to reach target in disinfectant flush state in milliseconds. -#define FLUSH_DISINFECTANT_ADDITIONAL_WAIT_TIME_MS ( 60 * MS_PER_SECOND ) ///< Additional time to wait for temperature and conductivity to reach target in disinfectant flush state +#define FLUSH_DISINFECTANT_TIMEOUT_MS ( 30 * MS_PER_SECOND ) ///< Flush disinfectant temperature and conductivity to reach target in disinfectant flush state in milliseconds. // Parameters during disinfect defines #define CHEM_DISINFECT_TARGET_RO_FLOW_LPM 0.5F ///< Chemical disinfect target RO flow rate in L/min. @@ -130,17 +134,30 @@ #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 +#define ACID_MOVING_AVG_NUM_OF_SAMPLES 30 ///< Acid moving average number of samples. +#define ACID_DATA_COLLECTION_TIMEOUT_MS ( 0.5F * MS_PER_SECOND ) ///< Acid data collection timeout in milliseconds. + /// Non-volatile write structure typedef struct { BOOL hasDisStatusBeenWrittenToNV; ///< Boolean flag to indicate whether the disinfect status been written to NV or not. } DISINFECT_NV_OPS_T; +/// Acid status data structure +typedef struct +{ + BOOL acidDataColHasTimerBeenSet; ///< Acid has data collection timer started boolean flag. + U32 acidDataColStartTimeMS; ///< Acid data collection start time in milliseconds. + F32 acidCondRunningSumUSPCM; ///< Acid conductivity running sum in uS/cm. + F32 acidCondAvgUSPCM; ///< Acid conductivity average in uS/cm. + F32 acidCondSamplesUSPCM[ ACID_MOVING_AVG_NUM_OF_SAMPLES ]; ///< Acid conductivity samples array in uS/cm. + U32 acidCondSamplesNextIndex; ///< Acid conductivity sample next index number. +} ACID_DATA_STATUS_T; + // ********** private data ********** static DG_CHEM_DISINFECT_STATE_T chemDisinfectState; ///< Currently active chemical disinfect state. static DG_CHEM_DISINFECT_STATE_T prevChemDisinfectState; ///< Previous active heat disinfect state before alarm. -static DG_CHEM_DISINFECT_UI_STATE_T chemDisinfectUIState; ///< Currently active chemical disinfect UI state. static U32 overallChemDisinfectTimer; ///< Chemical disinfect cycle total timer. static U32 stateTimer; ///< Chemical disinfect state timer to be used in different states. static U32 stateTrialCounter; ///< Chemical disinfect state trial counter to be used for retries in different states. @@ -158,7 +175,6 @@ static CANCELLATION_MODE_T cancellationMode; ///< Cancellation mode. static ALARM_ID_T alarmDetectedPendingTrigger; ///< Chemical disinfect alarm to raise. static U32 flushCircWaitTime; ///< Variable time period in ms to wait in flush circulation state to check sensor values. -static U32 flushDisinfectantWaitTime; ///< Variable time period in ms to wait in disinfectant flush state to check sensor values. static U32 primeAcidSteadyStateCounter; ///< Prime acid steady state counter. static U32 rsrvrFillStableTimeCounter; ///< Task interval timer/counter for determining if reservoir has reached fill target. static U32 rsrvrFillToFullStableTimeCounter; ///< Task interval timer/counter for determining if reservoir is full. @@ -169,6 +185,7 @@ static BOOL haveDrainParamsBeenInit[ NUM_OF_DG_RESERVOIRS ]; ///< Boolean flag to indicate whether the drain parameters have been reset or not. static U32 maxTemperatureOutOfRangeStartTimeMS; ///< Maximum temperature out of range start time in milliseconds. static U32 maxCondOutOfRangeStartTimeMS; ///< Maximum conductivity out of range start time in milliseconds. +static ACID_DATA_STATUS_T acidDataStatus; ///< Acid data status. #ifndef _RELEASE_ /* Nelson Labs is in charge of testing the efficacy of the disinfects (heat and chem). The codes that contain the name Nelson are used to @@ -184,6 +201,7 @@ static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectDrainR1State( void ); static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectDrainR2State( void ); static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectFlushDrainState( void ); +static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectDeprimeAcidLine( void ); static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectFlushCirculationState( void ); static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectPrimeDisinfectantState( void ); static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectDisinfectantFlushState( void ); @@ -206,6 +224,8 @@ static void publishChemicalDisinfectData( void ); static void monitorModeChemicalDisinfect( void ); static void writeDisinfectDataToNV( DG_USAGE_INFO_ITEMS_T info ); +static void processAcidConductivityData( void ); +static BOOL isAcidCondOutOfRange( void ); #ifndef _RELEASE_ static void setNelsonSupportConditions( void ); @@ -221,14 +241,14 @@ * rsrvr1Status, rsrvr2Status, overallChemDisinfectTimer, cancellationMode, * rsrvrFillToFullStableTimeCounter, primeAcidSteadyStateCounter, isRsrvrLeaking, * chemDisinfectReservoirTime, ischemDisinfectWarmupTargetReached, - * isChemDisinfectTempAboveTarget, chemDisinfectUIState, isRsrvrLeaking, + * isChemDisinfectTempAboveTarget, isRsrvrLeaking, * disinfectNVOps.hasDisStatusBeenWrittenToNV, rsrvrsVolMonitorCounter, * DisinfectCycleCounter, drpControlTimerCounter, dataPublishCounter, - * alarmDetectedPendingTrigger, flushCircWaitTime, flushDisinfectantWaitTime + * alarmDetectedPendingTrigger, flushCircWaitTime, acidDataStatus * primeAcidSteadyStateCounter, rsrvrFillStableTimeCounter, R1FullVolume, * rsrvrFillToFullStableTimeCounter, R2FullVolume, disinfectantMixRatio, * haveDrainParamsBeenInit[ DG_RESERVOIR_1 ], haveDrainParamsBeenInit[ DG_RESERVOIR_2 ], - * maxTemperatureOutOfRangeStartTimeMS, maxCondOutOfRangeStartTimeMS + * maxTemperatureOutOfRangeStartTimeMS, maxCondOutOfRangeStartTimeMS, * @return none *************************************************************************/ void initChemicalDisinfectMode( void ) @@ -237,7 +257,7 @@ for ( rsrvr = DG_RESERVOIR_1; rsrvr < NUM_OF_DG_RESERVOIRS; rsrvr++ ) { - haveDrainParamsBeenInit[ rsrvr ] = FALSE; + haveDrainParamsBeenInit[ rsrvr ] = FALSE; } chemDisinfectState = DG_CHEM_DISINFECT_STATE_START; @@ -256,7 +276,6 @@ chemDisinfectReservoirTime = 0; ischemDisinfectWarmupTargetReached = FALSE; isChemDisinfectTempAboveTarget = FALSE; - chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_NOT_RUNNING; disinfectNVOps.hasDisStatusBeenWrittenToNV = FALSE; isRsrvrLeaking = FALSE; rsrvrsVolMonitorCounter = 0; @@ -265,20 +284,24 @@ dataPublishCounter = 0; alarmDetectedPendingTrigger = ALARM_ID_NO_ALARM; flushCircWaitTime = 0; - flushDisinfectantWaitTime = 0; rsrvrFillStableTimeCounter = 0; rsrvrFillToFullStableTimeCounter = 0; R1FullVolume = 0.0F; R2FullVolume = 0.0F; disinfectantMixRatio = 0.0F; maxTemperatureOutOfRangeStartTimeMS = getMSTimerCount(); maxCondOutOfRangeStartTimeMS = getMSTimerCount(); + acidDataStatus.acidDataColHasTimerBeenSet = FALSE; + acidDataStatus.acidCondAvgUSPCM = 0.0F; + acidDataStatus.acidDataColHasTimerBeenSet = getMSTimerCount(); + acidDataStatus.acidCondRunningSumUSPCM = 0.0F; + acidDataStatus.acidCondSamplesNextIndex = 0; + memset( acidDataStatus.acidCondSamplesUSPCM, 0x0, sizeof( F32 ) * ACID_MOVING_AVG_NUM_OF_SAMPLES ); + #ifndef _RELEASE_ setNelsonSupportConditions(); #endif - - requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID, PARK_CONC_PUMPS ); } /*********************************************************************//** @@ -321,6 +344,8 @@ *************************************************************************/ U32 execChemicalDisinfectMode( void ) { + processAcidConductivityData(); + // The inlet pressure shall be checked all the time as long as VPi is open checkInletWaterPressure(); @@ -352,6 +377,10 @@ chemDisinfectState = handleChemicalDisinfectFlushDrainState(); break; + case DG_CHEM_DISINFECT_STATE_DEPRIME_ACID_LINE: + chemDisinfectState = handleChemicalDisinfectDeprimeAcidLine(); + break; + case DG_CHEM_DISINFECT_STATE_FLUSH_CIRCULATION: chemDisinfectState = handleChemicalDisinfectFlushCirculationState(); break; @@ -459,16 +488,13 @@ * @details Inputs: alarm, rsrvrFillStableTimeCounter, rsrvr1Status, * stateTimer * @details Outputs: alarm, rsrvrFillStableTimeCounter, rsrvr1Status, - * stateTimer, chemDisinfectUIState + * stateTimer * @return next state of the chemical disinfect state machine *************************************************************************/ static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectStartState( void ) { DG_CHEM_DISINFECT_STATE_T state = DG_CHEM_DISINFECT_STATE_START; - // Set the chemical disinfect state that is published on the UI - chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_FLUSH_BEFORE_DISINFECT; - if ( FALSE == isAlarmActive( ALARM_ID_DG_CHEM_DISINFECT_INSERT_ACID ) ) { if ( ( STATE_CLOSED == getSwitchStatus( CONCENTRATE_CAP ) ) || ( STATE_OPEN == getSwitchStatus( DIALYSATE_CAP ) ) ) @@ -501,7 +527,7 @@ * 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: rsrvr1Status, rsrvr2Status, chemDisinfectUIState + * @details Outputs: rsrvr1Status, rsrvr2Status * @return next state of the chemical disinfect state machine *************************************************************************/ static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectDrainR1State( void ) @@ -547,8 +573,7 @@ * transition is finished within the time, it transitions to the next * state, otherwise, it transitions to basic cancellation path. * @details Inputs: stateTimer, rsrvr2Status, isThisLastDrain - * @details Outputs: stateTimer, rsrvr2Status, stateTrialCounter, - * chemDisinfectUIState + * @details Outputs: stateTimer, rsrvr2Status, stateTrialCounter * @return next state of the chemical disinfect state machine *************************************************************************/ static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectDrainR2State( void ) @@ -602,10 +627,8 @@ * period of time and then measures the temperature and conductivity of * water. If they are not within the range, it transitions to basic * cancellation path, otherwise it transitions to the next state. - * @details Inputs: stateTimer, stateTrialCounter, alarm, - * prevChemDisinfectState - * @details Outputs: stateTimer, stateTrialCounter, alarm, - * prevChemDisinfectState + * @details Inputs: stateTimer + * @details Outputs: stateTimer * @return next state of the chemical disinfect state machine *************************************************************************/ static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectFlushDrainState( void ) @@ -623,7 +646,34 @@ startHeater( DG_PRIMARY_HEATER ); // The UV reactors will be on for the entire disinfect cycle turnOnUVReactor( OUTLET_UV_REACTOR ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, DEPRIME_ACID_LINE_ACID_CONC_PUMP_SPEED_MLPM ); + // Turn on the concentrate pumps + requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); + stateTimer = getMSTimerCount(); + state = DG_CHEM_DISINFECT_STATE_DEPRIME_ACID_LINE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleChemicalDisinfectDeprimeAcidLine function handles the chemical + * disinfect deprime acid line state. In this state the acid pump is run for + * a couple of seconds to remove the residual fluid from the acid line to + * prevent any leaks from the acid port. + * @details Inputs: stateTimer + * @details Outputs: stateTimer, flushCircWaitTime + * @return next state of the chemical disinfect state machine + *************************************************************************/ +static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectDeprimeAcidLine( void ) +{ + DG_CHEM_DISINFECT_STATE_T state = DG_CHEM_DISINFECT_STATE_DEPRIME_ACID_LINE; + + if ( TRUE == didTimeout( stateTimer, DEPRIME_ACID_LINE_TIMEOUT_MS ) ) + { + requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID, PARK_CONC_PUMPS ); flushCircWaitTime = FLUSH_CICRCULATION_INITIAL_WAIT_TIME_MS; stateTimer = getMSTimerCount(); state = DG_CHEM_DISINFECT_STATE_FLUSH_CIRCULATION; @@ -662,13 +712,13 @@ } #endif - F32 avgTemp = ( TPoTemp + TD2Temp ) / NUM_OF_TEMP_SENSORS_TO_AVG; - F32 cd2Conductivity = getConductivityValue( (U32)CONDUCTIVITYSENSORS_CD2_SENSOR ); - F32 cpoConductivity = getConductivityValue( (U32)CONDUCTIVITYSENSORS_CPO_SENSOR ); - BOOL isTPoOut = FALSE; - BOOL isTD2Out = FALSE; - BOOL isCD2Out = FALSE; - BOOL isCPoOut = FALSE; + F32 avgTemp = ( TPoTemp + TD2Temp ) / NUM_OF_TEMP_SENSORS_TO_AVG; + F32 cd2CondUSPCM = getConductivityValue( (U32)CONDUCTIVITYSENSORS_CD2_SENSOR ); + F32 cpoCondUSPCM = getConductivityValue( (U32)CONDUCTIVITYSENSORS_CPO_SENSOR ); + BOOL isTPoOut = FALSE; + BOOL isTD2Out = FALSE; + BOOL isCD2Out = FALSE; + BOOL isCPoOut = FALSE; #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_TEMPERATURE_SENSORS_ALARM ) != SW_CONFIG_ENABLE_VALUE ) @@ -678,11 +728,8 @@ isTD2Out = ( fabs( TD2Temp - avgTemp ) > MAX_FLUSH_CIRC_TEMP_SENSOR_DIFF_C ? TRUE : FALSE ); } - if ( getTestConfigStatus( TEST_CONFIG_MIX_WITH_WATER ) != TRUE ) - { - isCD2Out = ( cd2Conductivity > MAX_FLUSH_CIRC_CONDUCTIVITY_US_PER_CM ? TRUE : FALSE ); - isCPoOut = ( cpoConductivity > MAX_FLUSH_CIRC_CONDUCTIVITY_US_PER_CM ? TRUE : FALSE ); - } + isCD2Out = ( cd2CondUSPCM > MAX_FLUSH_CIRC_CONDUCTIVITY_US_PER_CM ? TRUE : FALSE ); + isCPoOut = ( cpoCondUSPCM > MAX_FLUSH_CIRC_CONDUCTIVITY_US_PER_CM ? TRUE : FALSE ); // Check if any of the temperature sensors are out of tolerance if( ( TRUE == isTPoOut ) || ( TRUE == isTD2Out ) || ( TRUE == isCD2Out ) || ( TRUE == isCPoOut ) ) @@ -695,17 +742,15 @@ flushCircWaitTime = FLUSH_CICRCULATION_ADDITIONAL_WAIT_TIME_MS; } else - { // State failed. Cancel chemical disinfect mode + { + alarmDetectedPendingTrigger = ALARM_ID_DG_CLEANING_MODE_COND_SENSORS_OUT_OF_RANGE; + + // 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 ) ) { alarmDetectedPendingTrigger = ALARM_ID_DG_CLEANING_MODE_TEMP_SENSORS_DIFF_OUT_OF_RANGE; } - else - { - alarmDetectedPendingTrigger = ALARM_ID_DG_CLEANING_MODE_COND_SENSORS_OUT_OF_RANGE; - } - prevChemDisinfectState = state; state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } @@ -719,6 +764,7 @@ disinfectantMixRatio = DISINFECTANT_MIX_RATIO_PRIME; primeAcidSteadyStateCounter = 0; + stateTrialCounter = 0; state = DG_CHEM_DISINFECT_STATE_PRIME_DISINFECTANT; stateTimer = getMSTimerCount(); } @@ -737,48 +783,49 @@ * cancellation path. * @details Inputs: stateTimer, primeAcidSteadyStateCounter * @details Outputs: stateTimer, prevChemDisinfectState, - * primeAcidSteadyStateCounter, chemDisinfectUIState + * primeAcidSteadyStateCounter * @return next state of the chemical disinfect state machine *************************************************************************/ static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectPrimeDisinfectantState( void ) { DG_CHEM_DISINFECT_STATE_T state = DG_CHEM_DISINFECT_STATE_PRIME_DISINFECTANT; - F32 cd2Conductivity = getConductivityValue( (U32)CONDUCTIVITYSENSORS_CD2_SENSOR ); - chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_MIX_WATER_AND_ACID; - handleDisinfectantMixing( getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) * ML_PER_LITER, disinfectantMixRatio ); + if ( TRUE == didTimeout( stateTimer, PRIME_ACID_MINIMUM_PRIME_TIMEOUT_MS ) ) + { #ifndef _RELEASE_ - if ( nelsonSupport != NELSON_CHEM_DISINFECT ) + if ( nelsonSupport != NELSON_CHEM_DISINFECT ) #endif - { - if ( cd2Conductivity < MIN_PRIME_ACID_CONDUCTIVITY_US_PER_CM ) { - primeAcidSteadyStateCounter = 0; + if ( acidDataStatus.acidCondAvgUSPCM < MIN_PRIME_ACID_CONDUCTIVITY_US_PER_CM ) + { + primeAcidSteadyStateCounter = 0; + } } + + // Check if the acid conductivity value has been above the threshold for the specified time period + if ( ( ++primeAcidSteadyStateCounter >= PRIME_ACID_STEADY_CONDUCTIVITY_TASK_INT ) || + ( TRUE == getTestConfigStatus( TEST_CONFIG_MIX_WITH_WATER ) ) ) + { + // Turn off the concentrate pump + requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); + // Turn on the RO pump and concentrate pump to the disinfectant fill rates + setROPumpTargetFlowRateLPM( CHEM_DISINFECT_TARGET_RO_FLOW_LPM, MAX_RO_PUMP_FILL_DISINFECTANT_PRESSURE_PSI ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, DISINFECTANT_PUMP_FILL_SPEED_ML_PER_MIN ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); + stateTrialCounter = 0; + disinfectantMixRatio = DISINFECTANT_MIX_RATIO_FILL; + stateTimer = getMSTimerCount(); + state = DG_CHEM_DISINFECT_STATE_DISINFECTANT_FLUSH; + } + else if ( TRUE == didTimeout( stateTimer, PRIME_ACID_LINE_TIMEOUT_MS ) ) + { + prevChemDisinfectState = state; + state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; + alarmDetectedPendingTrigger = ALARM_ID_DG_CHEM_DISINFECT_PRIME_ACID_LINE_TIME_OUT; + } } - // Check if the acid conductivity value has been above the threshold for the specified time period - if ( ( ++primeAcidSteadyStateCounter >= PRIME_ACID_STEADY_CONDUCTIVITY_TASK_INT ) || - ( TRUE == getTestConfigStatus( TEST_CONFIG_MIX_WITH_WATER ) ) ) - { - // Turn off the concentrate pump - requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); - // Turn on the RO pump and concentrate pump to the disinfectant fill rates - setROPumpTargetFlowRateLPM( CHEM_DISINFECT_TARGET_RO_FLOW_LPM, MAX_RO_PUMP_FILL_DISINFECTANT_PRESSURE_PSI ); - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, DISINFECTANT_PUMP_FILL_SPEED_ML_PER_MIN ); - requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); - disinfectantMixRatio = DISINFECTANT_MIX_RATIO_FILL; - flushDisinfectantWaitTime = FLUSH_DISINFECTANT_INITIAL_WAIT_TIME_MS; - stateTimer = getMSTimerCount(); - state = DG_CHEM_DISINFECT_STATE_DISINFECTANT_FLUSH; - } - if ( TRUE == didTimeout( stateTimer, PRIME_ACID_LINE_TIMEOUT_MS ) ) - { - prevChemDisinfectState = state; - state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; - alarmDetectedPendingTrigger = ALARM_ID_DG_CHEM_DISINFECT_PRIME_ACID_LINE_TIME_OUT; - } return state; } @@ -794,42 +841,32 @@ * reached within the defined period of time, it transition to a cancellation path. * @details Inputs: stateTimer, primeAcidSteadyStateCounter, * temperature, conductivity - * @details Outputs: stateTimer, prevChemDisinfectState, chemDisinfectUIState, - * alarm + * @details Outputs: stateTimer, prevChemDisinfectState, alarm * @return next state of the chemical disinfect state machine *************************************************************************/ static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectDisinfectantFlushState( void ) { DG_CHEM_DISINFECT_STATE_T state = DG_CHEM_DISINFECT_STATE_DISINFECTANT_FLUSH; - chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_MIX_WATER_AND_ACID; - writeDisinfectDataToNV( USAGE_INFO_CHEM_DIS_START ); handleDisinfectantMixing( getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) * ML_PER_LITER, disinfectantMixRatio ); - if ( TRUE == didTimeout( stateTimer, flushDisinfectantWaitTime ) ) + if ( TRUE == didTimeout( stateTimer, ( ( stateTrialCounter + 1 ) * FLUSH_DISINFECTANT_TIMEOUT_MS ) ) ) { - F32 cd2Cond = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); - BOOL isCD2OutOfRange = ( ( cd2Cond < MIN_DISINFECT_CONDUCTIVITY_US_PER_CM || cd2Cond > MAX_DISINFECT_CONDUCTIVITY_US_PER_CM ) ? TRUE : FALSE ); + BOOL isCD2OutOfRange = isAcidCondOutOfRange(); - if ( getTestConfigStatus( TEST_CONFIG_MIX_WITH_WATER ) != TRUE ) + if ( TRUE == getTestConfigStatus( TEST_CONFIG_MIX_WITH_WATER ) ) { isCD2OutOfRange = FALSE; } if ( TRUE == isCD2OutOfRange ) { - // The conditions have not been met - // Check if we have exceeded the number of trials. If not, try another time - if ( ++stateTrialCounter < MAX_ALLOWED_DISINFECTANT_FLUSH_PERIODS ) + if ( ++stateTrialCounter >= MAX_ALLOWED_DISINFECTANT_FLUSH_PERIODS ) { - stateTimer = getMSTimerCount(); - flushDisinfectantWaitTime = FLUSH_DISINFECTANT_ADDITIONAL_WAIT_TIME_MS; + stateTimer = getMSTimerCount(); + state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; } - else - { - state = DG_CHEM_DISINFECT_STATE_FILL_WITH_DISINFECTANT; - } } else { @@ -871,8 +908,6 @@ { DG_CHEM_DISINFECT_STATE_T state = DG_CHEM_DISINFECT_STATE_FILL_WITH_DISINFECTANT; - chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_DISINFECT_DEVICE; - handleDisinfectantMixing( getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) * ML_PER_LITER, disinfectantMixRatio ); // First reservoir 1 must be full @@ -927,15 +962,13 @@ * transitions to the next state. * @details Inputs: stateTimer, rsrvr1Status, rsrvr2Status * @details Outputs: stateTimer, rsrvr1Status, rsrvr2Status, - * chemDisinfectUIState, prevChemDisinfectState + * prevChemDisinfectState * @return next state of the chemical disinfect state machine *************************************************************************/ static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectDisinfectR1ToR2State( void ) { DG_CHEM_DISINFECT_STATE_T state = DG_CHEM_DISINFECT_STATE_DISINFECT_R1_TO_R2; - chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_DISINFECT_DEVICE; - handleDisinfectantMixing( getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) * ML_PER_LITER, disinfectantMixRatio ); chemicalDisinfectTimerUpdate(); @@ -985,7 +1018,7 @@ * If reservoir 2 is filled within the specified time, it * transitions to the next state. * @details Inputs: stateTimer, rsrvr2Status - * @details Outputs: stateTimer, chemDisinfectUIState + * @details Outputs: stateTimer * @return next state of the chemical disinfect state machine *************************************************************************/ static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectPartialDrainR1FillR2ToR1State( void ) @@ -1031,15 +1064,12 @@ * transitions to the next state. * @details Inputs: stateTimer, rsrvr1Status, rsrvr2Status * @details Outputs: stateTimer, rsrvr1Status, rsrvr2Status, - * chemDisinfectUIState * @return next state of the chemical disinfect state machine *************************************************************************/ static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectDisinfectR2ToR1State( void ) { DG_CHEM_DISINFECT_STATE_T state = DG_CHEM_DISINFECT_STATE_DISINFECT_R2_TO_R1; - chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_DISINFECT_DEVICE; - handleDisinfectantMixing( getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) * ML_PER_LITER, disinfectantMixRatio ); chemicalDisinfectTimerUpdate(); @@ -1084,10 +1114,9 @@ initDrainParameters( DG_RESERVOIR_2 ); rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - isThisLastDrain = TRUE; - chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_FLUSH_AFTER_DISINFECT; - stateTimer = getMSTimerCount(); - state = DG_CHEM_DISINFECT_STATE_DRAIN_R1; + isThisLastDrain = TRUE; + stateTimer = getMSTimerCount(); + state = DG_CHEM_DISINFECT_STATE_DRAIN_R1; #ifndef _RELEASE_ if ( NELSON_CHEM_DISINFECT == nelsonSupport ) @@ -1128,7 +1157,7 @@ * If reservoir 1 is filled within the specified time, it * transitions to the next state. * @details Inputs: stateTimer, rsrvr1Status - * @details Outputs: stateTimer, chemDisinfectUIState + * @details Outputs: stateTimer * @return next state of the chemical disinfect state machine *************************************************************************/ static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectPartialDrainR2FillR1ToR2State( void ) @@ -1171,15 +1200,14 @@ * chemical disinfect cancel mode basic path state. The state sets the state * to complete and raises an alarm. * @details Inputs: none - * @details Outputs: cancellationMode, chemDisinfectUIState + * @details Outputs: cancellationMode * @return next state of the heat disinfect state machine *************************************************************************/ static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectCancelModeBasicPathState( void ) { DG_CHEM_DISINFECT_STATE_T state = DG_CHEM_DISINFECT_STATE_CANCEL_BASIC_PATH; - chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_CANCEL_DISINFECT; - cancellationMode = CANCELLATION_MODE_BASIC; + cancellationMode = CANCELLATION_MODE_BASIC; failChemicalDisinfect(); @@ -1192,16 +1220,13 @@ * chemical disinfect cancel mode cold water path state. It drains the reservoirs * before the cancel basic path mode is entered. * @details Inputs: rsrvr1Status, rsrvr2Status, cancellationMode, stateTimer - * @details Outputs: rsrvr1Status, rsrvr2Status, cancellationMode, stateTimer, - * chemDisinfectUIState + * @details Outputs: rsrvr1Status, rsrvr2Status, cancellationMode, stateTimer * @return next state of the chemical disinfect state machine *************************************************************************/ static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectCancelModeWaterPathState( void ) { DG_CHEM_DISINFECT_STATE_T state = DG_CHEM_DISINFECT_STATE_CANCEL_WATER_PATH; - chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_CANCEL_DISINFECT; - if ( CANCELLATION_MODE_NONE == cancellationMode ) { // Stop all the actuators first then decide who should run next @@ -1265,15 +1290,13 @@ * disinfect complete state. The state stops chemical disinfect and * requests transition to mode standby. * @details Inputs: none - * @details Outputs: chemDisinfectUIState + * @details Outputs: none * @return next state of the chemical disinfect state machine *************************************************************************/ static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectCompleteState( void ) { DG_CHEM_DISINFECT_STATE_T state = DG_CHEM_DISINFECT_STATE_COMPLETE; - chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_COMPLETE; - #ifndef _RELEASE_ if ( nelsonSupport != NELSON_NONE ) { @@ -1610,6 +1633,7 @@ data.overallElapsedTime = calcTimeSince( overallChemDisinfectTimer ); data.stateElapsedTime = calcTimeSince( stateTimer ); data.cancellationMode = (U32)cancellationMode; + data.acidAvgCondUSPCM = acidDataStatus.acidCondAvgUSPCM; //If the mode is in the actual chemical disinfect states, publish the elapsed time, otherwise publish 0 to avoid confusion if ( chemDisinfectState > DG_CHEM_DISINFECT_STATE_FLUSH_DRAIN ) @@ -1626,8 +1650,6 @@ data.R2FillLevel = 0.0F; } - data.chemDisinfectUIState = chemDisinfectUIState; - // General data publish channel broadcastData( MSG_ID_DG_CHEM_DISINFECT_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( MODE_CHEMICAL_DISINFECT_DATA_T ) ); @@ -1722,9 +1744,8 @@ if ( ( chemDisinfectState >= DG_CHEM_DISINFECT_STATE_DISINFECTANT_FLUSH ) && ( chemDisinfectState <= DG_CHEM_DISINFECT_STATE_PARTIAL_DRAIN_R2_FILL_R1_TO_R2 ) ) { // Disinfect conditions check - F32 cd2CondUSCM = getConductivityValue( (U32)CONDUCTIVITYSENSORS_CD2_SENSOR ); F32 TPoTemp = getTemperatureValue( TEMPSENSORS_OUTLET_PRIMARY_HEATER ); - BOOL isCD2OutofRange = ( ( cd2CondUSCM < MIN_DISINFECT_CONDUCTIVITY_US_PER_CM ) || ( cd2CondUSCM > MAX_DISINFECT_CONDUCTIVITY_US_PER_CM ) ? TRUE : FALSE ); + BOOL isCD2OutofRange = isAcidCondOutOfRange(); BOOL isTPoOutofRange = ( TPoTemp > MAX_DISINFECT_TPO_TEMPERATURE_C ? TRUE : FALSE ); maxTemperatureOutOfRangeStartTimeMS = ( TRUE == isTPoOutofRange ? maxTemperatureOutOfRangeStartTimeMS : getMSTimerCount() ); @@ -1772,6 +1793,52 @@ } } +/*********************************************************************//** + * @brief + * The processAcidConductivityData function processes the moving average + * of the acid conductivity values. + * @details Inputs: acidDataStatus + * @details Outputs: acidDataStatus + * @return: none + *************************************************************************/ +static void processAcidConductivityData( void ) +{ + if ( FALSE == acidDataStatus.acidDataColHasTimerBeenSet ) + { + acidDataStatus.acidDataColStartTimeMS = getMSTimerCount(); + acidDataStatus.acidDataColHasTimerBeenSet = TRUE; + } + else if ( TRUE == didTimeout( acidDataStatus.acidDataColStartTimeMS, ACID_DATA_COLLECTION_TIMEOUT_MS ) ) + { + F32 acidCondUSPCM = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); + U32 currentIndex = acidDataStatus.acidCondSamplesNextIndex; + F32 prevSampleToRemoveUSPCM = acidDataStatus.acidCondSamplesUSPCM[ currentIndex ]; + + acidDataStatus.acidDataColStartTimeMS = getMSTimerCount(); + acidDataStatus.acidDataColHasTimerBeenSet = TRUE; + acidDataStatus.acidCondSamplesUSPCM[ currentIndex ] = acidCondUSPCM; + acidDataStatus.acidCondRunningSumUSPCM = acidDataStatus.acidCondRunningSumUSPCM + acidCondUSPCM - prevSampleToRemoveUSPCM; + acidDataStatus.acidCondSamplesNextIndex = INC_WRAP( acidDataStatus.acidCondSamplesNextIndex, 0, ACID_MOVING_AVG_NUM_OF_SAMPLES - 1 ); + acidDataStatus.acidCondAvgUSPCM = acidDataStatus.acidCondRunningSumUSPCM / (F32)ACID_MOVING_AVG_NUM_OF_SAMPLES; + } +} + +/*********************************************************************//** + * @brief + * The isAcidCondOutOfRange function checks whether the acid conductivity + * is out of range or not. + * @details Inputs: acidDataStatus + * @details Outputs: acidDataStatus + * @return: TRUE is acid conductivity is out of range, otherwise, FALSE + *************************************************************************/ +static BOOL isAcidCondOutOfRange( void ) +{ + F32 acidCondUSPCM = acidDataStatus.acidCondAvgUSPCM; + BOOL isCD2OutOfRange = ( ( acidCondUSPCM < MIN_DISINFECT_CONDUCTIVITY_US_PER_CM || acidCondUSPCM > MAX_DISINFECT_CONDUCTIVITY_US_PER_CM ) ? TRUE : FALSE ); + + return isCD2OutOfRange; +} + /**@}*/ // ********** Nelson Support Functions **********