Index: firmware/App/Modes/ModeFill.c =================================================================== diff -u -r23fd0a4edf7848f18eeea946d4c5aa954e3e9f99 -r9438614daab0edede947e39a9d563fce8f66225e --- firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 23fd0a4edf7848f18eeea946d4c5aa954e3e9f99) +++ firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 9438614daab0edede947e39a9d563fce8f66225e) @@ -45,38 +45,26 @@ // ********** private definitions ********** #define TARGET_RO_PRESSURE_PSI 130 ///< Target pressure for RO pump. -#define RO_PUMP_400_ML_PER_MIN 0.4 ///< RO pump speed of 400.0 mL/minute. -#define RO_PUMP_800_ML_PER_MIN 0.8 ///< 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 ( 1 * MS_PER_SECOND ) ///< Persistent period for empty bottle detect. +#define EMPTY_BOTTLE_DETECT_PERSISTENT_PERIOD_MS ( 5 * MS_PER_SECOND ) ///< Persistent period for empty bottle detect. #define CONCENTRATE_PUMP_PRIME_INTERVAL ( 3 * MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Persistent time interval for concentrate pumps prime. #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 CONDUCTIVITY_WHEN_ACID_JUG_EMPTY 10000.0 ///< The conductivity value when the acid jug is empty. -#define CONDUCTIVITY_WHEN_BICARB_JUG_EMPTY 12000.0 ///< The conductivity value when the bicard jug is empty. -#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 ( 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 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 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 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. +#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. /// 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 ) ); @@ -100,44 +88,24 @@ static F32 reservoirBaseWeight; ///< Fill reservoir base weight. static FILL_CONDITION_STATUS_T fillStatus; ///< Fill condition status. -static U32 waterQualityTestStartTime; ///< Starting time for inlet water quality test. +static U32 waterQualityCheckStartTime; ///< Starting time for inlet water quality check. 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 bicarbConductivityTotal; ///< Total of bicard conductivity during fill. +static F32 dialysateConductivityTotal; ///< Total of dialysate conductivity during fill. static U32 conductivitySampleCount; ///< Sample count of conductivity during fill. -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 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 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 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 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 handleDeliverDialysateState( void ); static DG_FILL_MODE_STATE_T handlePausedState( void ); @@ -146,15 +114,14 @@ 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 * The initFillMode function initializes the fill mode module. * @details Inputs: none * @details Outputs: fillState, dialysateFillStartTime, reservoirBaseWeight, * totalROFlowRateMLPM, concentrateTestStartTime, acidConductivityTotal, - * bicarbConductivityTotal, conductivitySampleCount, + * dialysateConductivityTotal, conductivitySampleCount, * concentratePumpPrimeCount * @return none *************************************************************************/ @@ -166,20 +133,12 @@ totalROFlowRateMLPM = 0.0; concentrateTestStartTime = 0; acidConductivityTotal = 0.0; - bicarbConductivityTotal = 0.0; + 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_DG_ACID_BOTTLE_LOW_VOLUME, 0, EMPTY_BOTTLE_DETECT_PERSISTENT_PERIOD_MS ); - initPersistentAlarm( ALARM_ID_DG_BICARB_BOTTLE_LOW_VOLUME, 0, EMPTY_BOTTLE_DETECT_PERSISTENT_PERIOD_MS ); + 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 ); initPersistentAlarm( ALARM_ID_DG_DIALYSATE_TEMPERATURE_SENSORS_DRFIT_TIMEOUT, 0, DIALYSATE_TEMPERATURE_SENSORS_DRIFT_TIMEOUT_MS ); } @@ -245,33 +204,26 @@ switch ( fillState ) { case DG_FILL_MODE_STATE_START: - fillState = DG_FILL_MODE_STATE_TEST_INLET_WATER; + waterQualityCheckStartTime = getMSTimerCount(); + fillState = DG_FILL_MODE_STATE_CHECK_INLET_WATER; break; - case DG_FILL_MODE_STATE_TEST_INLET_WATER: - fillState = handleTestInletWaterState(); + case DG_FILL_MODE_STATE_CHECK_INLET_WATER: + fillState = handleCheckInletWaterState(); break; - case DG_FILL_MODE_STATE_PRIME_CONCENTRATE_LINES: - fillState = handlePrimeConcentrateLines(); + case DG_FILL_MODE_STATE_BICARB_PUMP_CHECK: + fillState = handleBicarbPumpCheckState(); break; - case DG_FILL_MODE_STATE_FLUSH_BUBBLES: - fillState = handleFlushBubbles(); + case DG_FILL_MODE_STATE_ACID_PUMP_CHECK: + fillState = handleAcidPumpCheckState(); break; - case DG_FILL_MODE_STATE_TEST_BICARB_CONDUCTIVITY: - fillState = handleTestBicarbConductivityState(); + case DG_FILL_MODE_STATE_DIALYSATE_PRODUCTION: + fillState = handleDialysateProductionState(); 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; @@ -370,226 +322,171 @@ /*********************************************************************//** * @brief - * 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 + * 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 * @return the next state *************************************************************************/ -static DG_FILL_MODE_STATE_T handleTestInletWaterState( void ) +static DG_FILL_MODE_STATE_T handleCheckInletWaterState( void ) { - DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_TEST_INLET_WATER; + DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_CHECK_INLET_WATER; #ifndef DISABLE_DIALYSATE_CHECK if ( TRUE == isWaterQualityGood() ) #endif { - // If this is the first fill of a treatment, prime acid and bicarb lines, otherwise transition + // If this is the first fill of a treatment, prime and 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 ); - requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); // TODO if + requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); #endif - concentratePrimingStartTime = getMSTimerCount(); - result = DG_FILL_MODE_STATE_PRIME_CONCENTRATE_LINES; + result = DG_FILL_MODE_STATE_BICARB_PUMP_CHECK; } else { - result = DG_FILL_MODE_STATE_PRODUCE_DIALYSATE; + result = DG_FILL_MODE_STATE_DIALYSATE_PRODUCTION; } } -#ifndef DISABLE_DIALYSATE_CHECK - else + + if ( TRUE == didTimeout( waterQualityCheckStartTime, WATER_QUALITY_CHECK_TIME_OUT_MS ) ) { activateAlarmNoData( ALARM_ID_DG_BAD_INLET_WATER_QUALITY ); + requestNewOperationMode( DG_MODE_GENE ); } -#endif return result; } /*********************************************************************//** * @brief - * The handlePrimeConcentrateLines function primes the acid and bicarb - * lines. - * @details Inputs: - * @details Outputs: + * The handleBicarbPumpCheckState function checks 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 handlePrimeConcentrateLines( void ) +static DG_FILL_MODE_STATE_T handleBicarbPumpCheckState( void ) { - DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_PRIME_CONCENTRATE_LINES; + DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_BICARB_PUMP_CHECK; - if ( TRUE == didTimeout( concentratePrimingStartTime, PRIME_CONCENTRATE_LINES_TIME_OUT_MS ) ) - { - requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); - requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); + 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; - // 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; - } +#ifndef DISABLE_DIALYSATE_CHECK + F32 bicarbConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); +#else + F32 bicarbConductivity = MAX_BICARB_CONCENTRATE_CONDUCTIVITY; +#endif - return result; -} + bicarbPumpFlowRateMLPM = MIN( bicarbPumpFlowRateMLPM, CONCENTRATE_PUMP_MAX_SPEED ); -/*********************************************************************//** - * @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 ( TRUE == didTimeout( flushBubblesStartTime, FLUSH_BUBBLES_PUMP_TIME_OUT_MS ) ) + if ( bicarbConductivity >= MIN_BICARB_CONCENTRATE_CONDUCTIVITY ) { - if ( ++pumpSpeedIndex < RO_PUMP_LOOKUP_TABLE_SIZE ) + // Reduce acid pump speed after reaching minimum conductivity + // This prevents conductivity value to go out of sensor's range + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, bicarbPumpFlowRateMLPM ); + + if ( concentratePumpPrimeCount++ > CONCENTRATE_PUMP_PRIME_INTERVAL ) { - 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 + concentratePumpPrimeCount = 0; concentrateTestStartTime = getMSTimerCount(); - result = DG_FILL_MODE_STATE_TEST_BICARB_CONDUCTIVITY; +#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; } } + 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 ) ) { - 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 ); - } + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BICARB_CONDUCTIVITY_OUT_OF_RANGE, bicarbConductivity ); + requestNewOperationMode( DG_MODE_GENE ); } return result; } /*********************************************************************//** * @brief - * 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. + * The handleAcidPumpCheckState function checks conductivity value for * acid concentrate. - * @details Inputs: Acid and bicard conductivity sensor values - * @details Outputs: Verified acid, bicard, acid & bicard conductivity values + * @details Inputs: Acid conductivity sensor value + * @details Outputs: Verified acid conductivity value * @return the next state *************************************************************************/ -static DG_FILL_MODE_STATE_T handleTestAcidConductivityState( void ) +static DG_FILL_MODE_STATE_T handleAcidPumpCheckState( void ) { - 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_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_ACID_PUMP_CHECK; - totalBicardConductivity += bicardConductivity; - bicardConductivitySampleCount++; + 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; - totalAcidConductivity += acidConductivity; - acidConductivitySampleCount++; +#ifndef DISABLE_DIALYSATE_CHECK + F32 acidConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); +#else + F32 acidConductivity = MAX_ACID_CONCENTRATE_CONDUCTIVITY; +#endif - if ( TRUE == didTimeout( concentrateTestStartTime, CONCENTRATE_TEST_TIME_OUT_MS ) ) + acidPumpFlowRateMLPM = MIN( acidPumpFlowRateMLPM, CONCENTRATE_PUMP_MAX_SPEED ); + + if ( acidConductivity >= MIN_ACID_CONCENTRATE_CONDUCTIVITY ) { - averageBicardConductivity = totalBicardConductivity / bicardConductivitySampleCount; - averageAcidConductivity = totalAcidConductivity / acidConductivitySampleCount; - averageConductivity = 2.0 * ( averageAcidConductivity - averageBicardConductivity ) / ( averageAcidConductivity + averageBicardConductivity ); + // Reduce acid pump speed after reaching minimum conductivity + // This prevents conductivity value to go out of sensor's range + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, acidPumpFlowRateMLPM ); - 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) ) ) + if ( concentratePumpPrimeCount++ > CONCENTRATE_PUMP_PRIME_INTERVAL ) { - // Do the necessary setup here before transition to Produce Dialysate State + concentratePumpPrimeCount = 0; + fillStatus.isThisFirstFill = FALSE; requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); - result = DG_FILL_MODE_STATE_PRODUCE_DIALYSATE; + requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); + result = DG_FILL_MODE_STATE_DIALYSATE_PRODUCTION; } - 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; } /*********************************************************************//** * @brief - * The handleProduceDialysateState function executes the dialysate production + * The handleDialysateProductionState function executes the dialysate production * state of the fill mode state machine. * @details Inputs: inlet water quality and dialysate temperature * @details Outputs: none * @return the next state *************************************************************************/ -static DG_FILL_MODE_STATE_T handleProduceDialysateState( void ) +static DG_FILL_MODE_STATE_T handleDialysateProductionState( void ) { - DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_PRODUCE_DIALYSATE; + DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_DIALYSATE_PRODUCTION; F32 measuredROFlowRateMLPM = getMeasuredROFlowRateLPM() * ML_PER_LITER; #ifndef DISABLE_DIALYSATE_CHECK @@ -601,10 +498,8 @@ // Prime mixing before deliver result to reservoir handleDialysateMixing( measuredROFlowRateMLPM ); #ifndef DISABLE_MIXING - requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); // SRSDG 217 - requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); // SRSDG 217 - - if ( concentratePumpPrimeCount++ > CONCENTRATE_PUMP_PRIME_INTERVAL ) + requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); #endif setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); result = DG_FILL_MODE_STATE_DELIVER_DIALYSATE; @@ -629,18 +524,20 @@ *************************************************************************/ static DG_FILL_MODE_STATE_T handleDeliverDialysateState( void ) { + F32 integratedVolumeML; + + F32 measuredROFlowRateMLPM = getMeasuredROFlowRateLPM() * ML_PER_LITER; + F32 acidConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); + 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; + DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_DELIVER_DIALYSATE; DG_RESERVOIR_ID_T inactiveReservoir = getInactiveReservoir(); - F32 integratedVolumeML; - F32 measuredROFlowRateMLPM = getMeasuredROFlowRateLPM() * ML_PER_LITER; - F32 acidConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); - F32 bicarbConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); - - BOOL isAcidConductivityBelowThreshold = ( acidConductivity < CONDUCTIVITY_WHEN_ACID_JUG_EMPTY ? TRUE : FALSE ); - BOOL isBicarbConductivityBelowThreshold = ( bicarbConductivity < CONDUCTIVITY_WHEN_BICARB_JUG_EMPTY ? TRUE : FALSE ); - - // Set concentrate pumps speed based on the RO pump flow rate + // Set concentrate pumps speed based off RO pump flow rate handleDialysateMixing( measuredROFlowRateMLPM ); totalROFlowRateMLPM += measuredROFlowRateMLPM; @@ -649,7 +546,7 @@ usedBicarbVolumeML.data += getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB ) * FLOW_INTEGRATOR; acidConductivityTotal += acidConductivity; - bicarbConductivityTotal += bicarbConductivity; + dialysateConductivityTotal += dialysateConductivity; conductivitySampleCount++; // DG is delivering dialysate keep collecting the sample counter and the measured flow @@ -658,66 +555,65 @@ fillStatus.fillTemperatureRunningSum += getTemperatureValue( (U32)TEMPSENSORS_OUTLET_PRIMARY_HEATER ); #ifndef DISABLE_DIALYSATE_CHECK - if ( ( isWaterQualityGood() != TRUE ) || ( checkDialysateTemperature() != TRUE ) ) // SRSDG 240 , SRSDG 397 + if ( ( isWaterQualityGood() != TRUE ) || ( checkDialysateTemperature() != TRUE ) ) { requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); - result = DG_FILL_MODE_STATE_PRODUCE_DIALYSATE; + result = DG_FILL_MODE_STATE_DIALYSATE_PRODUCTION; } -#endif -#ifndef DISABLE_MIXING - // Detect empty bottles using integrated volumes and conductivity sensors - if ( ( ( ACID_CONCENTRATION_BOTTLE_VOLUME_ML - getF32OverrideValue( &usedAcidVolumeML ) ) <= CONCENTRATION_BOTTLE_LOW_VOLUME_ML ) || // SRSDG 437 - ( TRUE == isPersistentAlarmTriggered( ALARM_ID_DG_ACID_BOTTLE_LOW_VOLUME, isAcidConductivityBelowThreshold ) ) ) + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_ACID_CONDUCTIVITY_OUT_OF_RANGE, isAcidConductivityOutOfRange ) ) { usedAcidVolumeML.data = 0.0; requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); - activateAlarmNoData( ALARM_ID_DG_ACID_BOTTLE_LOW_VOLUME ); result = DG_FILL_MODE_STATE_PAUSED; } - if ( ( ( BICARB_CONCENTRATION_BOTTLE_VOLUME_ML - getF32OverrideValue( &usedBicarbVolumeML ) ) <= CONCENTRATION_BOTTLE_LOW_VOLUME_ML ) || // SRSDG 438 - ( TRUE == isPersistentAlarmTriggered( ALARM_ID_DG_BICARB_BOTTLE_LOW_VOLUME, isBicarbConductivityBelowThreshold ) ) ) + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_BICARB_CONDUCTIVITY_OUT_OF_RANGE, isDialysateConductivityOutOfRange ) ) { usedBicarbVolumeML.data = 0.0; requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); - activateAlarmNoData( ALARM_ID_DG_BICARB_BOTTLE_LOW_VOLUME ); result = DG_FILL_MODE_STATE_PAUSED; } #endif +#ifndef DISABLE_MIXING + if ( ( ACID_CONCENTRATION_BOTTLE_VOLUME_ML - getF32OverrideValue( &usedAcidVolumeML ) ) <= CONCENTRATION_BOTTLE_LOW_VOLUME_ML ) + { + activateAlarmNoData( ALARM_ID_DG_ACID_BOTTLE_LOW_VOLUME ); + } - // If we've reached our target fill to volume (by weight), we're done filling - go back to generation idle mode // SRSDG 398 + if ( ( BICARB_CONCENTRATION_BOTTLE_VOLUME_ML - getF32OverrideValue( &usedBicarbVolumeML ) ) <= CONCENTRATION_BOTTLE_LOW_VOLUME_ML ) + { + activateAlarmNoData( ALARM_ID_DG_BICARB_BOTTLE_LOW_VOLUME ); + } +#endif + // If we've reached our target fill to volume (by weight), we're done filling - go back to generation idle mode if ( TRUE == hasTargetFillVolumeBeenReached( inactiveReservoir ) ) { F32 filledVolumeML = getReservoirWeight( inactiveReservoir ) - reservoirBaseWeight; F32 integratedVolumeToLoadCellReadingPercent = fabs( 1 - ( filledVolumeML / integratedVolumeML ) ); - F32 avgAcidConductivity = acidConductivityTotal / conductivitySampleCount; - F32 avgBicardConductivity = bicarbConductivityTotal / conductivitySampleCount; + F32 avgAcidConductivity = acidConductivityTotal / conductivitySampleCount; // TODO - should we be checking this below? + F32 avgDialysateConductivity = dialysateConductivityTotal / conductivitySampleCount; -#ifndef DISABLE_FLOW_CHECK_IN_FILL - if ( integratedVolumeToLoadCellReadingPercent > FLOW_INTEGRATED_VOLUME_CHECK_TOLERANCE ) // SRSDG 439 + if ( integratedVolumeToLoadCellReadingPercent > FLOW_INTEGRATED_VOLUME_CHECK_TOLERANCE ) { +#ifndef DISABLE_FLOW_CHECK_IN_FILL SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_FLOW_METER_CHECK_FAILURE, filledVolumeML, integratedVolumeML ); - } #endif - -#ifndef DISABLE_DIALYSATE_CHECK // SRSDG 400 - if ( TRUE == isValueWithinPercentRange( avgBicardConductivity, BICARB_NORMAL_CONDUCTIVITY, FIVE_PERCENT_FACTOR ) ) - { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DIALYSATE_CONDUCTIVITY_FAULT, avgBicardConductivity, BICARB_NORMAL_CONDUCTIVITY ); } - if ( TRUE == isValueWithinPercentRange( avgAcidConductivity, ACID_NORMAL_CONDUCTIVITY, FIVE_PERCENT_FACTOR ) ) +#ifndef DISABLE_DIALYSATE_CHECK + if ( ( avgDialysateConductivity < MIN_DIALYSATE_CONDUCTIVITY ) || ( avgDialysateConductivity > MAX_DIALYSATE_CONDUCTIVITY ) ) { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DIALYSATE_CONDUCTIVITY_FAULT, avgAcidConductivity, ACID_NORMAL_CONDUCTIVITY ); + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DIALYSATE_CONDUCTIVITY_FAULT, avgAcidConductivity, avgDialysateConductivity ); } #endif + // Done with this fill. Calculate the average fill flow rate and average temperature // Reset the variables for the next fill // Get the last fill temperature before leaving to Generation Idle @@ -730,7 +626,7 @@ // Write the latest fill data into the RTC RAM for heaters control // TODO test this and make sure it is writing it correctly - setFillInfoToRTCRAM(); // SRSDG ??? + setFillInfoToRTCRAM(); requestNewOperationMode( DG_MODE_GENE ); } @@ -753,7 +649,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_TEST_INLET_WATER; + result = DG_FILL_MODE_STATE_CHECK_INLET_WATER; } return result; @@ -771,10 +667,9 @@ BOOL isInletPressureGood = ( FALSE == isAlarmActive( ALARM_ID_INLET_WATER_LOW_PRESSURE ) ? FALSE : TRUE ); BOOL isWaterTemperatureGood = ( ( FALSE == isAlarmActive( ALARM_ID_INLET_WATER_HIGH_TEMPERATURE ) && - FALSE == isAlarmActive( ALARM_ID_INLET_WATER_LOW_TEMPERATURE ) && - FALSE == isAlarmActive( ALARM_ID_INLET_WATER_TEMPERATURE_OUT_OF_RANGE) ) ? FALSE : TRUE ); + FALSE == isAlarmActive( ALARM_ID_INLET_WATER_LOW_TEMPERATURE ) ) ? FALSE : TRUE ); - BOOL isWaterConductivityGood = ( ( FALSE == isAlarmActive( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_WARNING_RANGE ) && + BOOL isWaterConductivityGood = ( ( FALSE == isAlarmActive( ALARM_ID_INLET_WATER_HIGH_CONDUCTIVITY ) && FALSE == isAlarmActive( ALARM_ID_INLET_WATER_LOW_CONDUCTIVITY ) && FALSE == isAlarmActive( ALARM_ID_RO_REJECTION_RATIO_OUT_OF_RANGE ) ) ? FALSE : TRUE ); @@ -822,30 +717,6 @@ /*********************************************************************//** * @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