Index: firmware/App/Controllers/BalancingChamber.c =================================================================== diff -u -rb96f1964c061605200af748e1b4a5c2785c7985d -rac5e52d907ff6adad795d8f81ca8206c5cd33c77 --- firmware/App/Controllers/BalancingChamber.c (.../BalancingChamber.c) (revision b96f1964c061605200af748e1b4a5c2785c7985d) +++ firmware/App/Controllers/BalancingChamber.c (.../BalancingChamber.c) (revision ac5e52d907ff6adad795d8f81ca8206c5cd33c77) @@ -7,8 +7,8 @@ * * @file BalancingChamber.c * -* @author (last) Varshini Nagabooshanam -* @date (last) 26-Jan-2026 +* @author (last) Jashwant Gantyada +* @date (last) 05-Mar-2026 * * @author (original) Vinayakam Mani * @date (original) 28-Jan-2025 Index: firmware/App/Controllers/BalancingChamber.h =================================================================== diff -u -r830213bc6dcc1a684610caf78c79d55f2cb41e93 -rac5e52d907ff6adad795d8f81ca8206c5cd33c77 --- firmware/App/Controllers/BalancingChamber.h (.../BalancingChamber.h) (revision 830213bc6dcc1a684610caf78c79d55f2cb41e93) +++ firmware/App/Controllers/BalancingChamber.h (.../BalancingChamber.h) (revision ac5e52d907ff6adad795d8f81ca8206c5cd33c77) @@ -7,8 +7,8 @@ * * @file BalancingChamber.h * -* @author (last) Vinayakam Mani -* @date (last) 03-Oct-2025 +* @author (last) Jashwant Gantyada +* @date (last) 05-Mar-2026 * * @author (original) Vinayakam Mani * @date (original) 28-Jan-2025 Index: firmware/App/Controllers/DialysatePumps.c =================================================================== diff -u -r8e93a6e39b2c7af5f0b47ef1272a2b53446fab0b -rac5e52d907ff6adad795d8f81ca8206c5cd33c77 --- firmware/App/Controllers/DialysatePumps.c (.../DialysatePumps.c) (revision 8e93a6e39b2c7af5f0b47ef1272a2b53446fab0b) +++ firmware/App/Controllers/DialysatePumps.c (.../DialysatePumps.c) (revision ac5e52d907ff6adad795d8f81ca8206c5cd33c77) @@ -30,6 +30,7 @@ #include "SafetyShutdown.h" #include "TaskGeneral.h" #include "TaskPriority.h" +#include "TestSupport.h" #include "Timers.h" #include "Utilities.h" @@ -73,6 +74,7 @@ #define D12_PUMP_I_COEFFICIENT 60.0F ///< I term for fresh dialysate pump delta pressure control. #define D48_PUMP_P_COEFFICIENT 20.0F ///< P term for spent dialysate pump delta pressure control. #define D48_PUMP_I_COEFFICIENT 60.0F ///< I term for spent dialysate pump delta pressure control. +#define D48_PUMP_CLOSED_LOOP_DEADBAND_RPM 50.0F ///< Deadband on PI output so pump speed does not fluctuate frequently. #define DIAL_PUMP_NO_FEED_FORWARD 0.0F ///< Feedforward term for dialysate pump control #define DEGAS_PUMP_SLOPE_FACTOR -0.0156F ///< Dialysate pump target pressure multiply factor ( m factor in 'y = mx + b' equation) #define DEGAS_PUMP_INTERCEPT_FACTOR 0.1153F ///< Dialysate pump target pressure addition factor ( b factor in 'y = mx + b' equation) @@ -156,6 +158,46 @@ /*********************************************************************//** * @brief + * The getD48MinPumpRPM function returns the minimum RPM limit for the D48 pump + * based on test configuration (Diener 1000 vs Diener 2000). + * @details \b Inputs: Test configuration TEST_CONFIG_DD_ENABLE_DIENER_1000_PUMP. + * @details \b Outputs: none + * @return Minimum RPM for D48 pump (134 when Diener 1000 enabled, 200 otherwise). + *************************************************************************/ +U32 getD48MinPumpRPM( void ) +{ + U32 minRpm = MIN_DIALYSATE_PUMP_RPM; + + if ( TRUE == getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DIENER_1000_PUMP ) ) + { + minRpm = D48_DIENER_1000_MIN_RPM; + } + + return minRpm; +} + +/*********************************************************************//** + * @brief + * The getD48MaxPumpRPM function returns the maximum RPM limit for the D48 pump + * based on test configuration (Diener 1000 vs Diener 2000). + * @details \b Inputs: Test configuration TEST_CONFIG_DD_ENABLE_DIENER_1000_PUMP. + * @details \b Outputs: none + * @return Maximum RPM for D48 pump (2770 when Diener 1000 enabled, 2650 otherwise). + *************************************************************************/ +U32 getD48MaxPumpRPM( void ) +{ + U32 maxRpm = MAX_DIALYSATE_PUMP_RPM; + + if ( TRUE == getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DIENER_1000_PUMP ) ) + { + maxRpm = D48_DIENER_1000_MAX_RPM; + } + + return maxRpm; +} + +/*********************************************************************//** + * @brief * The initDialysatePump function initializes the DialysatePumps unit. * @details \b Inputs: none * @details \b Outputs: Dialysate pump unit variables initialized. @@ -192,7 +234,14 @@ dialysatePumpMeasuredCurrentA[ pumpId ].ovInitData = 0.0F; dialysatePumpMeasuredCurrentA[ pumpId ].ovData = 0.0F; dialysatePumpMeasuredCurrentA[ pumpId ].override = OVERRIDE_RESET; - dialysatePumps[ pumpId ].currentPumpSpeed = MIN_DIALYSATE_PUMP_RPM; + if ( D48_PUMP == pumpId ) + { + dialysatePumps[ pumpId ].currentPumpSpeed = getD48MinPumpRPM(); + } + else + { + dialysatePumps[ pumpId ].currentPumpSpeed = MIN_DIALYSATE_PUMP_RPM; + } dialysatePumps[ pumpId ].prevPumpTargetSpeed = 0.0F; dialysatePumps[ pumpId ].control = DIALYSATE_PUMP_CONTROL_STOP; dialysatePumps[ pumpId ].directionErrorCount = 0; @@ -221,14 +270,14 @@ initializePIController( PI_CONTROLLER_ID_D12_PUMP, FRESH_DIAL_OPEN_LOOP_SPEED_RPM, D12_PUMP_P_COEFFICIENT, D12_PUMP_I_COEFFICIENT, MIN_DIALYSATE_PUMP_RPM, MAX_DIALYSATE_PUMP_RPM, FALSE, DIAL_PUMP_NO_FEED_FORWARD ); - // Initialize spent dialysate pump PI controller + // Initialize spent dialysate pump PI controller (use Diener 1000 range to support both pump types) initializePIController( PI_CONTROLLER_ID_D48_PUMP, SPENT_DIAL_OPEN_LOOP_SPEED_RPM, D48_PUMP_P_COEFFICIENT, D48_PUMP_I_COEFFICIENT, - MIN_DIALYSATE_PUMP_RPM, MAX_DIALYSATE_PUMP_RPM,FALSE, DIAL_PUMP_NO_FEED_FORWARD ); + D48_DIENER_1000_MIN_RPM, D48_DIENER_1000_MAX_RPM, FALSE, DIAL_PUMP_NO_FEED_FORWARD ); // Init the dialysate pump with valid PWM while motor is disabled. // when enable triggers, we dont want invlid RPM set that triggers alarm in motor controller. setFPGAD12PumpSpeed( MIN_DIALYSATE_PUMP_RPM ); - setFPGAD48PumpSpeed( MIN_DIALYSATE_PUMP_RPM ); + setFPGAD48PumpSpeed( getD48MinPumpRPM() ); #ifdef __PITEST__ for ( i = 0; i < NUM_OF_CONTROLLER_SIGNAL; i++ ) @@ -287,37 +336,50 @@ BOOL setDialysatePumpTargetRPM( DIALYSATE_PUMPS_T pumpId, U32 rpm, BOOL isOpenLoopControlEnabled ) { BOOL result = FALSE; + U32 minRPM; + U32 maxRPM; + if ( D48_PUMP == pumpId ) + { + minRPM = getD48MinPumpRPM(); + maxRPM = getD48MaxPumpRPM(); + } + else + { + minRPM = MIN_DIALYSATE_PUMP_RPM; + maxRPM = MAX_DIALYSATE_PUMP_RPM; + } + if ( pumpId < NUM_OF_DIALYSATE_PUMPS ) { - if ( ( MIN_DIALYSATE_PUMP_RPM <= rpm ) && ( rpm <= MAX_DIALYSATE_PUMP_RPM ) ) + if ( ( minRPM <= rpm ) && ( rpm <= maxRPM ) ) { pumpTargetSpeed[ pumpId ].data = rpm; } - else if ( rpm < MIN_DIALYSATE_PUMP_RPM ) + else if ( rpm < minRPM ) { - // Lets assign minimum speed to make sure, driver is not getting into fault mode - pumpTargetSpeed[ pumpId ].data = MIN_DIALYSATE_PUMP_RPM; + // Assign minimum speed so driver does not enter fault mode. + pumpTargetSpeed[ pumpId ].data = minRPM; } else { - pumpTargetSpeed[ pumpId ].data = MAX_DIALYSATE_PUMP_RPM; + pumpTargetSpeed[ pumpId ].data = maxRPM; } // Assign Open loop or close loop control isDialPumpOpenLoopEnabled[ pumpId ] = isOpenLoopControlEnabled; #ifdef __BARO_PRES_SENSOR__ - //Update Degas pump target speed + // Update degas pump target speed. calculateDegasPumpTargetPressure(); #endif - //handle target speed update when pump is running + // Handle target speed update when pump is running. if ( DIALYSATE_PUMP_CONTROL_TO_TARGET_STATE == dialysatePumps[ pumpId ].dialysatePumpState ) { F32 diffSpeed = fabs( getDialysatePumpTargetSpeed( pumpId ) - dialysatePumps[ pumpId ].prevPumpTargetSpeed ); if ( diffSpeed > PUMP_TRANS_TO_RAMP_SPEED_THRESHOLD ) { - // change to ramp state + // Change to ramp state. dialysatePumps[ pumpId ].dialysatePumpState = DIALYSATE_PUMP_RAMP_UP_STATE; } } @@ -344,10 +406,9 @@ *************************************************************************/ void signalDialysatePumpHardStop( DIALYSATE_PUMPS_T pumpId ) { - //Update control to stop the dialysate pump + // Update control to stop the dialysate pump. if ( D12_PUMP == pumpId ) { - // dialysate pump control run enable dialysatePumps[ pumpId ].control = DIALYSATE_PUMP_CONTROL_STOP; setFPGAD12PumpControl( dialysatePumps[ pumpId ].control ); setFPGAD12PumpSpeed( MIN_DIALYSATE_PUMP_RPM ); @@ -356,18 +417,25 @@ { dialysatePumps[ pumpId ].control = DIALYSATE_PUMP_CONTROL_STOP; setFPGAD48PumpControl( dialysatePumps[ pumpId ].control ); - setFPGAD48PumpSpeed( MIN_DIALYSATE_PUMP_RPM ); + setFPGAD48PumpSpeed( getD48MinPumpRPM() ); } - // Reset all the variables to stop mode - dialysatePumps[ pumpId ].currentPumpSpeed = MIN_DIALYSATE_PUMP_RPM; + // Reset all the variables to stop mode. + if ( D48_PUMP == pumpId ) + { + dialysatePumps[ pumpId ].currentPumpSpeed = getD48MinPumpRPM(); + } + else + { + dialysatePumps[ pumpId ].currentPumpSpeed = MIN_DIALYSATE_PUMP_RPM; + } pumpTargetSpeed[ pumpId ].data = 0.0F; dialysatePumps[ pumpId ].dialysatePumpState = DIALYSATE_PUMP_OFF_STATE; dialysatePumps[ pumpId ].controlTimerCounter = 0; dialysatePumps[ pumpId ].isDialPumpOn = FALSE; isDialPumpOpenLoopEnabled[ pumpId ] = FALSE; - //Reset PI Controller + // Reset PI controller. if ( D12_PUMP == pumpId ) { resetPIController( PI_CONTROLLER_ID_D12_PUMP, FRESH_DIAL_OPEN_LOOP_SPEED_RPM, DIAL_PUMP_NO_FEED_FORWARD ); @@ -660,12 +728,22 @@ { DIALYSATE_PUMP_STATE_T result = DIALYSATE_PUMP_OFF_STATE; F32 targetSpeed = getDialysatePumpTargetSpeed( pumpId ); + U32 minRPM; - if ( targetSpeed >= MIN_DIALYSATE_PUMP_RPM ) + if ( D48_PUMP == pumpId ) { + minRPM = getD48MinPumpRPM(); + } + else + { + minRPM = MIN_DIALYSATE_PUMP_RPM; + } + + if ( targetSpeed >= minRPM ) + { if ( D12_PUMP == pumpId ) { - // dialysate pump control run enable, forward run only. + // Dialysate pump control run enable, forward run only. dialysatePumps[ pumpId ].control = DIALYSATE_PUMP_CONTROL_RUN; setFPGAD12PumpControl( dialysatePumps[ pumpId ].control ); } @@ -729,6 +807,7 @@ F32 speedIncrease = 0.0F; BOOL hasTgtBeenReached = FALSE; F32 currentToTargetDiff = fabs( getDialysatePumpTargetSpeed( pumpId ) - dialysatePumps[ pumpId ].currentPumpSpeed ); + U32 minRPM; if ( currentToTargetDiff > ZERO_SPEED ) { @@ -742,7 +821,7 @@ hasTgtBeenReached = TRUE; } - // Subtract current speed when target speed is smaller + // Subtract current speed when target speed is smaller. if ( getDialysatePumpTargetSpeed( pumpId ) < dialysatePumps[ pumpId ].currentPumpSpeed ) { speedIncrease *= -1.0F; @@ -757,16 +836,25 @@ // } } - if ( dialysatePumps[ pumpId ].currentPumpSpeed >= MIN_DIALYSATE_PUMP_RPM ) + if ( D48_PUMP == pumpId ) { + minRPM = getD48MinPumpRPM(); + } + else + { + minRPM = MIN_DIALYSATE_PUMP_RPM; + } + + if ( dialysatePumps[ pumpId ].currentPumpSpeed >= minRPM ) + { if ( D12_PUMP == pumpId ) { - // Set fresh dialyate pump speed + // Set fresh dialysate pump speed. setFPGAD12PumpSpeed( (U16)dialysatePumps[ pumpId ].currentPumpSpeed ); } else { - // Set spent dialyate pump speed + // Set spent dialysate pump speed. setFPGAD48PumpSpeed( (U16)dialysatePumps[ pumpId ].currentPumpSpeed ); } } @@ -1178,15 +1266,29 @@ if ( (DIALYSATE_PUMPS_T)payload.pumpID < NUM_OF_DIALYSATE_PUMPS ) { - // Handle start command + U32 minRPM; + U32 maxRPM; + + if ( D48_PUMP == (DIALYSATE_PUMPS_T)payload.pumpID ) + { + minRPM = getD48MinPumpRPM(); + maxRPM = getD48MaxPumpRPM(); + } + else + { + minRPM = MIN_DIALYSATE_PUMP_RPM; + maxRPM = MAX_DIALYSATE_PUMP_RPM; + } + + // Handle start command. if ( ( TRUE == payload.startStop ) && - ( ( payload.rpm >= MIN_DIALYSATE_PUMP_RPM ) && ( payload.rpm <= MAX_DIALYSATE_PUMP_RPM ) ) ) + ( ( payload.rpm >= minRPM ) && ( payload.rpm <= maxRPM ) ) ) { setDialysatePumpTargetRPM( (DIALYSATE_PUMPS_T)payload.pumpID, payload.rpm, (BOOL)payload.pumpControl ); result = TRUE; } - //Handle stop command + // Handle stop command. if ( FALSE == payload.startStop ) { signalDialysatePumpHardStop( (DIALYSATE_PUMPS_T)payload.pumpID ); Index: firmware/App/Controllers/DialysatePumps.h =================================================================== diff -u -r3bafab778c613a1abd0c421128320408db407ef8 -rac5e52d907ff6adad795d8f81ca8206c5cd33c77 --- firmware/App/Controllers/DialysatePumps.h (.../DialysatePumps.h) (revision 3bafab778c613a1abd0c421128320408db407ef8) +++ firmware/App/Controllers/DialysatePumps.h (.../DialysatePumps.h) (revision ac5e52d907ff6adad795d8f81ca8206c5cd33c77) @@ -32,20 +32,11 @@ // ********** public definitions ********** -#define MIN_DIALYSATE_PUMP_RPM 200 ///< Minimum RPM target for dialysate pump (though zero is allowed if turning pump off). -#define MAX_DIALYSATE_PUMP_RPM 2650 ///< Maximum RPM target for dialysate pump. +#define MIN_DIALYSATE_PUMP_RPM 200 ///< Minimum RPM target for D12 pump and D48 Diener 2000 pump. +#define MAX_DIALYSATE_PUMP_RPM 2650 ///< Maximum RPM target for D12 pump and D48 Diener 2000 pump. -#ifdef __NEW_D48_PUMP__ - -#define MIN_DIALYSATE_PUMP_RPM 200 ///< Minimum RPM target for dialysate pump (though zero is allowed if turning pump off). -#define MAX_DIALYSATE_PUMP_RPM 1300 ///< Maximum RPM target for dialysate pump. - -#else - -#define MIN_DIALYSATE_PUMP_RPM 200 ///< Minimum RPM target for dialysate pump (though zero is allowed if turning pump off). -#define MAX_DIALYSATE_PUMP_RPM 2650 ///< Maximum RPM target for dialysate pump. - -#endif +#define D48_DIENER_1000_MIN_RPM 134 ///< Minimum RPM for D48 Diener 1000 pump (test config enabled). +#define D48_DIENER_1000_MAX_RPM 2770 ///< Maximum RPM for D48 Diener 1000 pump (test config enabled). #define DEGAS_PUMP_TARGET_PRES_ADJ_THRESHOLD -1.0F ///< Dialysate Pump(D12) target pressure threshold adjustment factor. #define MIN_DIALYSATE_FLOW_RATE ( 100.0F ) ///< Minimum dialysate flow rate @@ -92,6 +83,8 @@ void execDialysatePumpController( void ); SELF_TEST_STATUS_T execDialysatePumpSelfTest( void ); +U32 getD48MinPumpRPM( void ); +U32 getD48MaxPumpRPM( void ); F32 getDialysatePumpTargetSpeed( DIALYSATE_PUMPS_T pumpId ); F32 getDialysatePumpMeasuredSpeed( DIALYSATE_PUMPS_T pumpId ); F32 getDialysatePumpTargetPressure( DIALYSATE_PUMPS_T pumpId ); Index: firmware/App/Modes/ModeGenDialysate.c =================================================================== diff -u -rb96f1964c061605200af748e1b4a5c2785c7985d -rac5e52d907ff6adad795d8f81ca8206c5cd33c77 --- firmware/App/Modes/ModeGenDialysate.c (.../ModeGenDialysate.c) (revision b96f1964c061605200af748e1b4a5c2785c7985d) +++ firmware/App/Modes/ModeGenDialysate.c (.../ModeGenDialysate.c) (revision ac5e52d907ff6adad795d8f81ca8206c5cd33c77) @@ -33,6 +33,7 @@ #include "TaskGeneral.h" #include "TDInterface.h" #include "Temperature.h" +#include "TestSupport.h" #include "Timers.h" #include "Ultrafiltration.h" #include "Valves.h" @@ -63,8 +64,10 @@ #define ZERO_DIAL_FLOW_RATE 0.0F ///< Zero dialysate flow rate #define SPENT_CHAMBER_FILL_MAX_COUNT 10 ///< Total number of spent chamber fill allowed. #define BICARB_CHAMBER_FILL_TIMEOUT ( 1 * MS_PER_SECOND ) ///< Bicarb chamber fill timeout. -#define PUMP_SPEED_SLOPE_FACTOR 1.24F ///< D48 pump speed (calculation based on Qd) slope factor. -#define PUMP_SPEED_INTERCEPT_FACTOR 30.0F ///< D48 pump speed (calculation based on Qd) intercept factor. +#define PUMP_SPEED_SLOPE_FACTOR_DIENER_2000 1.24F ///< D48 Diener 2000 pump speed slope (y = 1.24x + 30). +#define PUMP_SPEED_INTERCEPT_FACTOR_DIENER_2000 30.0F ///< D48 Diener 2000 pump speed intercept. +#define PUMP_SPEED_SLOPE_FACTOR_DIENER_1000 2.869F ///< D48 Diener 1000 pump speed slope (y = 2.869x + 25.956). +#define PUMP_SPEED_INTERCEPT_FACTOR_DIENER_1000 25.956F ///< D48 Diener 1000 pump speed intercept. //Testing #define DELAY_BC_SWITCHING_AT_START_UP ( 10 * MS_PER_SECOND ) ///< Provide a balancing chamber switching start up delay to stabilize pump speed etc., /// Payload record structure for Gen dialysate execution state set request @@ -140,7 +143,7 @@ bicarbFillStartTimeMS = 0; pendingSpentChamberFill = FALSE; pendingBicarbChamberFill = FALSE; - d48PumpSpeed = MIN_DIALYSATE_PUMP_RPM; + d48PumpSpeed = getD48MinPumpRPM(); //Testing bypassStateDelayStartTimeMS = 0; delayBypassStateFlag = TRUE; @@ -585,16 +588,30 @@ /*********************************************************************//** * @brief - * The calculateD48PumpSpeedForBCFill function calculates the pump speed based on the - * dialysate flow rate for continuous delivery of dialysate. - * @details \b Inputs: Qd. + * The getCalculatedD48PumpSpeedForBCFill function returns the D48 pump speed + * calculated from dialysate flow rate (Qd) for continuous delivery. + * @details \b Inputs: Qd from TD, test config TEST_CONFIG_DD_ENABLE_DIENER_1000_PUMP. * @details \b Outputs: none - * @return calculated D48 pump speed. + * @return Calculated D48 pump speed in RPM (Diener 1000 or 2000 formula per test config). *************************************************************************/ U32 getCalculatedD48PumpSpeedForBCFill( void ) { F32 dialFlowrate = getTDDialysateFlowrate(); - return (U32)( ( PUMP_SPEED_SLOPE_FACTOR * dialFlowrate ) + PUMP_SPEED_INTERCEPT_FACTOR ); + F32 slope; + F32 intercept; + + if ( TRUE == getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DIENER_1000_PUMP ) ) + { + slope = PUMP_SPEED_SLOPE_FACTOR_DIENER_1000; + intercept = PUMP_SPEED_INTERCEPT_FACTOR_DIENER_1000; + } + else + { + slope = PUMP_SPEED_SLOPE_FACTOR_DIENER_2000; + intercept = PUMP_SPEED_INTERCEPT_FACTOR_DIENER_2000; + } + + return (U32)( ( slope * dialFlowrate ) + intercept ); } /*********************************************************************//**