Index: firmware/App/Modes/ModeFill.c =================================================================== diff -u -rc53dd92ec3baa363ccfbd0477db69a3017f5c067 -rc44e496a684e4ff1c1a19389873a46fd8181334e --- firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision c53dd92ec3baa363ccfbd0477db69a3017f5c067) +++ firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision c44e496a684e4ff1c1a19389873a46fd8181334e) @@ -61,7 +61,9 @@ #define FILL_MODE_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the fill mode data is published on the CAN bus. #define DIALYSATE_FILL_TIME_OUT ( 5 * SEC_PER_MIN * MS_PER_SECOND ) ///< Time out period when reservoir is not filled with correct dialysate. -#define CONCENTRATE_PUMP_PRIME_INTERVAL ( 10 * MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Persistent time interval for concentrate pumps prime. +#define CONC_PUMPS_PRIME_AT_MAX_SPEED_TIME_OUT_MS ( 8 * MS_PER_SECOND ) ///< Concentrate pumps prime at maximum speed timeout in milliseconds. +#define CONC_PUMPS_PRIME_CHECK_COND_SNSRS_TIME_OUT_MS ( 10 * MS_PER_SECOND ) ///< Concentrate pumps prime check conductivity sensors timeout in milliseconds. +#define CONC_PUMPS_PRIME_MAX_ALLOWED_PRIME_TIME_OUT_MS ( 25 * MS_PER_SECOND ) ///< Concentrate pumps prime maximum allowed timeout in prime in milliseconds. #define FLOW_INTEGRATED_VOLUME_CHECK_TOLERANCE 0.1F ///< Flow integrated volume has 10% tolerance compare to load cell reading. @@ -114,14 +116,14 @@ static U32 dataPublishCounter; ///< Used to schedule dialysate fill data publication to CAN bus. static DG_FILL_MODE_STATE_T fillState; ///< Currently active fill state. -static U32 dialysateFillStartTime; ///< Current time when starting to fill dialysate. +static U32 dialysateFillStartTimeMS; ///< Current time when starting to fill dialysate in milliseconds. static F32 reservoirBaseWeight; ///< Fill reservoir base weight. static FILL_CONDITION_STATUS_T fillStatus; ///< Fill condition status. 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 U32 concPumpPrimeStartTimeMS; ///< Concentrate pump prime start time in milliseconds. static BOOL didFMPCheckStart; ///< Flag indicates whether FMP flow vs. LC volume check has begun. static F32 acidConductivityTotal; ///< Total of acid conductivity during fill. @@ -145,6 +147,9 @@ static U32 pumpSpeedIndex; ///< Index used to access the desired pump speed in roPumpFlushBubblesSpeed table. static BOOL havePauseActuatorsBeenSet; ///< Flag to indicate the actuators have been set to pause for the first time. static FILL_ACID_BICARB_TYPES_T chemicalsTypes; ///< Chemicals Types (acid and bicarb). +static DG_CHEMICALS_FILL_COND_CAL_RECORD_T chemicalsCond; ///< Chemicals fill conductivity records. +static F32 acidMixRatio; ///< Acid conductivity mix ratio. +static F32 bicarbMixRatio; ///< Bicarb conductivity mix ratio. // NOTE: This variable should be initialized here because the init function is called every time and then this variable is set to FALSE even if the settings from the // UI wants the RO only mode. @@ -166,6 +171,7 @@ static DG_FILL_MODE_STATE_T handleDeliverDialysateState( void ); static DG_FILL_MODE_STATE_T handlePausedState( void ); +static void setModeFillStateTransition( DG_FILL_MODE_STATE_T state ); static BOOL areInletWaterConditionsAlarmsActive( void ); static BOOL areConductivityAlarmsActive( void ); static void handleDialysateMixing( F32 measuredROFlowRate_mL_min, F32 acidMixingRatio, F32 bicarbMixingRatio ); @@ -182,8 +188,16 @@ *************************************************************************/ void initFillMode( void ) { + DG_ACID_CONCENTRATES_RECORD_T acid; + DG_BICARB_CONCENTRATES_RECORD_T bicarb; + + getAcidConcentrateCalRecord( &acid ); + getBicarbConcentrateCalRecord( &bicarb ); + + acidMixRatio = acid.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].acidConcMixRatio; + bicarbMixRatio = bicarb.bicarbConcentrate[ CAL_DATA_BICARB_CONCENTRATE_1 ].bicarbConcMixRatio; fillState = DG_FILL_MODE_STATE_START; - dialysateFillStartTime = 0; + dialysateFillStartTimeMS = 0; dataPublishCounter = DATA_PUBLISH_COUNTER_START_COUNT; reservoirBaseWeight = 0.0F; integratedVolumeML.data = 0.0F; @@ -192,7 +206,7 @@ acidConductivityTotal = 0.0F; bicarbConductivityTotal = 0.0F; conductivitySampleCount = 0; - concentratePumpPrimeCount = 0; + concPumpPrimeStartTimeMS = getMSTimerCount(); pumpSpeedIndex = 0; averageBicarbConductivity = 0.0F; averageAcidConductivity = 0.0F; @@ -268,15 +282,15 @@ // Do the necessary setup here before transition to Produce Dialysate State fillStatus.isThisFirstFill = FALSE; - concentratePumpPrimeCount = 0; + concPumpPrimeStartTimeMS = getMSTimerCount(); break; case DG_FILL_MODE_STATE_DELIVER_DIALYSATE: requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); - dialysateFillStartTime = getMSTimerCount(); + dialysateFillStartTimeMS = getMSTimerCount(); fillStatus.isThisFirstFill = FALSE; break; @@ -287,6 +301,8 @@ } } + getFillChemicalCondRecord( &chemicalsCond ); + turnOnUVReactor( INLET_UV_REACTOR ); turnOnUVReactor( OUTLET_UV_REACTOR ); @@ -582,37 +598,15 @@ // to dialysate production directly if ( TRUE == isThisTheFirstFill() ) { - // Prepare the acid and bicarb pumps to prime the concentrate lines - setROPumpTargetFlowRateLPM( RO_PUMP_800_ML_PER_MIN / MILLILITERS_PER_LITER, TARGET_RO_PRESSURE_PSI ); - - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, CONCENTRATE_PUMP_MAX_SPEED ); - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, CONCENTRATE_PUMP_MAX_SPEED ); - requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); - requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); - - concentratePrimingStartTime = getMSTimerCount(); - result = DG_FILL_MODE_STATE_PRIME_CONCENTRATE_LINES; + result = DG_FILL_MODE_STATE_PRIME_CONCENTRATE_LINES; } else { - DG_ACID_CONCENTRATES_RECORD_T acid; - F32 acidMix; - DG_BICARB_CONCENTRATES_RECORD_T bicarb; - F32 bicarbMix; - - getAcidConcentrateCalRecord( &acid ); - getBicarbConcentrateCalRecord( &bicarb ); - - acidMix = acid.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].acidConcMixRatio; - bicarbMix = bicarb.bicarbConcentrate[ CAL_DATA_BICARB_CONCENTRATE_1 ].bicarbConcMixRatio; - - setROPumpTargetFlowRateLPM( getTargetFillFlowRateLPM(), TARGET_RO_PRESSURE_PSI ); - handleDialysateMixing( getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) * ML_PER_LITER, acidMix, bicarbMix ); - requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); - requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); result = DG_FILL_MODE_STATE_PRODUCE_DIALYSATE; } + setModeFillStateTransition( result ); + return result; } @@ -630,15 +624,8 @@ if ( TRUE == didTimeout( concentratePrimingStartTime, PRIME_CONCENTRATE_LINES_TIME_OUT_MS ) ) { - requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID, NO_PARK_CONC_PUMPS ); - requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); - - // Set the RO pump flow rate in according to the roPumpFlushBubblesSpeed table to flush bubbles - pumpSpeedIndex = 0; - setROPumpTargetFlowRateLPM( RO_PUMP_FLUSH_BUBBLES_FLOWS[ pumpSpeedIndex ] / MILLILITERS_PER_LITER, TARGET_RO_PRESSURE_PSI ); - - flushBubblesStartTime = getMSTimerCount(); - result = DG_FILL_MODE_STATE_FLUSH_BUBBLES; + result = DG_FILL_MODE_STATE_FLUSH_BUBBLES; + setModeFillStateTransition( result ); } return result; @@ -668,23 +655,8 @@ } else { - // Initialization - totalBicarbConductivity = 0.0F; - averageBicarbConductivity = 0.0F; - bicarbConductivitySampleCount = 0; - - // Set pumps flow rate to prepare for bicarb conductivity testing - setROPumpTargetFlowRateLPM( RO_PUMP_800_ML_PER_MIN / MILLILITERS_PER_LITER, TARGET_RO_PRESSURE_PSI ); - - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, BICARB_PUMP_40_ML_PER_MIN ); - requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); - - // Prior to collecting data for bicarb test, change the CD2 calibration table - setCondcutivitySensorCalTable( CONDUCTIVITYSENSORS_CD2_SENSOR, CAL_DATA_CD2_COND_SENSOR_FILL_BICARB_TEST ); - - // State transition - concentrateTestStartTime = getMSTimerCount(); - result = DG_FILL_MODE_STATE_TEST_BICARB_CONDUCTIVITY; + result = DG_FILL_MODE_STATE_TEST_BICARB_CONDUCTIVITY; + setModeFillStateTransition( result ); } } @@ -712,49 +684,21 @@ if ( TRUE == didTimeout( concentrateTestStartTime, CONCENTRATE_TEST_TIME_OUT_MS ) ) { - DG_CHEMICALS_FILL_COND_CAL_RECORD_T chemicalsCond; - F32 bicarbCondUSPerCM = 0.0F; + // In the bicarb test, the acid value is 0, so it is not queried + F32 bicarbCondUSPerCM = chemicalsCond.fillCondValues[ chemicalsTypes.acidType ][ FILL_COND_BICARB_TEST ].bicarbConduSPerCM; BOOL isConductivityInRange = FALSE; - getFillChemicalCondRecord( &chemicalsCond ); - - // In the bicarb test, the acid value is 0, so it is not queried - bicarbCondUSPerCM = chemicalsCond.fillCondValues[ chemicalsTypes.acidType ][ FILL_COND_BICARB_TEST ].bicarbConduSPerCM; - averageBicarbConductivity = totalBicarbConductivity / bicarbConductivitySampleCount; if ( TRUE == isValueWithinPercentRange( averageBicarbConductivity, bicarbCondUSPerCM, FIVE_PERCENT_FACTOR ) ) { isConductivityInRange = TRUE; } -#ifndef _RELEASE_ - if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_BICARB_CONDUCTIVITY_TEST ) ) - { - isConductivityInRange = TRUE; - } -#endif - if ( ( TRUE == isConductivityInRange ) || ( TRUE == getTestConfigStatus( TEST_CONFIG_MIX_WITH_WATER ) ) ) { - // Initialization - requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); - totalBicarbConductivity = 0.0F; - totalAcidConductivity = 0.0F; - bicarbConductivitySampleCount = 0; - acidConductivitySampleCount = 0; - - // Set pumps flow rate to prepare for acid conductivity testing - setROPumpTargetFlowRateLPM( RO_PUMP_800_ML_PER_MIN / MILLILITERS_PER_LITER, TARGET_RO_PRESSURE_PSI ); - setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, ACID_PUMP_20_ML_PER_MIN ); - requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); - - // Set back the conductivity of CD2 calibration table to the normal calibration table - setCondcutivitySensorCalTable( CONDUCTIVITYSENSORS_CD2_SENSOR, CAL_DATA_CD2_COND_SENSOR ); - - // State transition - concentrateTestStartTime = getMSTimerCount(); - result = DG_FILL_MODE_STATE_TEST_ACID_CONDUCTIVITY; + result = DG_FILL_MODE_STATE_TEST_ACID_CONDUCTIVITY; + setModeFillStateTransition( result ); } else { @@ -793,70 +737,38 @@ if ( TRUE == didTimeout( concentrateTestStartTime, CONCENTRATE_TEST_TIME_OUT_MS ) ) { - DG_CHEMICALS_FILL_COND_CAL_RECORD_T chemicalsCond; - F32 acidCondUSPerCM = 0.0F; + F32 acidCondUSPerCM = chemicalsCond.fillCondValues[ chemicalsTypes.acidType ][ FILL_COND_ACID_TEST ].acidConduSPerCM; BOOL hasAcidTestPassed = FALSE; BOOL hasCD1CD2TestPassed = FALSE; - getFillChemicalCondRecord( &chemicalsCond ); - - acidCondUSPerCM = chemicalsCond.fillCondValues[ chemicalsTypes.acidType ][ FILL_COND_ACID_TEST ].acidConduSPerCM; averageBicarbConductivity = totalBicarbConductivity / bicarbConductivitySampleCount; averageAcidConductivity = totalAcidConductivity / acidConductivitySampleCount; pctDiffInConductivity = fabs( 2.0F * ( averageAcidConductivity - averageBicarbConductivity ) / ( averageAcidConductivity + averageBicarbConductivity ) ); -#ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_ACID_CONDUCTIVITY_TEST ) != SW_CONFIG_ENABLE_VALUE ) -#endif + if ( ( TRUE == isValueWithinPercentRange( averageAcidConductivity, acidCondUSPerCM, FIVE_PERCENT_FACTOR ) ) || + ( TRUE == getTestConfigStatus( TEST_CONFIG_MIX_WITH_WATER ) ) ) { - if ( ( TRUE == isValueWithinPercentRange( averageAcidConductivity, acidCondUSPerCM, FIVE_PERCENT_FACTOR ) ) || - ( TRUE == getTestConfigStatus( TEST_CONFIG_MIX_WITH_WATER ) ) ) - { - hasAcidTestPassed = TRUE; - } - else - { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DG_ACID_CONDUCTIVITY_OUT_OF_RANGE, averageAcidConductivity ) - } - - if ( ( pctDiffInConductivity < FIVE_PERCENT_FACTOR ) || ( TRUE == getTestConfigStatus( TEST_CONFIG_MIX_WITH_WATER ) ) ) - { - hasCD1CD2TestPassed = TRUE; - } - else - { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DG_CD1_CD2_CHECK_FAULT, pctDiffInConductivity ) - } + hasAcidTestPassed = TRUE; } -#ifndef _RELEASE_ else { - hasAcidTestPassed = TRUE; + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DG_ACID_CONDUCTIVITY_OUT_OF_RANGE, averageAcidConductivity ) + } + + if ( ( pctDiffInConductivity < FIVE_PERCENT_FACTOR ) || ( TRUE == getTestConfigStatus( TEST_CONFIG_MIX_WITH_WATER ) ) ) + { hasCD1CD2TestPassed = TRUE; } -#endif + else + { + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DG_CD1_CD2_CHECK_FAULT, pctDiffInConductivity ) + } if ( ( TRUE == hasAcidTestPassed ) && ( TRUE == hasCD1CD2TestPassed ) ) { - DG_ACID_CONCENTRATES_RECORD_T acid; - F32 acidMix; - DG_BICARB_CONCENTRATES_RECORD_T bicarb; - F32 bicarbMix; - - getAcidConcentrateCalRecord( &acid ); - getBicarbConcentrateCalRecord( &bicarb ); - - acidMix = acid.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].acidConcMixRatio; - bicarbMix = bicarb.bicarbConcentrate[ CAL_DATA_BICARB_CONCENTRATE_1 ].bicarbConcMixRatio; - - setROPumpTargetFlowRateLPM( getTargetFillFlowRateLPM(), TARGET_RO_PRESSURE_PSI ); - handleDialysateMixing( getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) * ML_PER_LITER, acidMix, bicarbMix ); - requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); - - // Do the necessary setup here before transition to Produce Dialysate State - fillStatus.isThisFirstFill = FALSE; - result = DG_FILL_MODE_STATE_PRODUCE_DIALYSATE; + result = DG_FILL_MODE_STATE_PRODUCE_DIALYSATE; + setModeFillStateTransition( result ); } } @@ -867,34 +779,48 @@ * @brief * The handleProduceDialysateState function executes the dialysate production * state of the fill mode state machine. - * @details Inputs: inlet water quality and dialysate temperature + * @details Inputs: chemicalsCond, concPumpPrimeStartTimeMS * @details Outputs: none * @return the next state *************************************************************************/ static DG_FILL_MODE_STATE_T handleProduceDialysateState( void ) { DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_PRODUCE_DIALYSATE; - DG_ACID_CONCENTRATES_RECORD_T acid; - F32 acidMix; - DG_BICARB_CONCENTRATES_RECORD_T bicarb; - F32 bicarbMix; - getAcidConcentrateCalRecord( &acid ); - getBicarbConcentrateCalRecord( &bicarb ); + if ( TRUE == didTimeout( concPumpPrimeStartTimeMS, CONC_PUMPS_PRIME_AT_MAX_SPEED_TIME_OUT_MS ) ) + { + // Once the time for running the concentrate pumps at full speed has been elapsed, start running the pumps and the target mix ratio + handleDialysateMixing( getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) * ML_PER_LITER, acidMixRatio, bicarbMixRatio ); - acidMix = acid.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].acidConcMixRatio; - bicarbMix = bicarb.bicarbConcentrate[ CAL_DATA_BICARB_CONCENTRATE_1 ].bicarbConcMixRatio; + if ( TRUE == didTimeout( concPumpPrimeStartTimeMS, CONC_PUMPS_PRIME_CHECK_COND_SNSRS_TIME_OUT_MS ) ) + { + /* Once the time for priming the concentrate lines has elapsed, check the mixing conductivity of the sensors + * If the acid and bicarb conductivity values are at about 50% of the target concentrate during fill, transition to the next state + * If the acid and bicarb conductivity values are not at 50% but the maximum prime time has elapsed, transition to the next state + */ + F32 acidConduSPerCM = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); + F32 bicarbConduSPerCM = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); + F32 acidFillConduSPerCM = chemicalsCond.fillCondValues[ chemicalsTypes.acidType ][ FILL_COND_NORMAL_OP ].acidConduSPerCM; + F32 bicarbFillConduSPerCM = chemicalsCond.fillCondValues[ chemicalsTypes.acidType ][ FILL_COND_NORMAL_OP ].bicarbConduSPerCM; - // Prime mixing before deliver result to reservoir - handleDialysateMixing( getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) * ML_PER_LITER, acidMix, bicarbMix ); + if ( ( acidConduSPerCM >= ( acidFillConduSPerCM * HALF ) ) && ( bicarbConduSPerCM >= ( bicarbFillConduSPerCM * HALF ) ) ) + { + result = DG_FILL_MODE_STATE_DELIVER_DIALYSATE; + setModeFillStateTransition( result ); + } + else if ( TRUE == didTimeout( concPumpPrimeStartTimeMS, CONC_PUMPS_PRIME_MAX_ALLOWED_PRIME_TIME_OUT_MS ) ) + { + result = DG_FILL_MODE_STATE_DELIVER_DIALYSATE; + setModeFillStateTransition( result ); + } - if ( concentratePumpPrimeCount++ > CONCENTRATE_PUMP_PRIME_INTERVAL ) - { - setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); - - dialysateFillStartTime = getMSTimerCount(); - fillStatus.isThisFirstFill = FALSE; - result = DG_FILL_MODE_STATE_DELIVER_DIALYSATE; + if ( TRUE == getTestConfigStatus( TEST_CONFIG_MIX_WITH_WATER ) ) + { + // If mix with water is enabled do not wait for the conductivity values or timeout, transition to the next state + result = DG_FILL_MODE_STATE_DELIVER_DIALYSATE; + setModeFillStateTransition( result ); + } + } } return result; @@ -910,17 +836,13 @@ *************************************************************************/ static DG_FILL_MODE_STATE_T handleDeliverDialysateState( void ) { - DG_ACID_CONCENTRATES_RECORD_T acid; - DG_BICARB_CONCENTRATES_RECORD_T bicarb; - F32 acidMix = 0.0F; - F32 bicarbMix = 0.0F; DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_DELIVER_DIALYSATE; DG_RESERVOIR_ID_T inactiveRsrvr = getInactiveReservoir(); - F32 acidConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); - F32 bicarbConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); + F32 acidConduSPerCM = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); + F32 bicarbConduSPerCM = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); F32 inletTemperature = getTemperatureValue( TEMPSENSORS_CONDUCTIVITY_SENSOR_2 ); - F32 cpi = getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ); - F32 cpo = getConductivityValue( CONDUCTIVITYSENSORS_CPO_SENSOR ); + F32 cpiConduSPerCM = getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ); + F32 cpoConduSPerCM = getConductivityValue( CONDUCTIVITYSENSORS_CPO_SENSOR ); F32 rejRatio = RO_REJECTION_RATIO_OUT_OF_RANGE_VALUE; // default 1:1 before calculation in case can't divide by zero. #ifndef _RELEASE_ @@ -931,26 +853,20 @@ } #endif - getAcidConcentrateCalRecord( &acid ); - getBicarbConcentrateCalRecord( &bicarb ); - - acidMix = acid.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].acidConcMixRatio; - bicarbMix = bicarb.bicarbConcentrate[ CAL_DATA_BICARB_CONCENTRATE_1 ].bicarbConcMixRatio; - // Set concentrate pumps speed based on the RO pump flow rate - handleDialysateMixing( getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) * ML_PER_LITER, acidMix, bicarbMix ); + handleDialysateMixing( getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) * ML_PER_LITER, acidMixRatio, bicarbMixRatio ); // Sum conductivity readings for CPo and RR checks - if ( fabs(cpi) >= NEARLY_ZERO ) + if ( fabs(cpiConduSPerCM) >= NEARLY_ZERO ) { - rejRatio = cpo / cpi; + rejRatio = cpoConduSPerCM / cpiConduSPerCM; } - sumFillCPoConductivity += cpo; + sumFillCPoConductivity += cpoConduSPerCM; sumFillRejRatio += rejRatio; fillCPoConductivitySampleCnt++; // Delay start of FMP check, then begin integrating flow to a volume - if ( TRUE == didTimeout( dialysateFillStartTime, DELAY_FMP_CHECK_START_BY_MS ) ) + if ( TRUE == didTimeout( dialysateFillStartTimeMS, DELAY_FMP_CHECK_START_BY_MS ) ) { if ( FALSE == didFMPCheckStart ) { // When FMP check starts, set baseline weight of reservoir we are filling @@ -963,8 +879,8 @@ usedAcidVolumeML.data += getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP1_ACID ) * FLOW_INTEGRATOR; usedBicarbVolumeML.data += getMeasuredPumpSpeed( CONCENTRATEPUMPS_CP2_BICARB ) * FLOW_INTEGRATOR; - acidConductivityTotal += acidConductivity; - bicarbConductivityTotal += bicarbConductivity; + acidConductivityTotal += acidConduSPerCM; + bicarbConductivityTotal += bicarbConduSPerCM; conductivitySampleCount++; // DG is delivering dialysate keep collecting the sample counter and the measured flow @@ -974,49 +890,38 @@ // TODO: Check for open straw door status and alarm if closed // Check if run out of time to fill the reservoir - if ( TRUE == didTimeout( dialysateFillStartTime, DIALYSATE_FILL_TIME_OUT ) ) + if ( TRUE == didTimeout( dialysateFillStartTimeMS, DIALYSATE_FILL_TIME_OUT ) ) { activateAlarmNoData( ALARM_ID_DG_DIALYSATE_FILL_OUT_OF_TIME ); } // If we've reached our target fill to volume (by weight), we're done filling - go back to generation idle mode // SRSDG 398 if ( TRUE == hasTargetFillVolumeBeenReached( inactiveRsrvr ) ) { - DG_CHEMICALS_FILL_COND_CAL_RECORD_T chemicalsCond; - - getFillChemicalCondRecord( &chemicalsCond ); - F32 filledVolumeML = getReservoirWeight( inactiveRsrvr ) - reservoirBaseWeight; F32 integratedVolumeToLoadCellReadingPercent = fabs( 1.0F - ( getIntegratedVolumeML() / filledVolumeML ) ); // Filled volume more accurate and stable than the integrated volume from the flowmeter - F32 avgAcidConductivity = acidConductivityTotal / conductivitySampleCount; - F32 avgBicarbConductivity = bicarbConductivityTotal / conductivitySampleCount; - F32 acidNormalConductivity = chemicalsCond.fillCondValues[ chemicalsTypes.acidType ][ FILL_COND_NORMAL_OP ].acidConduSPerCM; - F32 bicarbNormalConductivity = chemicalsCond.fillCondValues[ chemicalsTypes.acidType ][ FILL_COND_NORMAL_OP ].bicarbConduSPerCM; + F32 avgAcidConduSPerCM = acidConductivityTotal / conductivitySampleCount; + F32 avgBicarbConduSPerCM = bicarbConductivityTotal / conductivitySampleCount; + F32 bicarbNormalConduSPerCM = chemicalsCond.fillCondValues[ chemicalsTypes.acidType ][ FILL_COND_NORMAL_OP ].bicarbConduSPerCM; - SEND_EVENT_WITH_2_F32_DATA( DG_EVENT_AVG_DIALYSATE_FILL_COND_VALUES, avgAcidConductivity, avgBicarbConductivity ) + SEND_EVENT_WITH_2_F32_DATA( DG_EVENT_AVG_DIALYSATE_FILL_COND_VALUES, avgAcidConduSPerCM, avgBicarbConduSPerCM ) SEND_EVENT_WITH_2_F32_DATA( DG_EVENT_RESERVOIR_FILL_VALUES, reservoirBaseWeight, filledVolumeML ) - // Check RO filter -#ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_RO_RATIO_CHECK ) != SW_CONFIG_ENABLE_VALUE ) -#endif + if ( getTargetFillVolumeML() > MIN_FILL_TARGET_TO_CHECK_RO_AND_CPO_ML ) { - if ( getTargetFillVolumeML() > MIN_FILL_TARGET_TO_CHECK_RO_AND_CPO_ML ) - { - F32 avgCPo = sumFillCPoConductivity / (F32)fillCPoConductivitySampleCnt; // sample count incremented above w/o condition so no need for divide by zero checks - F32 avgRR = sumFillRejRatio / (F32)fillCPoConductivitySampleCnt; + F32 avgCPo = sumFillCPoConductivity / (F32)fillCPoConductivitySampleCnt; // sample count incremented above w/o condition so no need for divide by zero checks + F32 avgRR = sumFillRejRatio / (F32)fillCPoConductivitySampleCnt; - if ( ( avgCPo > MAX_CPO_CONDUCTIVITY_ALLOW ) && ( getTestConfigStatus( TEST_CONFIG_MIX_WITH_WATER ) != TRUE ) ) - { - // Fault alarm per PRS 483 - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_OUTLET_PRIMARY_CONDUCTIVITY_OUT_OF_RANGE, avgCPo, MAX_CPO_CONDUCTIVITY_ALLOW ); - } - if ( ( avgRR > MAX_RO_REJECTION_RATIO_ALLOW ) && ( isROOnlyModeEnabled() != TRUE ) ) - { - // Fault alarm per PRS 483 - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_RO_REJECTION_RATIO_OUT_OF_RANGE, avgRR, MAX_RO_REJECTION_RATIO_ALLOW ); - } + if ( ( avgCPo > MAX_CPO_CONDUCTIVITY_ALLOW ) && ( getTestConfigStatus( TEST_CONFIG_MIX_WITH_WATER ) != TRUE ) ) + { + // Fault alarm per PRS 483 + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_OUTLET_PRIMARY_CONDUCTIVITY_OUT_OF_RANGE, avgCPo, MAX_CPO_CONDUCTIVITY_ALLOW ); } + if ( ( avgRR > MAX_RO_REJECTION_RATIO_ALLOW ) && ( isROOnlyModeEnabled() != TRUE ) ) + { + // Fault alarm per PRS 483 + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_RO_REJECTION_RATIO_OUT_OF_RANGE, avgRR, MAX_RO_REJECTION_RATIO_ALLOW ); + } } // Check FMP vs. LC @@ -1033,31 +938,15 @@ } } - // Check mixing via avg. conductivities -#ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_MIXING_IN_FILL ) != SW_CONFIG_ENABLE_VALUE ) -#endif + // SRSDG 400 + if ( ( FALSE == isValueWithinPercentRange( avgBicarbConduSPerCM, bicarbNormalConduSPerCM, FIVE_PERCENT_FACTOR ) ) && + ( getTargetFillVolumeML() > MIN_FILL_TARGET_TO_CHECK_RO_AND_CPO_ML ) && ( getTestConfigStatus( TEST_CONFIG_MIX_WITH_WATER ) != TRUE ) ) { - // SRSDG 400 - if ( ( FALSE == isValueWithinPercentRange( avgBicarbConductivity, bicarbNormalConductivity, FIVE_PERCENT_FACTOR ) ) && - ( getTargetFillVolumeML() > MIN_FILL_TARGET_TO_CHECK_RO_AND_CPO_ML ) && ( getTestConfigStatus( TEST_CONFIG_MIX_WITH_WATER ) != TRUE ) ) - { - setBadAvgConductivityDetectedFlag( TRUE ); // signal idle bad avg conductivity detected - setThisFisrtFillFlag( TRUE ); - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_FILL_CONDUCTIVITY_OUT_OF_RANGE, avgBicarbConductivity, bicarbNormalConductivity ); // trigger replace bottles alarm #1 - clearAlarm( ALARM_ID_DG_CREATING_DIALYSATE_PLEASE_WAIT ); // clear this alarm before triggering in case previous fill was bad and still active from before - activateAlarmNoData ( ALARM_ID_DG_CREATING_DIALYSATE_PLEASE_WAIT ); - } - - if ( ( FALSE == isValueWithinPercentRange( avgAcidConductivity, acidNormalConductivity, FIVE_PERCENT_FACTOR ) ) && - ( getTargetFillVolumeML() > MIN_FILL_TARGET_TO_CHECK_RO_AND_CPO_ML ) && ( getTestConfigStatus( TEST_CONFIG_MIX_WITH_WATER ) != TRUE ) ) - { - setBadAvgConductivityDetectedFlag( TRUE ); // signal idle bad avg conductivity detected - setThisFisrtFillFlag( TRUE ); - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_FILL_CONDUCTIVITY_OUT_OF_RANGE, avgAcidConductivity, acidNormalConductivity ); // trigger replace bottles alarm #1 then - clearAlarm( ALARM_ID_DG_CREATING_DIALYSATE_PLEASE_WAIT ); // clear this alarm before triggering in case previous fill was bad and still active from before - activateAlarmNoData ( ALARM_ID_DG_CREATING_DIALYSATE_PLEASE_WAIT ); - } + setBadAvgConductivityDetectedFlag( TRUE ); // signal idle bad avg conductivity detected + setThisFisrtFillFlag( TRUE ); + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_FILL_CONDUCTIVITY_OUT_OF_RANGE, avgBicarbConduSPerCM, bicarbNormalConduSPerCM ); // trigger replace bottles alarm #1 + clearAlarm( ALARM_ID_DG_CREATING_DIALYSATE_PLEASE_WAIT ); // clear this alarm before triggering in case previous fill was bad and still active from before + activateAlarmNoData ( ALARM_ID_DG_CREATING_DIALYSATE_PLEASE_WAIT ); } // Done with this fill. Calculate the average fill flow rate and average temperature @@ -1089,14 +978,7 @@ { DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_PAUSED; - if ( FALSE == havePauseActuatorsBeenSet ) - { - setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); - setROPumpTargetFlowRateLPM( TARGET_RO_FLOW_RATE_IN_PAUSE_L, TARGET_RO_PRESSURE_PSI ); - requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID, NO_PARK_CONC_PUMPS ); - requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); - havePauseActuatorsBeenSet = TRUE; - } + setModeFillStateTransition( result ); if ( ( FALSE == areInletWaterConditionsAlarmsActive() ) && ( FALSE == areConductivityAlarmsActive() ) ) { @@ -1109,6 +991,106 @@ /*********************************************************************//** * @brief + * The setModeFillStateTransition function sets the actuators and variables + * for the state transition in mode fill. + * @details Inputs: none + * @details Outputs: concPumpPrimeStartTimeMS, fillStatus + * @param state mode fill state enum + * @return none + *************************************************************************/ +static void setModeFillStateTransition( DG_FILL_MODE_STATE_T state ) +{ + switch( state ) + { + case DG_FILL_MODE_STATE_TEST_INLET_WATER: + break; + + case DG_FILL_MODE_STATE_PRIME_CONCENTRATE_LINES: + // Prepare the acid and bicarb pumps to prime the concentrate lines + setROPumpTargetFlowRateLPM( RO_PUMP_800_ML_PER_MIN / MILLILITERS_PER_LITER, TARGET_RO_PRESSURE_PSI ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, CONCENTRATE_PUMP_MAX_SPEED ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, CONCENTRATE_PUMP_MAX_SPEED ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); + concentratePrimingStartTime = getMSTimerCount(); + break; + + case DG_FILL_MODE_STATE_FLUSH_BUBBLES: + requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID, NO_PARK_CONC_PUMPS ); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); + + // Set the RO pump flow rate in according to the roPumpFlushBubblesSpeed table to flush bubbles + pumpSpeedIndex = 0; + setROPumpTargetFlowRateLPM( RO_PUMP_FLUSH_BUBBLES_FLOWS[ pumpSpeedIndex ] / MILLILITERS_PER_LITER, TARGET_RO_PRESSURE_PSI ); + flushBubblesStartTime = getMSTimerCount(); + break; + + case DG_FILL_MODE_STATE_TEST_BICARB_CONDUCTIVITY: + // Set pumps flow rate to prepare for bicarb conductivity testing + setROPumpTargetFlowRateLPM( RO_PUMP_800_ML_PER_MIN / MILLILITERS_PER_LITER, TARGET_RO_PRESSURE_PSI ); + + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, BICARB_PUMP_40_ML_PER_MIN ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); + + // Prior to collecting data for bicarb test, change the CD2 calibration table + setCondcutivitySensorCalTable( CONDUCTIVITYSENSORS_CD2_SENSOR, CAL_DATA_CD2_COND_SENSOR_FILL_BICARB_TEST ); + totalBicarbConductivity = 0.0F; + averageBicarbConductivity = 0.0F; + bicarbConductivitySampleCount = 0; + concentrateTestStartTime = getMSTimerCount(); + break; + + case DG_FILL_MODE_STATE_TEST_ACID_CONDUCTIVITY: + // Initialization + requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); + // Set pumps flow rate to prepare for acid conductivity testing + setROPumpTargetFlowRateLPM( RO_PUMP_800_ML_PER_MIN / MILLILITERS_PER_LITER, TARGET_RO_PRESSURE_PSI ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, ACID_PUMP_20_ML_PER_MIN ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); + + // Set back the conductivity of CD2 calibration table to the normal calibration table + setCondcutivitySensorCalTable( CONDUCTIVITYSENSORS_CD2_SENSOR, CAL_DATA_CD2_COND_SENSOR ); + totalBicarbConductivity = 0.0F; + totalAcidConductivity = 0.0F; + bicarbConductivitySampleCount = 0; + acidConductivitySampleCount = 0; + concentrateTestStartTime = getMSTimerCount(); + break; + + case DG_FILL_MODE_STATE_PRODUCE_DIALYSATE: + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, CONCENTRATE_PUMP_MAX_SPEED ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, CONCENTRATE_PUMP_MAX_SPEED ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); + concPumpPrimeStartTimeMS = getMSTimerCount(); + fillStatus.isThisFirstFill = FALSE; + break; + + case DG_FILL_MODE_STATE_DELIVER_DIALYSATE: + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); + dialysateFillStartTimeMS = getMSTimerCount(); + fillStatus.isThisFirstFill = FALSE; + break; + + case DG_FILL_MODE_STATE_PAUSED: + if ( FALSE == havePauseActuatorsBeenSet ) + { + setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); + setROPumpTargetFlowRateLPM( TARGET_RO_FLOW_RATE_IN_PAUSE_L, TARGET_RO_PRESSURE_PSI ); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID, NO_PARK_CONC_PUMPS ); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB, NO_PARK_CONC_PUMPS ); + havePauseActuatorsBeenSet = TRUE; + } + break; + + default: + // Do nothing. Prime state out of range is controlled in the exec function + break; + } +} + +/*********************************************************************//** + * @brief * The areInletWaterConditionsAlarmsActive function checks whether the inlet * water conditions are out of range and any of their alarms are active. * @details Inputs: none