Index: firmware/App/Controllers/BalancingChamber.c =================================================================== diff -u -r7278aeac8fdd894067a05c3bd3a177d38c0b0803 -r081b2525e3a650671d770513eb841057d88ea505 --- firmware/App/Controllers/BalancingChamber.c (.../BalancingChamber.c) (revision 7278aeac8fdd894067a05c3bd3a177d38c0b0803) +++ firmware/App/Controllers/BalancingChamber.c (.../BalancingChamber.c) (revision 081b2525e3a650671d770513eb841057d88ea505) @@ -45,16 +45,17 @@ #define BAL_CHAMBER_DATA_PUBLISH_INTERVAL ( 250 / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the balancing chamber data published. #define BAL_CHAMBER_FILL_PRES_DROP_MS ( 200 / TASK_GENERAL_INTERVAL ) ///< Time (ms/tasktime) to confirm the balancing chamber filling started and corrosponding valves opened. +#if 1 +#define BAL_CHAMBER_FILL_COMPLETE_MS ( 100 / TASK_GENERAL_INTERVAL ) ///< Time (ms/tasktime) to confirm the balancing chamber fill completed and pressure is within range +#else #define BAL_CHAMBER_FILL_COMPLETE_MS ( 300 / TASK_GENERAL_INTERVAL ) ///< Time (ms/tasktime) to confirm the balancing chamber fill completed and pressure is within range -#define SPENT_FILL_COMPLETE_PRES 25.0F ///< Spent fill complete pressure (PSI) for Diener 2000 pump. -#define SPENT_FILL_COMPLETE_PRES_QD_MID_PSIG 10.0F ///< Spent fill complete pressure (PSI) when Diener 1000 and 200 < Qd <= 400. -#define SPENT_FILL_COMPLETE_PRES_QD_HIGH_PSIG 20.0F ///< Spent fill complete pressure (PSI) when Diener 1000 and Qd > 400. -#define SPENT_FILL_COMPLETE_QD_SLOPE_MAX_MLPM 300.0F ///< For Qd <= 300 mL/min, spent fill completion uses pressure-rise slope detection. +#endif +#define SPENT_FILL_COMPLETE_QD_LOW_RISE_MAX_MLPM 300.0F ///< For Qd <= 300 mL/min (Diener 1000). #define SPENT_FILL_COMPLETE_DP_RISE_PSIG 0.5F ///< Minimum 100 ms spent pressure rise (current minus n-2) to count as a rise hit at low Qd. -#define SPENT_FILL_SLOPE_SPENT_PRESSURE_HIGH_PSIG 2.0F ///< Above this absolute spent pressure, only one rise hit is required. +#define SPENT_FILL_COMPLETE_DP_RISE_HIGH_QD_PSIG 3.0F ///< Minimum spent pressure rise for Diener 2000 or Qd > 300 mL/min. +#define SPENT_FILL_SLOPE_SPENT_PRESSURE_HIGH_PSIG 2.0F ///< Above this spent pressure rise, only one rise hit is required. #define SPENT_FILL_SLOPE_MAX_RISE_HITS 2 ///< Rise hits required when Qd <= 150 in the low spent-pressure band. #define SPENT_FILL_DETECT_COUNT_TOL_PCT 1.0F ///< Allowed detection timing tolerance as a fraction of expected BC switching count. -#define QD_THRESHOLD_HIGH_MLPM 400.0F ///< Qd threshold (mL/min) below which mid pressure limit applies. #define SPENT_DIFF_COUNT_ZERO 0 ///< Zero count difference for spent side fill comparing target count #define D48_SPEED_ADJUST_FACTOR 0.5F ///< D48 speed adjustment factor ( 50% of speed adjustment = 0.5) #define D48_SPEED_RANGE_LIMIT 0.25F ///< D48 speed adjustment range check limit ( D48 speed can vary +/-25% of initial calculated speed) @@ -99,6 +100,7 @@ static U32 balChamberFillTimeoutCount; ///< Timeout count (in task interval) to detect BC fill timeout. static S32 diffSpentFillCompleteCount; ///< Difference between spent target fill to actual fill count static BOOL isSpentFillComplete; ///< Flag indicating spent side fill complete. +static BOOL isFreshSideValvesClosed; ///< Flag indicating fresh-side BC valves are closed while spent side may still be filling. static F32 lastPrevSpentDialPressure; ///< Low-Qd slope: spent pressure last sample of dosing (tick before VALVES_CLOSE); then n-2 in VC. static F32 prevSpentDialPressure; ///< Spent pressure previous sample (n-1) during VALVES_CLOSE for low-Qd slope detection. static U32 spentFillRiseHitCount; ///< Low-Qd slope: counted rise hits (only incremented when in timing window). @@ -129,10 +131,13 @@ static void publishBalChamberData( void ); static U32 getBalChamberDataPublishInterval( void ); static void checkSpentFillComplete( F32 spentDialPressure ); -static BOOL isSpentFillCompleteByPressure( F32 spentDialPressure, F32 qdMlpm, F32 spentFillCompletePresPsig ); +static BOOL isSpentFillCompleteByPressure( F32 spentDialPressure, F32 qdMlpm ); static void applyBalChamberSwitchingPeriod( F32 tdDialysateFlowrate ); static BOOL isBalChamberTimeBasedSwitching( void ); static void scheduleFirstCycleRelaxAfterQdApply( void ); +static void valveControlForBCState1FreshSideClose( void ); +static void valveControlForBCState2FreshSideClose( void ); +static void closeFreshSideValvesWhenFillComplete( void ); static void calculateBalancingChamberError( void ); /*********************************************************************//** @@ -186,6 +191,7 @@ spentFillRiseHitCount = 0; spentFillRiseMissCounter = 0; isSpentFillComplete = FALSE; + isFreshSideValvesClosed = FALSE; isBalChamberSwitchingActive = FALSE; isBalChamberSwitchingOnRequested = FALSE; isBalChamberSwitchingOffRequested = FALSE; @@ -320,6 +326,7 @@ spentFillRiseHitCount = 0; spentFillRiseMissCounter = 0; isSpentFillComplete = FALSE; + isFreshSideValvesClosed = FALSE; spentDialPressure = getFilteredPressure( D51_PRES ); lastPrevSpentDialPressure = spentDialPressure; prevSpentDialPressure = spentDialPressure; @@ -343,7 +350,9 @@ *************************************************************************/ static void scheduleFirstCycleRelaxAfterQdApply( void ) { - bcSwitchingBasedOnClosedPeriodCounter = 2; + //TODO : revert after testing + //bcSwitchingBasedOnClosedPeriodCounter = 2; + bcSwitchingBasedOnClosedPeriodCounter = 4; } /*********************************************************************//** @@ -640,6 +649,59 @@ /*********************************************************************//** * @brief + * The valveControlForBCState1FreshSideClose function closes only the fresh-side + * balancing chamber valves opened during state 1 fill. + * @details \b Inputs: none + * @details \b Outputs: valve states + * @return none. + *************************************************************************/ +static void valveControlForBCState1FreshSideClose( void ) +{ + setValveState( D19_VALV, VALVE_STATE_CLOSED ); + setValveState( D24_VALV, VALVE_STATE_CLOSED ); +} + +/*********************************************************************//** + * @brief + * The valveControlForBCState2FreshSideClose function closes only the fresh-side + * balancing chamber valves opened during state 2 fill. + * @details \b Inputs: none + * @details \b Outputs: valve states + * @return none. + *************************************************************************/ +static void valveControlForBCState2FreshSideClose( void ) +{ + setValveState( D26_VALV, VALVE_STATE_CLOSED ); + setValveState( D21_VALV, VALVE_STATE_CLOSED ); +} + +/*********************************************************************//** + * @brief + * The closeFreshSideValvesWhenFillComplete function closes the fresh-side BC + * valves once fresh fill is detected, without waiting for spent fill. + * @details \b Inputs: balChamberSWState, isPressureStabilizedDuringFill, isFreshSideValvesClosed + * @details \b Outputs: isFreshSideValvesClosed, valve states + * @return none. + *************************************************************************/ +static void closeFreshSideValvesWhenFillComplete( void ) +{ + if ( ( TRUE == isPressureStabilizedDuringFill ) && ( FALSE == isFreshSideValvesClosed ) ) + { + if ( BAL_CHAMBER_SW_STATE1 == balChamberSWState ) + { + valveControlForBCState1FreshSideClose(); + } + else + { + valveControlForBCState2FreshSideClose(); + } + + isFreshSideValvesClosed = TRUE; + } +} + +/*********************************************************************//** + * @brief * The handleBalChamberState1FillStart function handles the balancing chamber * state 1 fill and time to fill chamber counter being updated. * @details \b Inputs: Pressure @@ -665,6 +727,7 @@ spentFillRiseHitCount = 0; spentFillRiseMissCounter = 0; isSpentFillComplete = FALSE; + isFreshSideValvesClosed = FALSE; if ( FALSE == getTestConfigStatus( TEST_CONFIG_DD_DISABLE_DRY_BICARB ) ) { @@ -795,7 +858,6 @@ static BAL_CHAMBER_EXEC_STATE_T handleBalChamberState1FillDetectComplete( void ) { BAL_CHAMBER_EXEC_STATE_T state = BAL_CHAMBER_STATE1_FILL_DETECT_COMPLETE; - BOOL isBothFillsComplete = FALSE; BOOL isFirstCycleNotDone = FALSE; BOOL isFillCompleteOrFirstCycle = FALSE; @@ -811,31 +873,46 @@ state = BAL_CHAMBER_STATE_IDLE; } - // If the dry bicarbonate is enabled then we ignore looking at d18 pressure to be in range. - if ( ( FALSE == getTestConfigStatus( TEST_CONFIG_DD_DISABLE_DRY_BICARB ) ) && ( TRUE == getBicarbChamberFillRequested() ) ) - { - isPressureStabilizedDuringFill = TRUE; - } +#if 1 // Check fresh dialysate pressure back in range to indicate fresh fill complete. - else if ( ( freshDialPressure >= FRESH_DIAL_PRESSURE_MIN_PSIG ) && ( freshDialPressure <= FRESH_DIAL_PRESSURE_MAX_PSIG ) ) + if ( ( freshDialPressure >= FRESH_DIAL_PRESSURE_MIN_PSIG ) && ( freshDialPressure <= FRESH_DIAL_PRESSURE_MAX_PSIG ) ) { if ( ++balChamberFillCompleteStablePressureCounter >= BAL_CHAMBER_FILL_COMPLETE_MS ) { // stabilized pressure indicating fresh side fill is complete isPressureStabilizedDuringFill = TRUE; } } +#else + // If the dry bicarbonate is enabled then we ignore looking at d18 pressure to be in range. + if ( ( FALSE == getTestConfigStatus( TEST_CONFIG_DD_DISABLE_DRY_BICARB ) ) && ( TRUE == getBicarbChamberFillRequested() ) ) + { + isPressureStabilizedDuringFill = TRUE; + } + // Check fresh dialysate pressure back in range to indicate fresh fill complete. + else if ( ( freshDialPressure >= FRESH_DIAL_PRESSURE_MIN_PSIG ) && ( freshDialPressure <= FRESH_DIAL_PRESSURE_MAX_PSIG ) ) + { + if ( ++balChamberFillCompleteStablePressureCounter >= BAL_CHAMBER_FILL_COMPLETE_MS ) + { + // stabilized pressure indicating fresh side fill is complete + isPressureStabilizedDuringFill = TRUE; + } + } +#endif + // Close fresh side valves only upon fresh fill completion by detecting pressure rise. + closeFreshSideValvesWhenFillComplete(); + + // Check Spent side fill complete checkSpentFillComplete( spentDialPressure ); - // Check both spent and fresh side fill is complete - isBothFillsComplete = ( ( TRUE == isSpentFillComplete ) && ( TRUE == isPressureStabilizedDuringFill ) ) ? TRUE : FALSE; isFirstCycleNotDone = ( ( FALSE == isFirstCycleBCSwitchingCompleted ) && ( currentBalChamberSwitchingCounter >= balChamberValveClosePeriod ) ) ? TRUE : FALSE; if ( FALSE == getBalChamberSwitchingOnlyStatus() ) { - isFillCompleteOrFirstCycle = ( ( TRUE == isBothFillsComplete ) || ( TRUE == isFirstCycleNotDone ) ) ? TRUE : FALSE; + isFillCompleteOrFirstCycle = ( ( ( TRUE == isSpentFillComplete ) && ( TRUE == isFreshSideValvesClosed ) ) || + ( TRUE == isFirstCycleNotDone ) ) ? TRUE : FALSE; } if ( ( TRUE == isFillCompleteOrFirstCycle ) || @@ -983,6 +1060,7 @@ spentFillRiseHitCount = 0; spentFillRiseMissCounter = 0; isSpentFillComplete = FALSE; + isFreshSideValvesClosed = FALSE; if ( FALSE == getTestConfigStatus( TEST_CONFIG_DD_DISABLE_DRY_BICARB ) ) { @@ -1056,27 +1134,38 @@ static BAL_CHAMBER_EXEC_STATE_T handleBalChamberState2FillDetectComplete( void ) { BAL_CHAMBER_EXEC_STATE_T state = BAL_CHAMBER_STATE2_FILL_DETECT_COMPLETE; - BOOL isBothFillsComplete = FALSE; BOOL isFirstCycleNotDone = FALSE; BOOL isFillCompleteOrFirstCycle = FALSE; freshDialPressure = getFilteredPressure( D18_PRES ); spentDialPressure = getFilteredPressure( D51_PRES ); - // If the dry bicarbonate is enabled then we ignore looking at d18 pressure to be in range. - if ( ( FALSE == getTestConfigStatus( TEST_CONFIG_DD_DISABLE_DRY_BICARB ) ) && ( TRUE == getBicarbChamberFillRequested() ) ) - { - isPressureStabilizedDuringFill = TRUE; - } +#if 1 // Check fresh dialysate pressure back in range to indicate fresh fill complete. - else if ( ( freshDialPressure >= FRESH_DIAL_PRESSURE_MIN_PSIG ) && ( freshDialPressure <= FRESH_DIAL_PRESSURE_MAX_PSIG ) ) + if ( ( freshDialPressure >= FRESH_DIAL_PRESSURE_MIN_PSIG ) && ( freshDialPressure <= FRESH_DIAL_PRESSURE_MAX_PSIG ) ) { if ( ++balChamberFillCompleteStablePressureCounter >= BAL_CHAMBER_FILL_COMPLETE_MS ) { // stabilized pressure indicating fresh side fill is complete isPressureStabilizedDuringFill = TRUE; } } +#else + // If the dry bicarbonate is enabled then we ignore looking at d18 pressure to be in range. + if ( ( FALSE == getTestConfigStatus( TEST_CONFIG_DD_DISABLE_DRY_BICARB ) ) && ( TRUE == getBicarbChamberFillRequested() ) ) + { + isPressureStabilizedDuringFill = TRUE; + } + // Check fresh dialysate pressure back in range to indicate fresh fill complete. + else if ( ( freshDialPressure >= FRESH_DIAL_PRESSURE_MIN_PSIG ) && ( freshDialPressure <= FRESH_DIAL_PRESSURE_MAX_PSIG ) ) + { + if ( ++balChamberFillCompleteStablePressureCounter >= BAL_CHAMBER_FILL_COMPLETE_MS ) + { + // stabilized pressure indicating fresh side fill is complete + isPressureStabilizedDuringFill = TRUE; + } + } +#endif // After the first BC cycle, fault if fill never completes at the Qd-based timeout. if ( ( currentBalChamberFillCounter > balChamberFillTimeoutCount ) && ( TRUE != getTestConfigStatus( TEST_CONFIG_DD_DISABLE_BC_PRESSURE_ALARMS ) ) ) @@ -1087,26 +1176,19 @@ state = BAL_CHAMBER_STATE_IDLE; } - // Check fresh dialysate pressure back in range to indicate fill complete. - if ( ( freshDialPressure >= FRESH_DIAL_PRESSURE_MIN_PSIG ) && ( freshDialPressure <= FRESH_DIAL_PRESSURE_MAX_PSIG ) ) - { - if ( ++balChamberFillCompleteStablePressureCounter >= BAL_CHAMBER_FILL_COMPLETE_MS ) - { - // stabilized pressure indicating fresh side fill is complete - isPressureStabilizedDuringFill = TRUE; - } - } + // Close fresh side valves only upon fresh fill completion by detecting pressure rise. + closeFreshSideValvesWhenFillComplete(); + // Check Spent side fill complete checkSpentFillComplete( spentDialPressure ); - // Check switching cycle time or pressure check for valve closure - isBothFillsComplete = ( ( TRUE == isSpentFillComplete ) && ( TRUE == isPressureStabilizedDuringFill ) ) ? TRUE : FALSE; isFirstCycleNotDone = ( ( FALSE == isFirstCycleBCSwitchingCompleted ) && ( currentBalChamberSwitchingCounter >= balChamberValveClosePeriod ) ) ? TRUE : FALSE; if ( FALSE == getBalChamberSwitchingOnlyStatus() ) { - isFillCompleteOrFirstCycle = ( ( TRUE == isBothFillsComplete ) || ( TRUE == isFirstCycleNotDone ) ) ? TRUE : FALSE; + isFillCompleteOrFirstCycle = ( ( ( TRUE == isSpentFillComplete ) && ( TRUE == isFreshSideValvesClosed ) ) || + ( TRUE == isFirstCycleNotDone ) ) ? TRUE : FALSE; } if ( ( TRUE == isFillCompleteOrFirstCycle ) || @@ -1284,73 +1366,65 @@ * @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 Inputs: spentDialPressure, qdMlpm, valve-close period, fill counter, + * Diener pump test config, and D51 slope history. * @details \b Outputs: spentFillRiseHitCount, spentFillRiseMissCounter, - * lastPrevSpentDialPressure, prevSpentDialPressure (updated only in slope mode). + * lastPrevSpentDialPressure, prevSpentDialPressure. * @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 ) +static BOOL isSpentFillCompleteByPressure( F32 spentDialPressure, F32 qdMlpm ) { - BOOL useSlopeDetector = ( ( ( TRUE != getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DIENER_2000_PUMP ) ) && - ( qdMlpm <= SPENT_FILL_COMPLETE_QD_SLOPE_MAX_MLPM ) ) ? TRUE : FALSE ); + BOOL useLowQdRiseThreshold = ( ( ( TRUE != getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DIENER_2000_PUMP ) ) && + ( qdMlpm <= SPENT_FILL_COMPLETE_QD_LOW_RISE_MAX_MLPM ) ) ? TRUE : FALSE ); + F32 riseThresholdPsig = ( TRUE == useLowQdRiseThreshold ) ? SPENT_FILL_COMPLETE_DP_RISE_PSIG : + SPENT_FILL_COMPLETE_DP_RISE_HIGH_QD_PSIG; BOOL state; - if ( TRUE == useSlopeDetector ) + // Gate slope hits near expected valve-close count (current vs balChamberValveClosePeriod +/- tolerance). + 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 ) ) ? TRUE : FALSE; + F32 riseDeltaPsi = spentDialPressure - lastPrevSpentDialPressure; + BOOL riseHit = ( riseDeltaPsi > riseThresholdPsig ) ? TRUE : FALSE; + U32 requiredRiseCount; + + // Mid band between low/high spent pressure rise: require two rise hits. + if ( riseDeltaPsi > SPENT_FILL_SLOPE_SPENT_PRESSURE_HIGH_PSIG ) { - // Gate slope hits near expected valve-close count (current vs balChamberValveClosePeriod +/- tolerance). - 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 ) ) ? TRUE : FALSE; - F32 riseDeltaPsi = spentDialPressure - lastPrevSpentDialPressure; - BOOL riseHit = ( riseDeltaPsi > SPENT_FILL_COMPLETE_DP_RISE_PSIG ) ? TRUE : FALSE; - U32 requiredRiseCount; + requiredRiseCount = 1U; + } + else + { + requiredRiseCount = 2U; + } - // Mid band between low/high spent pressure: require two rise hits. - if ( riseDeltaPsi > SPENT_FILL_SLOPE_SPENT_PRESSURE_HIGH_PSIG ) + if ( ( TRUE == riseHit ) && ( TRUE == isDetectionInCountWindow ) ) + { + spentFillRiseHitCount += 1; + spentFillRiseMissCounter = 0; + } + else if ( spentFillRiseHitCount > 0 ) + { + if ( ( FALSE == riseHit ) && ( TRUE == isDetectionInCountWindow ) ) { - requiredRiseCount = 1U; - } - else - { - requiredRiseCount = 2U; - } + spentFillRiseMissCounter += 1; - if ( ( TRUE == riseHit ) && ( TRUE == isDetectionInCountWindow ) ) - { - spentFillRiseHitCount += 1; - spentFillRiseMissCounter = 0; - } - else if ( spentFillRiseHitCount > 0 ) - { - if ( ( FALSE == riseHit ) && ( TRUE == isDetectionInCountWindow ) ) + if ( spentFillRiseMissCounter >= 2 ) { - spentFillRiseMissCounter += 1; - - if ( spentFillRiseMissCounter >= 2 ) - { - spentFillRiseHitCount = 0; - spentFillRiseMissCounter = 0; - } + spentFillRiseHitCount = 0; + spentFillRiseMissCounter = 0; } } + } - lastPrevSpentDialPressure = prevSpentDialPressure; - prevSpentDialPressure = spentDialPressure; + lastPrevSpentDialPressure = prevSpentDialPressure; + prevSpentDialPressure = spentDialPressure; - // Complete on slope hits, or on absolute pressure at period only if Qd > low band (low Qd: slope-only, no absolute-pressure fallback). - state = ( spentFillRiseHitCount >= requiredRiseCount ) ? TRUE : FALSE; - } - else - { - // Not in slope mode (Diener 2000 pump or Qd > SPENT_FILL_COMPLETE_QD_SLOPE_MAX_MLPM): threshold-only spent fill complete. - state = ( spentDialPressure >= spentFillCompletePresPsig ) ? TRUE : FALSE; - } + state = ( spentFillRiseHitCount >= requiredRiseCount ) ? TRUE : FALSE; return state; } @@ -1375,7 +1449,6 @@ U32 d48SpeedPostRangeCheck = 0; F32 qdMlpm = getBalChamberActiveDialysateFlowrate(); BOOL result = FALSE; - F32 spentFillCompletePresPsig; BOOL isSpentFillCompleteDetected = FALSE; if ( TRUE == isBalChamberTimeBasedSwitching() ) @@ -1387,25 +1460,8 @@ } else { - // 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 ) ) - { - spentFillCompletePresPsig = SPENT_FILL_COMPLETE_PRES; - } - else - { - if ( qdMlpm <= QD_THRESHOLD_HIGH_MLPM ) - { - spentFillCompletePresPsig = SPENT_FILL_COMPLETE_PRES_QD_MID_PSIG; - } - else - { - spentFillCompletePresPsig = SPENT_FILL_COMPLETE_PRES_QD_HIGH_PSIG; - } - } + isSpentFillCompleteDetected = isSpentFillCompleteByPressure( spentDialPressure, qdMlpm ); - isSpentFillCompleteDetected = isSpentFillCompleteByPressure( spentDialPressure, qdMlpm, spentFillCompletePresPsig ); - if ( ( TRUE == isSpentFillCompleteDetected ) && ( isSpentFillComplete != TRUE ) ) { // Check spent fill time against the balancing chamber closing period @@ -1479,6 +1535,66 @@ /*********************************************************************//** * @brief + * The getBalChamberFreshSideValvesClosedStatus function returns whether the + * fresh-side balancing chamber valves are closed for the current switch state. + * @details \b Inputs: isFreshSideValvesClosed + * @details \b Outputs: none + * @return TRUE when fresh-side BC valves are closed. + *************************************************************************/ +BOOL getBalChamberFreshSideValvesClosedStatus( void ) +{ + return isFreshSideValvesClosed; +} + +/*********************************************************************//** + * @brief + * The getBalChamberFreshFillCompleteStatus function returns whether fresh-side + * fill completed during the current BC switch cycle. + * @details \b Inputs: isPressureStabilizedDuringFill + * @details \b Outputs: none + * @return TRUE when fresh-side fill is complete. + *************************************************************************/ +BOOL getBalChamberFreshFillCompleteStatus( void ) +{ + return isPressureStabilizedDuringFill; +} + +/*********************************************************************//** + * @brief + * The getBalChamberSpentFillCompleteStatus function returns whether spent-side + * fill completed during the current BC switch cycle. + * @details \b Inputs: isSpentFillComplete + * @details \b Outputs: none + * @return TRUE when spent-side fill is complete. + *************************************************************************/ +BOOL getBalChamberSpentFillCompleteStatus( void ) +{ + return isSpentFillComplete; +} + +/*********************************************************************//** + * @brief + * The isBalChamberSwitchImminent function returns whether the balancing chamber + * is within the valve-close window (50 ms) before switching. + * @details \b Inputs: currentBalChamberSwitchingCounter, balChamberValveClosePeriod + * @details \b Outputs: none + * @return TRUE when BC switch is imminent. + *************************************************************************/ +BOOL isBalChamberSwitchImminent( void ) +{ + BOOL result = FALSE; + + if ( ( balChamberValveClosePeriod > 0 ) && + ( currentBalChamberSwitchingCounter >= balChamberSwitchingPeriod ) ) + { + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief * The getBalChamberSwitchingFreq function gets the balancing chamber switching * frequency value. * @details \b Inputs: balChamberSwitchingFreq Index: firmware/App/Controllers/DryBiCart.c =================================================================== diff -u -r7278aeac8fdd894067a05c3bd3a177d38c0b0803 -r081b2525e3a650671d770513eb841057d88ea505 --- firmware/App/Controllers/DryBiCart.c (.../DryBiCart.c) (revision 7278aeac8fdd894067a05c3bd3a177d38c0b0803) +++ firmware/App/Controllers/DryBiCart.c (.../DryBiCart.c) (revision 081b2525e3a650671d770513eb841057d88ea505) @@ -52,12 +52,12 @@ #define DRY_BICART_FILL_COMPLETE_TIME_MS ( 1 * MS_PER_SECOND ) ///< Wait time to reset the request flag after fill complete #define DRY_BICART_WCID2_FILL_COMPLETE_PRESSURE_PSI ( 10.0F + WCDI2_PRESSURE_OFFSET_PSI ) ///< Maximum pressure reached to indicate the dry bicart fill being completed for WCID2 -#define DRY_BICART_WCID1_FILL_COMPLETE_PRESSURE_PSI ( 10.0F + WCID1_PRESSURE_OFFSET_PSI ) ///< Maximum pressure reached to indicate the dry bicart fill being completed for WCID1 +#define DRY_BICART_WCID1_FILL_COMPLETE_PRESSURE_PSI ( 10.0F + WCID1_PRESSURE_OFFSET_PSI ) ///< Maximum pressure reached to indicate the dry bicart fill being completed for WCID1. #define GET_FILL_COMPLETE_PRESSURE_PSI (getTestConfigStatus( TEST_CONFIG_DD_ENABLE_WCID_1 ) != TRUE ? \ DRY_BICART_WCID2_FILL_COMPLETE_PRESSURE_PSI : DRY_BICART_WCID1_FILL_COMPLETE_PRESSURE_PSI ) ///< Get fill complete pressure based on the WCID configuration #define DRY_BICART_FILL_INITIATE_PRESSURE_PSI 1.5F ///< Minimum pressure required to initiate the dry bicart fill process. #define DRY_BICART_FILL_COMPLETE_SUPPLY_PRESSURE_PSI 10.0F ///< Maximum pressure allowed at bicart fill during supply process/state -#define DRY_BICART_FILL_INITIATE_SUPPLY_PRESSURE_PSI 3.0F ///< Minimum pressure required to initiate the dry bicart fill during supply process/state +#define DRY_BICART_FILL_INITIATE_SUPPLY_PRESSURE_PSI 4.0F ///< Minimum pressure required to initiate the dry bicart fill during supply process/state #define DRY_BICART_MAX_FILL_CYCLE_CNT 10 ///< Max fill cycle allowed (by override) for dry bicart fill/mix with water. #define DRY_BICART_MINIMUM_FILL_CYCLE_CNT 3 ///< Minimum fill cycle count for filling dry bicart // Dry Bicart Fill Vent @@ -74,6 +74,7 @@ #define DRY_BICART_SUPPLY_VENT_TIME_MS ( 1 * MS_PER_SECOND ) ///< Wait time to vent dry bicart gas before actuating Bicarb chamber(F) venting. #define DRY_BICART_SUPPLY_VENT_MAX_TIME_MS ( 1 * MS_PER_SECOND ) ///< Max time to vent both dry bicart and Chamber F. #define DRY_BICART_SUPPLY_COMPLETE_TIME_MS ( 2 * MS_PER_SECOND ) ///< Wait time to close the D80 valve after D65 is closed +#define DRY_BICART_SUPPLY_DECAY_COMPLETE_PRESSURE_PSI 4.0F ///< Minimum decay pressure needed to end the supply process. // Dry Bicart Drain #define LARGE_DRY_BICART_MAX_DRAIN_TIME_MS ( 8 * SEC_PER_MIN * MS_PER_SECOND ) ///< Max drain time for large dry bicart in ms. @@ -163,6 +164,8 @@ static BICARB_CHAMBER_FILL_EXEC_STATE_T handleBicarbChamberPressureCheckState( void ); static BICARB_CHAMBER_FILL_EXEC_STATE_T handleBicarbChamberSupplyVentStartState(void); static BICARB_CHAMBER_FILL_EXEC_STATE_T handleBicarbChamberSupplyVentEndState(void); +static BOOL isDryBicartBalChamberFillWindowOpen( void ); +static void closeD65IfBalChamberSwitchImminent( void ); // Drain static DRY_BICART_DRAIN_EXEC_STATE_T handleDryBicartDrainStartState( void ); static DRY_BICART_DRAIN_EXEC_STATE_T handleDryBicartFluidDrainState( void ); @@ -550,6 +553,44 @@ /*********************************************************************//** * @brief + * The isDryBicartBalChamberFillWindowOpen function checks whether D65 may be + * opened for dry bicarb refill: fresh-side BC valves closed and BC switch not + * within the 100 ms valve-close window. + * @details \b Inputs: getBalChamberFreshSideValvesClosedStatus, isBalChamberSwitchImminent + * @details \b Outputs: none + * @return TRUE when the BC fresh-side fill window is open for D65. + *************************************************************************/ +static BOOL isDryBicartBalChamberFillWindowOpen( void ) +{ + BOOL result = FALSE; + + if ( ( TRUE == getBalChamberFreshSideValvesClosedStatus() ) && + ( FALSE == isBalChamberSwitchImminent() ) ) + { + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The closeD65IfBalChamberSwitchImminent function closes D65 when the balancing + * chamber is within 100 ms of switching. + * @details \b Inputs: isBalChamberSwitchImminent + * @details \b Outputs: valve states + * @return none + *************************************************************************/ +static void closeD65IfBalChamberSwitchImminent( void ) +{ + if ( TRUE == isBalChamberSwitchImminent() ) + { + setValveState( D65_VALV, VALVE_STATE_CLOSED ); + } +} + +/*********************************************************************//** + * @brief * The setBicartFillRequested function sets the bicart fill request * flag value to be True. * @details \b Inputs: bicarbChamberFillRequested, dryBiCartDrainRequested, @@ -1070,20 +1111,27 @@ *************************************************************************/ static BICARB_CHAMBER_FILL_EXEC_STATE_T handleBicarbChamberCartridgeFillWaterStartState( void ) { - BICARB_CHAMBER_FILL_EXEC_STATE_T state = BICARB_CARTRIDGE_FILL_WATER_END_STATE; + BICARB_CHAMBER_FILL_EXEC_STATE_T state = BICARB_CARTRIDGE_FILL_WATER_START_STATE; - // Close vent valves and descaling valve - setValveState( D80_VALV, VALVE_STATE_CLOSED ); - setValveState( D81_VALV, VALVE_STATE_CLOSED ); - setValveState( D85_VALV, VALVE_STATE_CLOSED ); +#ifdef __D65_OPENING_DISABLED__ + if ( TRUE == isDryBicartBalChamberFillWindowOpen() ) +#endif + { + // Close vent valves and descaling valve + setValveState( D80_VALV, VALVE_STATE_CLOSED ); + setValveState( D81_VALV, VALVE_STATE_CLOSED ); + setValveState( D85_VALV, VALVE_STATE_CLOSED ); - // open inlet water to bicart - setValveState( D65_VALV, VALVE_STATE_OPEN ); - setValveState( D64_VALV, VALVE_STATE_OPEN ); + // open inlet water to bicart only when fresh-side BC valves are closed + setValveState( D65_VALV, VALVE_STATE_OPEN ); + setValveState( D64_VALV, VALVE_STATE_OPEN ); - dryBiCarbSupplyStartTime = getMSTimerCount(); - dryBiCartPersistenceStartTime = 0; + dryBiCarbSupplyStartTime = getMSTimerCount(); + dryBiCartPersistenceStartTime = 0; + state = BICARB_CARTRIDGE_FILL_WATER_END_STATE; + } + return state; } @@ -1100,6 +1148,16 @@ F32 d66Pressure = getFilteredPressure( D66_PRES ); F32 fillCompletePressure = GET_FILL_COMPLETE_PRESSURE_PSI; +#ifdef __D65_OPENING_DISABLED__ + if ( FALSE == isDryBicartBalChamberFillWindowOpen() ) + { + setValveState( D65_VALV, VALVE_STATE_CLOSED ); + } + else if ( TRUE == isDryBicartBalChamberFillWindowOpen() ) + { + setValveState( D65_VALV, VALVE_STATE_OPEN ); + } +#endif // check D66 pressure greater than or equal to 17 PSI if ( d66Pressure >= fillCompletePressure ) { @@ -1166,6 +1224,10 @@ BICARB_CHAMBER_FILL_EXEC_STATE_T state = BICARB_CHAMBER_PRESSURE_CHECK_STATE; F32 d66Pressure = getFilteredPressure( D66_PRES ); LVL_STATE_T bicarbChamberLevel = getBicarbChamberLevelStatus(); +#ifdef __D65_OPENING_DISABLED__ + // Close D65 irrespective of pressure for balancing chamber fresh side fill to complete. + closeD65IfBalChamberSwitchImminent(); +#endif // Once upper level reached high , close the valve, timeout is for safety in case level sensor didn't work(10 sec), or else its a time based filling (3 sec) if ( ( LVL_STATE_HIGH == bicarbChamberLevel ) || @@ -1182,7 +1244,7 @@ // do not close the D80 valve, wait till d66 decays to 3 PSI if ( TRUE == didTimeout( dryBiCarbSupplyStartTime, DRY_BICART_SUPPLY_COMPLETE_TIME_MS ) ) { - if ( d66Pressure <= getDryBicartLowerCartPressure() ) + if ( d66Pressure <= DRY_BICART_SUPPLY_DECAY_COMPLETE_PRESSURE_PSI ) { setValveState( D80_VALV, VALVE_STATE_CLOSED ); setValveState( D85_VALV, VALVE_STATE_OPEN ); @@ -1201,8 +1263,14 @@ { drybicartPersistenceOnLowercartPressureStartTime = getMSTimerCount(); } + +#ifdef __D65_OPENING_DISABLED__ // 200 ms persistence on D66 pressure + if ( ( TRUE == didTimeout( drybicartPersistenceOnLowercartPressureStartTime, DRY_BICART_PERSISTENCE_DURATION_MS ) ) && + ( TRUE == isDryBicartBalChamberFillWindowOpen() ) ) +#else if ( TRUE == didTimeout( drybicartPersistenceOnLowercartPressureStartTime, DRY_BICART_PERSISTENCE_DURATION_MS ) ) +#endif { setValveState( D65_VALV, VALVE_STATE_OPEN ); drybicartPersistenceOnLowercartPressureStartTime = 0; @@ -1618,7 +1686,7 @@ * @details \b Outputs: dryBiCartDataPublishInterval * @param Override message from Dialin which includes the interval * (in ms) to override the DD dry bicart data publish interval to. - * @return TRUE if override successful, FALSE if not + * @return TRUE if override successful, FALSE if not. *************************************************************************/ BOOL testDryBiCartDataPublishIntervalOverride( MESSAGE_T *message ) { Index: firmware/App/DDCommon.h =================================================================== diff -u -r4c603a22956757874a432a7f388193f567a32ea3 -r081b2525e3a650671d770513eb841057d88ea505 --- firmware/App/DDCommon.h (.../DDCommon.h) (revision 4c603a22956757874a432a7f388193f567a32ea3) +++ firmware/App/DDCommon.h (.../DDCommon.h) (revision 081b2525e3a650671d770513eb841057d88ea505) @@ -66,7 +66,10 @@ //Uncomment below to disable the conductivity sensor alarms #define __CONDUCTIVITY_SENSOR_ALARMS_DISABLED__ 1 +//Uncommnet below to enable the D65 valves opening during balancincg chamber fill +//#define __D65_OPENING_DISABLED__ 1 + #include #include #endif