Index: firmware/App/Controllers/BalancingChamber.c =================================================================== diff -u -r0bcac6885c8461b05da276fd245b580b7339ddfd -rb9fbba187be3070c9d3bd4b74eb7ccf884d6f14e --- firmware/App/Controllers/BalancingChamber.c (.../BalancingChamber.c) (revision 0bcac6885c8461b05da276fd245b580b7339ddfd) +++ firmware/App/Controllers/BalancingChamber.c (.../BalancingChamber.c) (revision b9fbba187be3070c9d3bd4b74eb7ccf884d6f14e) @@ -7,8 +7,8 @@ * * @file BalancingChamber.c * -* @author (last) Vinayakam Mani -* @date (last) 01-Jun-2026 +* @author (last) Sameer Kalliadan Poyil +* @date (last) 24-Jun-2026 * * @author (original) Vinayakam Mani * @date (original) 28-Jan-2025 @@ -23,6 +23,7 @@ #include "FpgaDD.h" #include "Heaters.h" #include "Level.h" +#include "MixingControl.h" #include "ModeGenDialysate.h" #include "ModeStandby.h" #include "Messaging.h" @@ -59,6 +60,8 @@ #define BICARB_CHAMBER_PERIODIC_FILL_TIME ( 1 * SEC_PER_MIN * \ ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ) ///< Periodic bicarb chamber fill request 60 sec x 20 = 1200 #define BAL_CHAMBER_FILL_TIMEOUT_FACTOR 3.0F ///< Balancing Chamber fill timeout factor (300% of observed fill count) +#define COMP_SLOPE -0.000376F ///< Balancing chamber temperature compensation slope factor +#define COMP_INTERCEPT 1.007269F ///< Balancing chamber temperature compensation intercept factor /// Payload record structure for balancing chamber switch only request typedef struct @@ -105,6 +108,7 @@ static F32 pendingTdDialysateFlowrate; ///< Pending TD dialysate flow rate; applied at FillEnd after a BC switch completes. static BOOL isBalChamberSwitchingPeriodUpdatePending; ///< BC switching period update pending apply at fill end. static U32 bcSwitchingBasedOnClosedPeriodCounter; ///< Valve-close segments remaining before first-cycle relaxations clear after Qd timing apply. +static F32 balancingError; ///< Balancing error that has been calculated during balancing chamber switching. //TODO: remove later once level sensor working static U32 bicarbChamberPeriodicFillCounter; @@ -126,6 +130,7 @@ static void applyBalChamberSwitchingPeriod( F32 tdDialysateFlowrate ); static BOOL isBalChamberTimeBasedSwitching( void ); static void scheduleFirstCycleRelaxAfterQdApply( void ); +static void calculateBalancingChamberError( void ); /*********************************************************************//** * @brief @@ -184,6 +189,7 @@ pendingTdDialysateFlowrate = 0.0F; isBalChamberSwitchingPeriodUpdatePending = FALSE; bcSwitchingBasedOnClosedPeriodCounter = 0; + balancingError = 0.0F; //TODO:remove once level sensor working bicarbChamberPeriodicFillCounter = 0; } @@ -240,6 +246,34 @@ /*********************************************************************//** * @brief + * The getBicarbDoseVol function gets the bicarb dose volume + * @details \b Inputs: bicarbDoseVolume + * @details \b Outputs: none + * @return TRUE if successful, FALSE if not. + *************************************************************************/ +F32 getBicarbDoseVol( void ) +{ + F32 result = getF32OverrideValue( &bicarbDoseVolume ); + + return result; +} + +/*********************************************************************//** + * @brief + * The getAcidDoseVol function gets acid mix volume + * @details \b Inputs: acidDoseVolume + * @details \b Outputs: none + * @return TRUE if successful, FALSE if not. + *************************************************************************/ +F32 getAcidDoseVol( void ) +{ + F32 result = getF32OverrideValue( &acidDoseVolume ); + + return result; +} + +/*********************************************************************//** + * @brief * The applyBalChamberSwitchingPeriod function applies the active balancing * chamber switching time based on the provided dialysis flow rate. * @details \b Inputs: Dialysis flow rate. @@ -341,7 +375,7 @@ currentBalChamberSwitchingCounter += 1; currentBalChamberFillCounter += 1; - if ( ( getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DRY_BICARB ) == TRUE ) && ( balChamberExecState > BAL_CHAMBER_STATE_IDLE ) ) + if ( ( FALSE == getTestConfigStatus( TEST_CONFIG_DD_DISABLE_DRY_BICARB ) ) && ( balChamberExecState > BAL_CHAMBER_STATE_IDLE ) ) { #ifdef CONDUCTIVE_LEVEL_SENSOR_ENABLED if ( LVL_STATE_LOW == bicarbChamberLevel ) @@ -617,7 +651,7 @@ spentFillRiseMissCounter = 0; isSpentFillComplete = FALSE; - if ( getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DRY_BICARB ) == TRUE ) + if ( FALSE == getTestConfigStatus( TEST_CONFIG_DD_DISABLE_DRY_BICARB ) ) { bicarbVolume = getBicarbMixVol(); acidVolume = getAcidMixVol(); @@ -763,7 +797,7 @@ } // If the dry bicarbonate is enabled then we ignore looking at d18 pressure to be in range. - if ( ( TRUE == getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DRY_BICARB ) ) && ( TRUE == getBicarbChamberFillRequested() ) ) + if ( ( FALSE == getTestConfigStatus( TEST_CONFIG_DD_DISABLE_DRY_BICARB ) ) && ( TRUE == getBicarbChamberFillRequested() ) ) { isPressureStabilizedDuringFill = TRUE; } @@ -935,7 +969,7 @@ spentFillRiseMissCounter = 0; isSpentFillComplete = FALSE; - if ( getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DRY_BICARB ) == TRUE ) + if ( FALSE == getTestConfigStatus( TEST_CONFIG_DD_DISABLE_DRY_BICARB ) ) { bicarbVolume = getBicarbMixVol(); acidVolume = getAcidMixVol(); @@ -1015,7 +1049,7 @@ spentDialPressure = getFilteredPressure( D51_PRES ); // If the dry bicarbonate is enabled then we ignore looking at d18 pressure to be in range. - if ( ( TRUE == getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DRY_BICARB ) ) && ( TRUE == getBicarbChamberFillRequested() ) ) + if ( ( FALSE == getTestConfigStatus( TEST_CONFIG_DD_DISABLE_DRY_BICARB ) ) && ( TRUE == getBicarbChamberFillRequested() ) ) { isPressureStabilizedDuringFill = TRUE; } @@ -1524,6 +1558,50 @@ /*********************************************************************//** * @brief + * The calculateBalancingChamberError function calculates the balancing error + * based on the fresh and spent dialysate temperature differences. + * @details \b Inputs: D4 and D50 temperature + * @details \b Outputs: balancing error + * @return balancing error the balancing error that impacts ultrafilteration. + *************************************************************************/ +static void calculateBalancingChamberError( void ) +{ + F32 freshDensity = 0.0F; + F32 spentDensity = 0.0F; + F32 compFreshFlowrate = 0.0F; + F32 compSpentFlowrate = 0.0F; + + // Fresh side dialysate density + if ( getTestConfigStatus( TEST_CONFIG_DD_FP_ENABLE_BETA_1_0_HW ) == TRUE ) + { + freshDensity = ( COMP_SLOPE * getFilteredTemperatureValue( D4_TEMP ) ) + COMP_INTERCEPT; + } + else + { + freshDensity = ( COMP_SLOPE * getFilteredTemperatureValue( D99_TEMP ) ) + COMP_INTERCEPT; + } + + spentDensity = ( COMP_SLOPE * getFilteredTemperatureValue( D50_TEMP ) ) + COMP_INTERCEPT; // spent side dialysate density + compFreshFlowrate = getTDDialysateFlowrate() * freshDensity; // Qd * fresh density + compSpentFlowrate = getTDDialysateFlowrate() * spentDensity; // Qd * spent density + balancingError = compFreshFlowrate - compSpentFlowrate; // Error in g/min +} + +/*********************************************************************//** + * @brief + * The getBalancingChamberError function gets the calculated balancing chamber + * error that may be used for adjusting the ultrafiltration rate. + * @details \b Inputs: balancingError + * @details \b Outputs: none + * @return balancing chamber error + *************************************************************************/ +F32 getBalancingChamberError( void ) +{ + return balancingError; +} + +/*********************************************************************//** + * @brief * The publishBalChamberData function broadcasts the balancing chamber * execution data at defined interval. * @details \b Inputs: balChamberDataPublicationTimerCounter