Index: firmware/App/Controllers/BalancingChamber.c =================================================================== diff -u -r145fd716a856f864f39fb0f9884865f6e45b9256 -r95eefab5b2337c7290e5add17dbb9031de4f7f37 --- firmware/App/Controllers/BalancingChamber.c (.../BalancingChamber.c) (revision 145fd716a856f864f39fb0f9884865f6e45b9256) +++ firmware/App/Controllers/BalancingChamber.c (.../BalancingChamber.c) (revision 95eefab5b2337c7290e5add17dbb9031de4f7f37) @@ -96,6 +96,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). @@ -127,6 +128,9 @@ 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 ); /*********************************************************************//** * @brief @@ -179,6 +183,7 @@ spentFillRiseHitCount = 0; spentFillRiseMissCounter = 0; isSpentFillComplete = FALSE; + isFreshSideValvesClosed = FALSE; isBalChamberSwitchingActive = FALSE; isBalChamberSwitchingOnRequested = FALSE; isBalChamberSwitchingOffRequested = FALSE; @@ -283,6 +288,7 @@ spentFillRiseHitCount = 0; spentFillRiseMissCounter = 0; isSpentFillComplete = FALSE; + isFreshSideValvesClosed = FALSE; spentDialPressure = getFilteredPressure( D51_PRES ); lastPrevSpentDialPressure = spentDialPressure; prevSpentDialPressure = spentDialPressure; @@ -592,6 +598,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( D22_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( D20_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 @@ -617,6 +676,7 @@ spentFillRiseHitCount = 0; spentFillRiseMissCounter = 0; isSpentFillComplete = FALSE; + isFreshSideValvesClosed = FALSE; if ( FALSE == getTestConfigStatus( TEST_CONFIG_DD_DISABLE_DRY_BICARB ) ) { @@ -747,7 +807,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; @@ -778,16 +837,17 @@ } } + closeFreshSideValvesWhenFillComplete(); + 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 ) || @@ -935,6 +995,7 @@ spentFillRiseHitCount = 0; spentFillRiseMissCounter = 0; isSpentFillComplete = FALSE; + isFreshSideValvesClosed = FALSE; if ( FALSE == getTestConfigStatus( TEST_CONFIG_DD_DISABLE_DRY_BICARB ) ) { @@ -1008,7 +1069,6 @@ 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; @@ -1039,26 +1099,17 @@ 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; - } - } + closeFreshSideValvesWhenFillComplete(); 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 ) || @@ -1431,6 +1482,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 >= balChamberValveClosePeriod ) ) + { + 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 -r145fd716a856f864f39fb0f9884865f6e45b9256 -r95eefab5b2337c7290e5add17dbb9031de4f7f37 --- firmware/App/Controllers/DryBiCart.c (.../DryBiCart.c) (revision 145fd716a856f864f39fb0f9884865f6e45b9256) +++ firmware/App/Controllers/DryBiCart.c (.../DryBiCart.c) (revision 95eefab5b2337c7290e5add17dbb9031de4f7f37) @@ -159,6 +159,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 ); @@ -496,6 +498,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 50 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 50 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 @@ -964,20 +1004,25 @@ *************************************************************************/ 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 ); + if ( TRUE == isDryBicartBalChamberFillWindowOpen() ) + { + // 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; } @@ -994,6 +1039,20 @@ F32 d66Pressure = getFilteredPressure( D66_PRES ); F32 fillCompletePressure = GET_DRY_BICART_FILL_COMPLETE_PRESSURE_PSI; + closeD65IfBalChamberSwitchImminent(); + + if ( ( FALSE == isDryBicartBalChamberFillWindowOpen() ) && + ( d66Pressure < fillCompletePressure ) ) + { + setValveState( D65_VALV, VALVE_STATE_CLOSED ); + } + else if ( ( TRUE == isDryBicartBalChamberFillWindowOpen() ) && + ( d66Pressure < fillCompletePressure ) ) + { + setValveState( D65_VALV, VALVE_STATE_OPEN ); + setValveState( D64_VALV, VALVE_STATE_OPEN ); + } + // check D66 pressure greater than or equal to 17 PSI if ( d66Pressure >= fillCompletePressure ) { @@ -1065,6 +1124,8 @@ F32 d66Pressure = getFilteredPressure( D66_PRES ); LVL_STATE_T bicarbChamberLevel = getBicarbChamberLevelStatus(); + closeD65IfBalChamberSwitchImminent(); + // 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 ) || ( TRUE == didTimeout( dryBiCarbSupplyStartTime, DRY_BICART_SUPPLY_VALVE_D80_OPEN_TIME_MS ) ) ) @@ -1100,7 +1161,8 @@ drybicartPersistenceOnLowercartPressureStartTime = getMSTimerCount(); } // 200 ms persistence on D66 pressure - if ( TRUE == didTimeout( drybicartPersistenceOnLowercartPressureStartTime, DRY_BICART_PERSISTENCE_DURATION_MS ) ) + if ( ( TRUE == didTimeout( drybicartPersistenceOnLowercartPressureStartTime, DRY_BICART_PERSISTENCE_DURATION_MS ) ) && + ( TRUE == isDryBicartBalChamberFillWindowOpen() ) ) { setValveState( D65_VALV, VALVE_STATE_OPEN ); drybicartPersistenceOnLowercartPressureStartTime = 0;