Index: firmware/App/Modes/ModeFill.c =================================================================== diff -u -r025612ad77fe630889a364586de54bffe5262d56 -ref4bc1eaa0f019b678b4d49011a5d23ebe558ad8 --- firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 025612ad77fe630889a364586de54bffe5262d56) +++ firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision ef4bc1eaa0f019b678b4d49011a5d23ebe558ad8) @@ -45,6 +45,10 @@ // ********** private definitions ********** #define TARGET_RO_PRESSURE_PSI 130 ///< Target pressure for RO pump. +#define RO_PUMP_400_ML_PER_MIN 400.0 ///< RO pump speed of 400.0 mL/minute. +#define RO_PUMP_800_ML_PER_MIN 800.0 ///< RO pump speed of 800.0 mL/minute. +#define ACID_PUMP_20_ML_PER_MIN 20.0 ///< Acid pump speed of 20.0 mL/minute. +#define BICARB_PUMP_40_ML_PER_MIN 40.0 ///< Bicarb pump speed of 40.0 mL/minute. #define DIALYSATE_FILL_TIME_OUT ( 5 * SEC_PER_MIN * MS_PER_SECOND ) ///< Time out period when reservoir is not filled with correct dialysate. #define EMPTY_BOTTLE_DETECT_PERSISTENT_PERIOD_MS ( 5 * MS_PER_SECOND ) ///< Persistent period for empty bottle detect. @@ -54,17 +58,23 @@ #define ACID_BICARB_CONCENTRATE_ADDITION_MULTIPLER 1.06 ///< Acid and bicarbonate concentrates make up around 6% to total volume. #define FLOW_INTEGRATED_VOLUME_CHECK_TOLERANCE 0.1 ///< Flow integrated volume has 10% tolerance compare to load cell reading. +#define ACID_TEST_CD1_TCD 12252.1 ///< Used for testing CD1 acid theoretical conductivity. +#define ACID_TEST_CD2_TCD ACID_TEST_CD1_TCD ///< Used for testing CD2 acid theoretical conductivity. +#define BICARD_TEST_CD2_TCD 6820.91 ///< Used for testing CD2 bicard theoretical conductivity. +#define FIVE_PERCENT_FACTOR 0.05 ///< 5.0 / 100.0 used to calculate conductivity within range of -/+ 5%. +#define RO_PUMP_LOOKUP_TABLE_SIZE 4 ///< Size of array used as RO pump speed lookup table. #define CONCENTRATE_PUMP_PRIME_EXTRA_SPEED_ML_MIN 5.0 ///< Concentrate pump additional speed during priming in mL/min. -#define CONCENTRATE_TEST_TIME_OUT_MS ( 45 * MS_PER_SECOND ) ///< Concentrate test time out period in ms. -#define WATER_QUALITY_CHECK_TIME_OUT_MS ( 30 * MS_PER_SECOND ) ///< Inlet water quality check time out period in ms. - +#define CONCENTRATE_TEST_TIME_OUT_MS ( 30 * MS_PER_SECOND ) ///< Concentrate test time out period in ms. +#define WATER_QUALITY_TEST_TIME_OUT_MS ( 30 * MS_PER_SECOND ) ///< Inlet water quality test time out period in ms. +#define PRIME_CONCENTRATE_LINES_TIME_OUT_MS ( 2 * MS_PER_SECOND ) ///< Time required to prime the concentrate lines. +#define FLUSH_BUBBLES_PUMP_TIME_OUT_MS ( 2 * MS_PER_SECOND ) ///< RO pump on during flush bubble interval in ms. #define DIALYSATE_TEMPERATURE_TOLERANCE_C 2.0 ///< Dialysate temperature tolerance in degree C. #define DIALYSATE_TEMPERATURE_SENSORS_MAX_DRIFT_C 2.0 ///< Dialysate temperature sensors maximum allowed drift in C. -#define DIALYSATE_TEMPERATURE_SENSORS_DRIFT_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Dialysate temperature sensors drift timeout in milliseconds. +#define DIALYSATE_TEMPERATURE_SENSORS_DRIFT_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Dialysate temperature sensors drift timeout in milliseconds. -#define ACID_CONCENTRATION_BOTTLE_VOLUME_ML 3000.0 ///< Volume of acid concentration in ml. -#define BICARB_CONCENTRATION_BOTTLE_VOLUME_ML 3000.0 ///< Volume of bicarb concentration in ml. -#define CONCENTRATION_BOTTLE_LOW_VOLUME_ML 100.0 ///< Concentration bottle low volume in ml. +#define ACID_CONCENTRATION_BOTTLE_VOLUME_ML 3430.0 ///< Bottle volume of acid concentration in mL. +#define BICARB_CONCENTRATION_BOTTLE_VOLUME_ML 3780.0 ///< Bottle volume of bicarb concentration in mL. +#define CONCENTRATION_BOTTLE_LOW_VOLUME_ML 100.0 ///< Concentration bottle low volume in mL. /// Multiplier to convert flow (mL/min) into volume (mL) for period of general task interval. static const F32 FLOW_INTEGRATOR = ( (F32)TASK_GENERAL_INTERVAL / (F32)( SEC_PER_MIN * MS_PER_SECOND ) ); @@ -88,24 +98,44 @@ static F32 reservoirBaseWeight; ///< Fill reservoir base weight. static FILL_CONDITION_STATUS_T fillStatus; ///< Fill condition status. -static U32 waterQualityCheckStartTime; ///< Starting time for inlet water quality check. +static U32 waterQualityTestStartTime; ///< Starting time for inlet water quality test. static U32 concentrateTestStartTime; ///< Starting time for concentrate test. +static U32 concentratePrimingStartTime; ///< Starting time for concentrate priming. +static U32 flushBubblesStartTime; ///< Starting time for flush bubbles. static U32 concentratePumpPrimeCount; ///< Interval count for concentrate pump prime. static F32 totalROFlowRateMLPM; ///< Total RO flow rate over period of time. static F32 acidConductivityTotal; ///< Total of acid conductivity during fill. static F32 dialysateConductivityTotal; ///< Total of dialysate conductivity during fill. static U32 conductivitySampleCount; ///< Sample count of conductivity during fill. -static OVERRIDE_F32_T usedAcidVolumeML = { 0.0, 0.0, 0.0, 0.0 }; ///< The integrated acid concentration volume has been used in ml. -static OVERRIDE_F32_T usedBicarbVolumeML = { 0.0, 0.0, 0.0, 0.0 }; ///< The integrated bicarb concentration volume has been used in ml. +static F32 averageBicardConductivity; ///< Average bicard conductivity over 30 seconds. +static F32 averageAcidConductivity; ///< Average acid conductivity over 30 seconds. +static F32 averageConductivity; ///< Average conductivity of acid and bicard over 30 seconds. +static U32 bicardConductivitySampleCount; ///< Sample count of bicard conductivity over 30 seconds. +static U32 acidConductivitySampleCount; ///< Sample count of acid conductivity over 30 seconds. + +static F32 totalBicardConductivity; ///< Total bicard conductivity over 30 seconds. +static F32 totalAcidConductivity; ///< Total acid conductivity over 30 seconds. + +static OVERRIDE_F32_T usedAcidVolumeML = { 0.0, 0.0, 0.0, 0.0 }; ///< The integrated acid concentration volume has been used in mL. +static OVERRIDE_F32_T usedBicarbVolumeML = { 0.0, 0.0, 0.0, 0.0 }; ///< The integrated bicarb concentration volume has been used in mL. + +static F32 roPumpSpeed[ RO_PUMP_LOOKUP_TABLE_SIZE ] = { RO_PUMP_400_ML_PER_MIN, ///< Lookup table to determine the desired RO speed in mL/min. + RO_PUMP_800_ML_PER_MIN, + RO_PUMP_400_ML_PER_MIN, + RO_PUMP_800_ML_PER_MIN }; +static U32 pumpSpeedIndex; ///< Index used to access the desired pump speed in roPumpSpeed table. + // ********** private function prototypes ********** -static DG_FILL_MODE_STATE_T handleCheckInletWaterState( void ); -static DG_FILL_MODE_STATE_T handleBicarbPumpCheckState( void ); -static DG_FILL_MODE_STATE_T handleAcidPumpCheckState( void ); -static DG_FILL_MODE_STATE_T handleDialysateProductionState( void ); +static DG_FILL_MODE_STATE_T handleTestInletWaterState( void ); +static DG_FILL_MODE_STATE_T handlePrimeConcentrateLines( void ); +static DG_FILL_MODE_STATE_T handleFlushBubbles( void ); +static DG_FILL_MODE_STATE_T handleTestBicarbConductivityState( void ); +static DG_FILL_MODE_STATE_T handleTestAcidConductivityState( void ); +static DG_FILL_MODE_STATE_T handleProduceDialysateState( void ); static DG_FILL_MODE_STATE_T handleDeliverDialysateState( void ); static DG_FILL_MODE_STATE_T handlePausedState( void ); @@ -114,6 +144,7 @@ static BOOL checkDialysateTemperature( void ); static void handleDialysateMixing( F32 measuredROFlowRate_mL_min ); static void setFillInfoToRTCRAM( void ); +static BOOL isValueWithinPercentRange( F32 testValue, F32 baseValue, F32 percentFactor ); /*********************************************************************//** * @brief @@ -136,6 +167,14 @@ dialysateConductivityTotal = 0.0; conductivitySampleCount = 0; concentratePumpPrimeCount = 0; + pumpSpeedIndex = 0; + averageBicardConductivity = 0.0; + averageAcidConductivity = 0.0; + averageConductivity = 0.0; + bicardConductivitySampleCount = 0; + acidConductivitySampleCount = 0; + totalBicardConductivity = 0.0; + totalAcidConductivity = 0.0; initPersistentAlarm( ALARM_ID_ACID_CONDUCTIVITY_OUT_OF_RANGE, 0, EMPTY_BOTTLE_DETECT_PERSISTENT_PERIOD_MS ); initPersistentAlarm( ALARM_ID_BICARB_CONDUCTIVITY_OUT_OF_RANGE, 0, EMPTY_BOTTLE_DETECT_PERSISTENT_PERIOD_MS ); @@ -204,26 +243,33 @@ switch ( fillState ) { case DG_FILL_MODE_STATE_START: - waterQualityCheckStartTime = getMSTimerCount(); - fillState = DG_FILL_MODE_STATE_CHECK_INLET_WATER; + fillState = DG_FILL_MODE_STATE_TEST_INLET_WATER; break; - case DG_FILL_MODE_STATE_CHECK_INLET_WATER: - fillState = handleCheckInletWaterState(); + case DG_FILL_MODE_STATE_TEST_INLET_WATER: + fillState = handleTestInletWaterState(); break; - case DG_FILL_MODE_STATE_BICARB_PUMP_CHECK: - fillState = handleBicarbPumpCheckState(); + case DG_FILL_MODE_STATE_PRIME_CONCENTRATE_LINES: + fillState = handlePrimeConcentrateLines(); break; - case DG_FILL_MODE_STATE_ACID_PUMP_CHECK: - fillState = handleAcidPumpCheckState(); + case DG_FILL_MODE_STATE_FLUSH_BUBBLES: + fillState = handleFlushBubbles(); break; - case DG_FILL_MODE_STATE_DIALYSATE_PRODUCTION: - fillState = handleDialysateProductionState(); + case DG_FILL_MODE_STATE_TEST_BICARB_CONDUCTIVITY: + fillState = handleTestBicarbConductivityState(); break; + case DG_FILL_MODE_STATE_TEST_ACID_CONDUCTIVITY: + fillState = handleTestAcidConductivityState(); + break; + + case DG_FILL_MODE_STATE_PRODUCE_DIALYSATE: + fillState = handleProduceDialysateState(); + break; + case DG_FILL_MODE_STATE_DELIVER_DIALYSATE: fillState = handleDeliverDialysateState(); break; @@ -322,158 +368,214 @@ /*********************************************************************//** * @brief - * The handleCheckInletWaterState function checks for inlet water quality - * before jumping to dialysate production state. - * @details Inputs: Temperature and conductivity alarms - * @details Outputs: request concentrate pump on and set RO pump flow rate + * The handleTestInletWaterState function tests for inlet water quality + * and if this is the first fill of a treatment, prime the acid and bicarb + * lines before jumping to dialysate production state. + * @details Inputs: Temperature, pressure, and conductivity alarms + * @details Outputs: request acid and bicarb pumps on * @return the next state *************************************************************************/ -static DG_FILL_MODE_STATE_T handleCheckInletWaterState( void ) +static DG_FILL_MODE_STATE_T handleTestInletWaterState( void ) { - DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_CHECK_INLET_WATER; + DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_TEST_INLET_WATER; #ifndef DISABLE_DIALYSATE_CHECK if ( TRUE == isWaterQualityGood() ) #endif { - // If this is the first fill of a treatment, prime and acid and bicarb lines, otherwise transition + // If this is the first fill of a treatment, prime acid and bicarb lines, otherwise transition // to dialysate production directly if ( TRUE == isThisTheFirstFill() ) { - concentrateTestStartTime = getMSTimerCount(); #ifndef DISABLE_MIXING - + // Prepare the acid and bicarb pumps to prime the concentrate lines + setROPumpTargetFlowRateLPM( RO_PUMP_800_ML_PER_MIN, TARGET_RO_PRESSURE_PSI ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, CONCENTRATE_PUMP_MAX_SPEED ); setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, CONCENTRATE_PUMP_MAX_SPEED ); - requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); #endif - result = DG_FILL_MODE_STATE_BICARB_PUMP_CHECK; + concentratePrimingStartTime = getMSTimerCount(); + result = DG_FILL_MODE_STATE_PRIME_CONCENTRATE_LINES; } else { - result = DG_FILL_MODE_STATE_DIALYSATE_PRODUCTION; + result = DG_FILL_MODE_STATE_PRODUCE_DIALYSATE; } - } - - if ( TRUE == didTimeout( waterQualityCheckStartTime, WATER_QUALITY_CHECK_TIME_OUT_MS ) ) +#ifndef DISABLE_DIALYSATE_CHECK + else { activateAlarmNoData( ALARM_ID_DG_BAD_INLET_WATER_QUALITY ); - requestNewOperationMode( DG_MODE_GENE ); } +#endif return result; } /*********************************************************************//** * @brief - * The handleBicarbPumpCheckState function checks conductivity value for - * bicarbonate concentrate. - * @details Inputs: Bicarbonate conductivity sensor value - * @details Outputs: Verified bicarbonate conductivity value + * The handlePrimeConcentrateLines function primes the acid and bicarb + * lines. + * @details Inputs: + * @details Outputs: * @return the next state *************************************************************************/ -static DG_FILL_MODE_STATE_T handleBicarbPumpCheckState( void ) +static DG_FILL_MODE_STATE_T handlePrimeConcentrateLines( void ) { - DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_BICARB_PUMP_CHECK; + DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_PRIME_CONCENTRATE_LINES; - DG_BICARB_CONCENTRATES_RECORD_T bicarb = getBicarbConcentrateCalRecord(); - F32 measuredROFlowRateMLPM = getMeasuredROFlowRateLPM() * ML_PER_LITER; - F32 bicarbPumpFlowRateMLPM = measuredROFlowRateMLPM * bicarb.bicarbConcentrate[ CAL_DATA_BICARB_CONCENTRATE_1 ].bicarbConcMixRatio - + CONCENTRATE_PUMP_PRIME_EXTRA_SPEED_ML_MIN; + if ( TRUE == didTimeout( concentratePrimingStartTime, PRIME_CONCENTRATE_LINES_TIME_OUT_MS ) ) + { + requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); -#ifndef DISABLE_DIALYSATE_CHECK - F32 bicarbConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); -#else - F32 bicarbConductivity = MAX_BICARB_CONCENTRATE_CONDUCTIVITY; -#endif + // Set the RO pump flow rate in according to the roPumpSpeed table to flush bubbles + pumpSpeedIndex = 0; + setROPumpTargetFlowRateLPM( roPumpSpeed[ pumpSpeedIndex ], TARGET_RO_PRESSURE_PSI ); + flushBubblesStartTime = getMSTimerCount(); + // State transition + result = DG_FILL_MODE_STATE_FLUSH_BUBBLES; + } - bicarbPumpFlowRateMLPM = MIN( bicarbPumpFlowRateMLPM, CONCENTRATE_PUMP_MAX_SPEED ); + return result; +} - if ( bicarbConductivity >= MIN_BICARB_CONCENTRATE_CONDUCTIVITY ) - { - // Reduce acid pump speed after reaching minimum conductivity - // This prevents conductivity value to go out of sensor's range - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, bicarbPumpFlowRateMLPM ); +/*********************************************************************//** + * @brief + * The handleFlushBubbles function removes the bubbles in the RO lines by + * running the RP pump at 400 mL/minute for 2 seconds 0 + * then 800 mL/minute for 2 seconds 1 + * then 400 mL/minute for 2 seconds 2 + * then 800 mL/minute for 2 seconds 3 + * @details Inputs: + * @details Outputs: request RO pump flow rate in mL/minute + * @return the next state + *************************************************************************/ +static DG_FILL_MODE_STATE_T handleFlushBubbles( void ) +{ + DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_FLUSH_BUBBLES; - if ( concentratePumpPrimeCount++ > CONCENTRATE_PUMP_PRIME_INTERVAL ) + if ( TRUE == didTimeout( flushBubblesStartTime, FLUSH_BUBBLES_PUMP_TIME_OUT_MS ) ) + { + if ( ++pumpSpeedIndex < RO_PUMP_LOOKUP_TABLE_SIZE ) { - concentratePumpPrimeCount = 0; + setROPumpTargetFlowRateLPM( roPumpSpeed[ pumpSpeedIndex ], TARGET_RO_PRESSURE_PSI ); + flushBubblesStartTime = getMSTimerCount(); + } + else + { + // Initialization + totalBicardConductivity = 0.0; + averageBicardConductivity = 0.0; + bicardConductivitySampleCount = 0; + // Set pumps flow rate to prepare for bicarb conductivity testing + setROPumpTargetFlowRateLPM( RO_PUMP_400_ML_PER_MIN, TARGET_RO_PRESSURE_PSI ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, BICARB_PUMP_40_ML_PER_MIN ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); + // State transition concentrateTestStartTime = getMSTimerCount(); -#ifndef DISABLE_MIXING - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, CONCENTRATE_PUMP_MAX_SPEED ); - requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); - requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); -#endif - - result = DG_FILL_MODE_STATE_ACID_PUMP_CHECK; + result = DG_FILL_MODE_STATE_TEST_BICARB_CONDUCTIVITY; } } - else - { - concentratePumpPrimeCount = 0; - } + return result; +} + +/*********************************************************************//** + * @brief + * The handleTestBicarbConductivityState function tests conductivity value for + * bicarbonate concentrate. + * @details Inputs: Bicarbonate conductivity sensor value + * @details Outputs: Verified bicarbonate conductivity value + * @return the next state + *************************************************************************/ +static DG_FILL_MODE_STATE_T handleTestBicarbConductivityState( void ) +{ + DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_TEST_BICARB_CONDUCTIVITY; + F32 bicardConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); + + totalBicardConductivity += bicardConductivity; + bicardConductivitySampleCount++; + if ( TRUE == didTimeout( concentrateTestStartTime, CONCENTRATE_TEST_TIME_OUT_MS ) ) { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BICARB_CONDUCTIVITY_OUT_OF_RANGE, bicarbConductivity ); - requestNewOperationMode( DG_MODE_GENE ); + averageBicardConductivity = totalBicardConductivity / bicardConductivitySampleCount; + + if( TRUE == isValueWithinPercentRange( averageBicardConductivity, BICARD_TEST_CD2_TCD, FIVE_PERCENT_FACTOR ) ) + { + // Initialization + requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); + totalBicardConductivity = 0.0; + totalAcidConductivity = 0.0; + averageBicardConductivity = 0.0; + averageAcidConductivity = 0.0; + averageConductivity = 0.0; + bicardConductivitySampleCount = 0; + acidConductivitySampleCount = 0; + // Set pumps flow rate to prepare for acid conductivity testing + setROPumpTargetFlowRateLPM( RO_PUMP_800_ML_PER_MIN, TARGET_RO_PRESSURE_PSI ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, ACID_PUMP_20_ML_PER_MIN ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); + // State transition + concentrateTestStartTime = getMSTimerCount(); + result = DG_FILL_MODE_STATE_TEST_ACID_CONDUCTIVITY; + } + else + { + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BICARB_CONDUCTIVITY_OUT_OF_RANGE, averageBicardConductivity ); + requestNewOperationMode( DG_MODE_GENE ); + } } return result; } /*********************************************************************//** * @brief - * The handleAcidPumpCheckState function checks conductivity value for + * The handleTestAcidConductivityState function validates that the average + * conductivity of the acid and bicard concentrate are within 5% of the + * theoretical conductivity over 30 seconds sampling period. * acid concentrate. - * @details Inputs: Acid conductivity sensor value - * @details Outputs: Verified acid conductivity value + * @details Inputs: Acid and bicard conductivity sensor values + * @details Outputs: Verified acid, bicard, acid & bicard conductivity values * @return the next state *************************************************************************/ -static DG_FILL_MODE_STATE_T handleAcidPumpCheckState( void ) +static DG_FILL_MODE_STATE_T handleTestAcidConductivityState( void ) { - DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_ACID_PUMP_CHECK; + DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_TEST_ACID_CONDUCTIVITY; + F32 acidConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); + F32 bicardConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); - DG_ACID_CONCENTRATES_RECORD_T acid = getAcidConcentrateCalRecord(); - F32 measuredROFlowRateMLPM = getMeasuredROFlowRateLPM() * ML_PER_LITER; - F32 acidPumpFlowRateMLPM = measuredROFlowRateMLPM * acid.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].acidConcMixRatio + - CONCENTRATE_PUMP_PRIME_EXTRA_SPEED_ML_MIN; + totalBicardConductivity += bicardConductivity; + bicardConductivitySampleCount++; -#ifndef DISABLE_DIALYSATE_CHECK - F32 acidConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); -#else - F32 acidConductivity = MAX_ACID_CONCENTRATE_CONDUCTIVITY; -#endif + totalAcidConductivity += acidConductivity; + acidConductivitySampleCount++; - acidPumpFlowRateMLPM = MIN( acidPumpFlowRateMLPM, CONCENTRATE_PUMP_MAX_SPEED ); - - if ( acidConductivity >= MIN_ACID_CONCENTRATE_CONDUCTIVITY ) + if ( TRUE == didTimeout( concentrateTestStartTime, CONCENTRATE_TEST_TIME_OUT_MS ) ) { - // Reduce acid pump speed after reaching minimum conductivity - // This prevents conductivity value to go out of sensor's range - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, acidPumpFlowRateMLPM ); + averageBicardConductivity = totalBicardConductivity / bicardConductivitySampleCount; + averageAcidConductivity = totalAcidConductivity / acidConductivitySampleCount; + averageConductivity = 2.0 * ( averageAcidConductivity - averageBicardConductivity ) / ( averageAcidConductivity + averageBicardConductivity ); - if ( concentratePumpPrimeCount++ > CONCENTRATE_PUMP_PRIME_INTERVAL ) + if ( ( TRUE == isValueWithinPercentRange(averageBicardConductivity, BICARD_TEST_CD2_TCD, FIVE_PERCENT_FACTOR) ) && + ( TRUE == isValueWithinPercentRange(averageAcidConductivity, ACID_TEST_CD2_TCD, FIVE_PERCENT_FACTOR) ) && + ( TRUE == isValueWithinPercentRange(averageConductivity, ACID_TEST_CD2_TCD, FIVE_PERCENT_FACTOR) ) ) { - concentratePumpPrimeCount = 0; - fillStatus.isThisFirstFill = FALSE; + // Do the necessary setup here before transition to Produce Dialysate State requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); - requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); - result = DG_FILL_MODE_STATE_DIALYSATE_PRODUCTION; + // setROPumpTargetFlowRateLPM( RO_PUMP_800_ML_PER_MIN, TARGET_RO_PRESSURE_PSI ); // Not needed since it has been on in previous state + + result = DG_FILL_MODE_STATE_PRODUCE_DIALYSATE; } + else + { + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_ACID_CONDUCTIVITY_OUT_OF_RANGE, averageAcidConductivity ); + requestNewOperationMode( DG_MODE_GENE ); + } } - else - { - concentratePumpPrimeCount = 0; - } - if ( TRUE == didTimeout( concentrateTestStartTime, CONCENTRATE_TEST_TIME_OUT_MS ) ) - { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_ACID_CONDUCTIVITY_OUT_OF_RANGE, acidConductivity ); - requestNewOperationMode( DG_MODE_GENE ); - } - return result; } @@ -485,9 +587,9 @@ * @details Outputs: none * @return the next state *************************************************************************/ -static DG_FILL_MODE_STATE_T handleDialysateProductionState( void ) +static DG_FILL_MODE_STATE_T handleProduceDialysateState( void ) { - DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_DIALYSATE_PRODUCTION; + DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_PRODUCE_DIALYSATE; F32 measuredROFlowRateMLPM = getMeasuredROFlowRateLPM() * ML_PER_LITER; #ifndef DISABLE_DIALYSATE_CHECK @@ -536,8 +638,8 @@ F32 dialysateConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); BOOL isAcidConductivityOutOfRange = ( acidConductivity <= MIN_ACID_CONCENTRATE_CONDUCTIVITY ) || ( acidConductivity >= MAX_ACID_CONCENTRATE_CONDUCTIVITY ) ? TRUE : FALSE; - BOOL isDialysateConductivityOutOfRange = ( dialysateConductivity <= MIN_DIALYSATE_CONDUCTIVITY ) || - ( dialysateConductivity >= MAX_DIALYSATE_CONDUCTIVITY ) ? TRUE : FALSE; + BOOL isDialysateConductivityOutOfRange = ( dialysateConductivity <= MIN_BICARB_CONCENTRATE_CONDUCTIVITY ) || + ( dialysateConductivity >= MAX_BICARB_CONCENTRATE_CONDUCTIVITY ) ? TRUE : FALSE; DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_DELIVER_DIALYSATE; DG_RESERVOIR_ID_T inactiveReservoir = getInactiveReservoir(); @@ -654,7 +756,7 @@ if ( ( FALSE == isAlarmActive( ALARM_ID_ACID_CONDUCTIVITY_OUT_OF_RANGE ) ) && ( FALSE == isAlarmActive( ALARM_ID_BICARB_CONDUCTIVITY_OUT_OF_RANGE ) ) ) { - result = DG_FILL_MODE_STATE_CHECK_INLET_WATER; + result = DG_FILL_MODE_STATE_TEST_INLET_WATER; } return result; @@ -722,6 +824,30 @@ /*********************************************************************//** * @brief + * The isValueWithinPercentRange function validates if the test value + * is within the percentage range specified by the baseValue and + * percentFactor. + * @details Inputs: testValue + * @details Outputs: None + * @return TRUE if testValue is within range. Otherwise, return FALSE + *************************************************************************/ +static BOOL isValueWithinPercentRange( F32 testValue, F32 baseValue, F32 percentFactor ) +{ + BOOL testFlag = FALSE; + F32 percentValue = baseValue * percentFactor; + F32 valueMax = baseValue + percentValue; + F32 valueMin = baseValue - percentValue; + + if( ( testValue >= valueMin ) && ( testValue <= valueMax ) ) + { + testFlag = TRUE; + } + + return testFlag; +} + +/*********************************************************************//** + * @brief * The handleDialysateMixing function handles the dialysate mixing by setting * the concentrate pump speed relative to the RO pump flow rate. * @details Inputs: none