Index: firmware/App/Controllers/BalancingChamber.c =================================================================== diff -u -r3a22e84a4c5ff8d7ffc77faa2ed69af31ae5852d -ra8f5f7020e488eb4d326a136be0e71cefdefe717 --- firmware/App/Controllers/BalancingChamber.c (.../BalancingChamber.c) (revision 3a22e84a4c5ff8d7ffc77faa2ed69af31ae5852d) +++ firmware/App/Controllers/BalancingChamber.c (.../BalancingChamber.c) (revision a8f5f7020e488eb4d326a136be0e71cefdefe717) @@ -114,6 +114,7 @@ static void publishBalChamberData( void ); static U32 getBalChamberDataPublishInterval( void ); static void checkSpentFillComplete( F32 spentDialPressure ); +static BOOL isSpentFillCompleteByPressure( F32 spentDialPressure, F32 qdMlpm, F32 spentFillCompletePresPsig ); /*********************************************************************//** * @brief @@ -146,7 +147,6 @@ balChamberSwitchingPeriod = 0; balChamberValveClosePeriod = 0; isBalChamberFillInProgress = FALSE; - currentBalChamberSwitchingCounter = 0; isPressureStabilizedDuringFill = FALSE; lastTdDialysateFlowrate = 0.0F; balChamberDataPublicationTimerCounter = 0; @@ -156,14 +156,15 @@ isPressureDroppedDuringFill = FALSE; freshDialPressure = 0.0F; spentDialPressure = 0.0F; - currentBalChamberFillCounter = 0; balChamberFillTimeoutCount = 0; diffSpentFillCompleteCount = 0; - isSpentFillComplete = FALSE; lastPrevSpentDialPressure = 0.0F; prevSpentDialPressure = 0.0F; + currentBalChamberSwitchingCounter = 0; + currentBalChamberFillCounter = 0; spentFillRiseHitCount = 0; spentFillRiseMissCounter = 0; + isSpentFillComplete = FALSE; //TODO:remove once level sensor working bicarbChamberPeriodicFillCounter = 0; } @@ -220,6 +221,15 @@ //Testing balChamberValveClosePeriod = balChamberSwitchingPeriod; balChamberValveClosePeriod -= 1; // Close valves prior 50 msecond for testing + + currentBalChamberFillCounter = 0; + currentBalChamberSwitchingCounter = 0; + spentFillRiseHitCount = 0; + spentFillRiseMissCounter = 0; + isSpentFillComplete = FALSE; + spentDialPressure = getFilteredPressure( D51_PRES ); + lastPrevSpentDialPressure = spentDialPressure; + prevSpentDialPressure = spentDialPressure; } } @@ -233,6 +243,8 @@ *************************************************************************/ U32 execBalancingChamberControl( void ) { + updateBalChamberSwitchingPeriod(); + // Increment counter indicating fill is in progress. currentBalChamberSwitchingCounter += 1; currentBalChamberFillCounter += 1; @@ -466,18 +478,18 @@ static BAL_CHAMBER_EXEC_STATE_T handleBalChamberState1FillStart( void ) { BAL_CHAMBER_EXEC_STATE_T state = BAL_CHAMBER_STATE1_FILL_START; - currentBalChamberSwitchingCounter = 0; balChamberSWState = BAL_CHAMBER_SW_STATE1; - currentBalChamberFillCounter = 0; balChamberFillTimeoutCount = 0; isBalChamberFillInProgress = FALSE; isPressureStabilizedDuringFill = FALSE; isPressureDroppedDuringFill = FALSE; - isSpentFillComplete = FALSE; lastPrevSpentDialPressure = 0.0F; prevSpentDialPressure = 0.0F; + currentBalChamberSwitchingCounter = 0; + currentBalChamberFillCounter = 0; spentFillRiseHitCount = 0; spentFillRiseMissCounter = 0; + isSpentFillComplete = FALSE; F32 acidVolume = getF32OverrideValue( &acidDoseVolume ); F32 bicarbVolume = getF32OverrideValue( &bicarbDoseVolume ); @@ -698,15 +710,15 @@ static BAL_CHAMBER_EXEC_STATE_T handleBalChamberState2FillStart( void ) { BAL_CHAMBER_EXEC_STATE_T state = BAL_CHAMBER_STATE2_FILL_START; - currentBalChamberSwitchingCounter = 0; isBalChamberFillInProgress = FALSE; isPressureStabilizedDuringFill = FALSE; isPressureDroppedDuringFill = FALSE; balChamberSWState = BAL_CHAMBER_SW_STATE2; - currentBalChamberFillCounter = 0; balChamberFillTimeoutCount = 0; lastPrevSpentDialPressure = 0.0F; prevSpentDialPressure = 0.0F; + currentBalChamberSwitchingCounter = 0; + currentBalChamberFillCounter = 0; spentFillRiseHitCount = 0; spentFillRiseMissCounter = 0; isSpentFillComplete = FALSE; @@ -872,6 +884,78 @@ /*********************************************************************//** * @brief + * The isSpentFillCompleteByPressure function evaluates whether the spent side of the + * balancing chamber fill is complete from D51 pressure. + * @details \b Inputs: spentDialPressure, qdMlpm, spentFillCompletePresPsig, valve-close period, + * fill counter, Diener pump test config, and D51 slope history for low-Qd slope mode. + * @details \b Outputs: spentFillRiseHitCount, spentFillRiseMissCounter, + * lastPrevSpentDialPressure, prevSpentDialPressure (updated only in slope mode). + * @param spentDialPressure filtered spent dialysate pressure (PSIG). + * @param qdMlpm dialysate flow rate (mL/min). + * @param spentFillCompletePresPsig spent fill complete pressure threshold for current Qd and pump. + * @return TRUE if spent fill is detected this task period; FALSE otherwise. + *************************************************************************/ +static BOOL isSpentFillCompleteByPressure( F32 spentDialPressure, F32 qdMlpm, F32 spentFillCompletePresPsig ) +{ + BOOL useSlopeDetector = ( ( TRUE != getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DIENER_2000_PUMP ) ) && + ( qdMlpm <= SPENT_FILL_COMPLETE_QD_SLOPE_MAX_MLPM ) ); + + if ( TRUE == useSlopeDetector ) + { + U32 detectTolCount = (U32)( (F32)balChamberValveClosePeriod * SPENT_FILL_DETECT_COUNT_TOL_PCT ); + U32 maxDetectCount = balChamberValveClosePeriod + detectTolCount; + U32 minDetectCount = balChamberValveClosePeriod - detectTolCount; + BOOL isDetectionInCountWindow = ( ( currentBalChamberFillCounter >= minDetectCount ) && + ( currentBalChamberFillCounter <= maxDetectCount ) ); + F32 riseDeltaPsi = spentDialPressure - lastPrevSpentDialPressure; + BOOL riseHit = ( riseDeltaPsi > SPENT_FILL_COMPLETE_DP_RISE_PSIG ); + U32 requiredRiseCount; + + if ( riseDeltaPsi > SPENT_FILL_SLOPE_SPENT_PRESSURE_HIGH_PSIG ) + { + requiredRiseCount = 1U; + } + else if ( riseDeltaPsi < SPENT_FILL_SLOPE_SPENT_PRESSURE_LOW_PSIG ) + { + requiredRiseCount = ( qdMlpm <= SPENT_FILL_COMPLETE_QD_TWO_HIT_MAX_MLPM ) ? SPENT_FILL_SLOPE_MAX_RISE_HITS : 1U; + } + else + { + requiredRiseCount = 1U; + } + + if ( ( TRUE == riseHit ) && ( TRUE == isDetectionInCountWindow ) ) + { + spentFillRiseHitCount += 1; + spentFillRiseMissCounter = 0; + } + else if ( spentFillRiseHitCount > 0 ) + { + if ( ( FALSE == riseHit ) && ( TRUE == isDetectionInCountWindow ) ) + { + spentFillRiseMissCounter += 1; + + if ( spentFillRiseMissCounter >= 2 ) + { + spentFillRiseHitCount = 0; + spentFillRiseMissCounter = 0; + } + } + } + + lastPrevSpentDialPressure = prevSpentDialPressure; + prevSpentDialPressure = spentDialPressure; + + return ( ( spentFillRiseHitCount >= requiredRiseCount ) || + ( ( currentBalChamberFillCounter >= balChamberValveClosePeriod ) && + ( spentDialPressure >= spentFillCompletePresPsig ) ) ); + } + + return ( spentDialPressure >= spentFillCompletePresPsig ); +} + +/*********************************************************************//** + * @brief * The checkSpentFillComplete function checks the pressure difference for * spent side fill completion and adjusts the D48 pump speed to align the * fill timing close to the switching period time. @@ -892,15 +976,7 @@ F32 qdMlpm = getTDDialysateFlowrate(); BOOL result = FALSE; F32 spentFillCompletePresPsig; - BOOL useSlopeDetector = FALSE; BOOL isSpentFillCompleteDetected = FALSE; - U32 requiredRiseCount = SPENT_FILL_SLOPE_MAX_RISE_HITS; - U32 detectTolCount = 0; - U32 minDetectCount = 0; - U32 maxDetectCount = 0; - BOOL isDetectionInCountWindow = FALSE; - F32 riseDeltaPsi = 0.0F; - BOOL riseHit = FALSE; // Diener 2000 pump: spent fill complete pressure use legacy 25 PSI. Other pump: depends on Qd. if ( TRUE == getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DIENER_2000_PUMP ) ) @@ -923,85 +999,37 @@ } } - // For low Qd on Diener-1000 path use a slope-based rising-edge check; otherwise retain absolute-pressure completion. - useSlopeDetector = ( ( TRUE != getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DIENER_2000_PUMP ) ) && - ( qdMlpm <= SPENT_FILL_COMPLETE_QD_SLOPE_MAX_MLPM ) ); + isSpentFillCompleteDetected = isSpentFillCompleteByPressure( spentDialPressure, qdMlpm, spentFillCompletePresPsig ); - if ( TRUE == useSlopeDetector ) + if ( ( TRUE == isSpentFillCompleteDetected ) && ( isSpentFillComplete != TRUE ) ) { - detectTolCount = (U32)( (F32)balChamberValveClosePeriod * SPENT_FILL_DETECT_COUNT_TOL_PCT ); - maxDetectCount = balChamberValveClosePeriod + detectTolCount; - minDetectCount = balChamberValveClosePeriod - detectTolCount; - - isDetectionInCountWindow = ( ( currentBalChamberFillCounter >= minDetectCount ) && - ( currentBalChamberFillCounter <= maxDetectCount ) ); - - riseDeltaPsi = spentDialPressure - lastPrevSpentDialPressure; - riseHit = ( riseDeltaPsi > SPENT_FILL_COMPLETE_DP_RISE_PSIG ); - - if ( spentDialPressure > SPENT_FILL_SLOPE_SPENT_PRESSURE_HIGH_PSIG ) + // Check spent fill time against the balancing chamber closing period + if ( balChamberValveClosePeriod > 0 ) { - requiredRiseCount = 1; - } - else if ( spentDialPressure < SPENT_FILL_SLOPE_SPENT_PRESSURE_LOW_PSIG ) - { - requiredRiseCount = ( qdMlpm <= SPENT_FILL_COMPLETE_QD_TWO_HIT_MAX_MLPM ) ? SPENT_FILL_SLOPE_MAX_RISE_HITS : 1U; - } - else - { - requiredRiseCount = 1; - } + diffSpentFillCompleteCount = balChamberValveClosePeriod - currentBalChamberFillCounter; + absDiffSpentFillCount = abs(diffSpentFillCompleteCount); + adjustedSpeed = ( ( (F32)absDiffSpentFillCount / (F32)balChamberValveClosePeriod ) * spentDialPumpSpeed ) * D48_SPEED_ADJUST_FACTOR; - if ( ( TRUE == riseHit ) && ( TRUE == isDetectionInCountWindow ) ) - { - spentFillRiseHitCount += 1; - spentFillRiseMissCounter = 0; - } - else if ( spentFillRiseHitCount > 0 ) - { - if ( ( FALSE == riseHit ) && ( TRUE == isDetectionInCountWindow ) ) + result = ( ( diffSpentFillCompleteCount <= 0 ) && ( diffSpentFillCompleteCount >= -2 ) ) ? TRUE : FALSE; + //Not adjust the D48 pump speed if the fill counter is just 50ms difference from the closing period (considering only positive DEADBAND as negative deadband might indicate under fill of BC). + if ( FALSE == result ) { - spentFillRiseMissCounter += 1; - - if ( spentFillRiseMissCounter >= 2 ) + if ( diffSpentFillCompleteCount < SPENT_DIFF_COUNT_ZERO ) { - spentFillRiseHitCount = 0; - spentFillRiseMissCounter = 0; + // Increase the D48 pump speed + spentDialPumpSpeed += adjustedSpeed; } - } - } + else + { + //Decrease the D48 pump speed + spentDialPumpSpeed -= adjustedSpeed; + } - isSpentFillCompleteDetected = ( spentFillRiseHitCount >= requiredRiseCount ); - lastPrevSpentDialPressure = prevSpentDialPressure; - prevSpentDialPressure = spentDialPressure; - } + d48SpeedPostRangeCheck = RANGE( spentDialPumpSpeed, minD48Speed, maxD48Speed ); - if ( ( TRUE == isSpentFillCompleteDetected ) && ( isSpentFillComplete != TRUE ) ) - { - // Check spent fill time against the balancing chamber closing period - diffSpentFillCompleteCount = balChamberValveClosePeriod - currentBalChamberFillCounter; - absDiffSpentFillCount = abs(diffSpentFillCompleteCount); - adjustedSpeed = ( ( (F32)absDiffSpentFillCount / (F32)balChamberValveClosePeriod ) * spentDialPumpSpeed ) * D48_SPEED_ADJUST_FACTOR; - - result = ( ( diffSpentFillCompleteCount <= 0 ) && ( diffSpentFillCompleteCount >= -2 ) ) ? TRUE : FALSE; - //Not adjust the D48 pump speed if the fill counter is just 50ms difference from the closing period (considering only positive DEADBAND as negative deadband might indicate under fill of BC). - if ( FALSE == result ) - { - if ( diffSpentFillCompleteCount < SPENT_DIFF_COUNT_ZERO ) - { - // Increase the D48 pump speed - spentDialPumpSpeed += adjustedSpeed; + // Update the D48 pump speed + setD48PumpSpeedForBCFill( d48SpeedPostRangeCheck ); } - else - { - //Decrease the D48 pump speed - spentDialPumpSpeed -= adjustedSpeed; - } - - d48SpeedPostRangeCheck = RANGE( spentDialPumpSpeed, minD48Speed, maxD48Speed ); - - // Update the D48 pump speed - setD48PumpSpeedForBCFill( d48SpeedPostRangeCheck ); } //Update spent fill is complete