Index: firmware/App/Controllers/BalancingChamber.c =================================================================== diff -u -r11ba042a2ccd2a86d727c5a53e66698b55aa870e -r1077fee46974061e6e0038b6c0ce0e1471715b61 --- firmware/App/Controllers/BalancingChamber.c (.../BalancingChamber.c) (revision 11ba042a2ccd2a86d727c5a53e66698b55aa870e) +++ firmware/App/Controllers/BalancingChamber.c (.../BalancingChamber.c) (revision 1077fee46974061e6e0038b6c0ce0e1471715b61) @@ -7,8 +7,8 @@ * * @file BalancingChamber.c * -* @author (last) Sameer Kalliadan Poyil -* @date (last) 22-Feb-2026 +* @author (last) Jashwant Gantyada +* @date (last) 13-Mar-2026 * * @author (original) Vinayakam Mani * @date (original) 28-Jan-2025 @@ -19,9 +19,9 @@ #include "Conductivity.h" #include "ConcentratePumps.h" #include "DialysatePumps.h" -#include "DryBiCart.h" #include "FpgaDD.h" #include "Heaters.h" +#include "ModeGenDialysate.h" #include "ModeStandby.h" #include "Messaging.h" #include "OperationModes.h" @@ -39,10 +39,19 @@ // ********** private definitions ********** -#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 corresponding valves opened. -#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 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_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. +#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_LOW_PSIG 3.5F ///< Spent fill complete pressure (PSI) when Diener 1000 and Qd <= 200. +#define SPENT_FILL_COMPLETE_PRES_QD_MID_PSIG 15.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 QD_THRESHOLD_LOW_MLPM 200.0F ///< Qd threshold (mL/min) below which low pressure limit applies. +#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) +#define BAL_CHAMBER_FILL_TIMEOUT_FACTOR 1.5 ///< Balancing Chamber fill timeout factor (150% of observed fill count) /// Payload record structure for balancing chamber switch only request typedef struct @@ -59,7 +68,7 @@ static U32 balChamberValveClosePeriod; ///< Close balancing chamber valves with the defined time prior switching state. static U32 currentBalChamberSwitchingCounter; ///< Counter (in task interval) to monitor the timing spent during balancing chamber fill/drain operation. static BOOL isBalChamberFillInProgress; ///< Flag indicating balancing chamber fill/drain is in progress. -static BOOL isPressureStalbilizedDuringFill; ///< Flag indicating that the pressure is stablized due to fill complete. +static BOOL isPressureStabilizedDuringFill; ///< Flag indicating that the pressure is stablized due to fill complete. static BAL_CHAMBER_SW_STATE_T balChamberSWState; ///< Current balancing chamber switching state ( state 1 or state 2). static U32 balChamberDataPublicationTimerCounter; ///< Used to schedule balancing chamber data publication to CAN bus. static U32 balChamberFillPressureDropCounter; ///< Counter to check balancing chamber valves opened and there by pressure drop is seen. @@ -73,10 +82,11 @@ static F32 lastTdDialysateFlowrate; ///< Previous TD dialysate flow rate static F32 freshDialPressure; ///< Fresh side dialysate pressure static F32 spentDialPressure; ///< Spent side dialysate pressure +static U32 currentBalChamberFillCounter; ///< Counter (in task interval) to monitor the timing spent for the spent side fill operation. +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. -//TODO: remove later once level sensor working -static U32 bicarbChamberPeriodicFillCounter; ///< Counter for checking the timeout for drybicart chamber fill request. - // ********** private function prototypes ********** static BAL_CHAMBER_EXEC_STATE_T handleBalChamberState1FillStart( void ); @@ -88,6 +98,7 @@ static BAL_CHAMBER_EXEC_STATE_T handleBalChamberState2FillEnd(void); static void publishBalChamberData( void ); static U32 getBalChamberDataPublishInterval( void ); +static void checkSpentFillComplete( F32 spentDialPressure ); /*********************************************************************//** * @brief @@ -130,11 +141,12 @@ isPressureDroppedDuringFill = FALSE; freshDialPressure = 0.0F; spentDialPressure = 0.0F; + currentBalChamberFillCounter = 0; + balChamberFillTimeoutCount = 0; + diffSpentFillCompleteCount = 0; + isSpentFillComplete = FALSE; +} - //TODO:remove once level sensor working - bicarbChamberPeriodicFillCounter = 0; - } - /*********************************************************************//** * @brief * The transitionToBalChamberFill function prepares for transition to @@ -175,6 +187,9 @@ //Update last td dialysate flow rate lastTdDialysateFlowrate = tdDialysateFlowrate; + // Update fill timeout count based on the switching period (e.g. 150% of period) + balChamberFillTimeoutCount = (U32)( (F32)balChamberSwitchingPeriod * BAL_CHAMBER_FILL_TIMEOUT_FACTOR ); + //Reset the BC switching flag for new Qd. isFirstCycleBCSwitchingCompleted = FALSE; @@ -199,24 +214,9 @@ { // Increment counter indicating fill is in progress. currentBalChamberSwitchingCounter += 1; + currentBalChamberFillCounter += 1; - if ( getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DRY_BICARB ) == TRUE ) - { - //Increment counter for dry bicarb chamber fill - bicarbChamberPeriodicFillCounter += 1; - // Fill bicarb chamber once every 60secs. - if ( bicarbChamberPeriodicFillCounter >= BICARB_CHAMBER_PERIODIC_FILL_TIME ) - { - if ( FALSE == setBicarbChamberFillRequested() ) - { - // TODO - //drybicart state machines are combined and so this is not an issue in future - //set alarm ? - } - bicarbChamberPeriodicFillCounter = 0; - } - } - + // execute current balancing chamber exec state switch ( balChamberExecState ) { case BAL_CHAMBER_STATE_START: @@ -269,43 +269,20 @@ /*********************************************************************//** * @brief - * The valveControlForBCClosedState function closes the all balancing - * chamber valves. + * The valveControlForBCState1FillStart function actuates the valve combination + * for state 1 fill/drain process. * @details \b Inputs: none * @details \b Outputs: valve states * @return none. *************************************************************************/ -void valveControlForBCClosedState( void ) +static void valveControlForBCState1FillStart( void ) { // Close balancing chamber valve combinations D23,D20 and D21,D26 setValveState( D23_VALV, VALVE_STATE_CLOSED ); setValveState( D20_VALV, VALVE_STATE_CLOSED ); setValveState( D21_VALV, VALVE_STATE_CLOSED ); setValveState( D26_VALV, VALVE_STATE_CLOSED ); - //Close balancing chamber valve combinations D19,D24 and D25,D22 - setValveState( D19_VALV, VALVE_STATE_CLOSED ); - setValveState( D24_VALV, VALVE_STATE_CLOSED ); - setValveState( D25_VALV, VALVE_STATE_CLOSED ); - setValveState( D22_VALV, VALVE_STATE_CLOSED ); -} - -/*********************************************************************//** - * @brief - * The valveControlForBCOpenState function opens all of the balancing - * chamber valves. - * @details \b Inputs: none - * @details \b Outputs: valve states - * @return none. - *************************************************************************/ -void valveControlForBCOpenState( void ) -{ - // Open balancing chamber valve combinations D23,D20 and D21,D26 - setValveState( D23_VALV, VALVE_STATE_OPEN ); - setValveState( D20_VALV, VALVE_STATE_OPEN ); - setValveState( D21_VALV, VALVE_STATE_OPEN ); - setValveState( D26_VALV, VALVE_STATE_OPEN ); - //Open balancing chamber valve combinations D19,D24 and D25,D22 setValveState( D19_VALV, VALVE_STATE_OPEN ); setValveState( D24_VALV, VALVE_STATE_OPEN ); @@ -315,115 +292,46 @@ /*********************************************************************//** * @brief - * The valveControlForBCFreshSideOnlyOpenState function opens the fresh side - * balancing chamber valves and closes the spent side valves. + * The valveControlForBCState1FillEnd function closes the valve opened + * for state 1 fill/drain process. * @details \b Inputs: none * @details \b Outputs: valve states * @return none. *************************************************************************/ -void valveControlForBCFreshSideOnlyOpenState( void ) +static void valveControlForBCState1FillEnd( void ) { - // Open fresh balancing chamber valves D19,D20,D21,D22 - setValveState( D19_VALV, VALVE_STATE_OPEN ); - setValveState( D20_VALV, VALVE_STATE_OPEN ); - setValveState( D21_VALV, VALVE_STATE_OPEN ); - setValveState( D22_VALV, VALVE_STATE_OPEN ); - - // Close spent side valves D23,D24,D25,D26 - setValveState( D23_VALV, VALVE_STATE_CLOSED ); - setValveState( D25_VALV, VALVE_STATE_CLOSED ); + //Close balancing chamber valve combinations D19,D24 and D25,D22 + setValveState( D19_VALV, VALVE_STATE_CLOSED ); setValveState( D24_VALV, VALVE_STATE_CLOSED ); - setValveState( D26_VALV, VALVE_STATE_CLOSED ); + setValveState( D25_VALV, VALVE_STATE_CLOSED ); + setValveState( D22_VALV, VALVE_STATE_CLOSED ); } /*********************************************************************//** * @brief - * The getCurrentBalancingChamberExecState function returns the current state - * of the balancing chamber. - * @details \b Inputs: balChamberExecState - * @details \b Outputs: none - * @return the current state of balancing chamber states. + * The valveControlForBCState2FillStart function actuates the valve combination + * for state 2 fill/drain process. + * @details \b Inputs: none + * @details \b Outputs: valve states + * @return none. *************************************************************************/ -BAL_CHAMBER_EXEC_STATE_T getCurrentBalancingChamberExecState( void ) +static void valveControlForBCState2FillStart( void ) { - return balChamberExecState; -} + //Close balancing chamber valve combinations D19,D24 and D25,D22 + setValveState( D19_VALV, VALVE_STATE_CLOSED ); + setValveState( D24_VALV, VALVE_STATE_CLOSED ); + setValveState( D25_VALV, VALVE_STATE_CLOSED ); + setValveState( D22_VALV, VALVE_STATE_CLOSED ); -/*********************************************************************//** - * @brief - * The getBalancingChamberFillinProgressStatus function returns the current - * balancing chamber fill in progress status. - * @details \b Inputs: isBalChamberFillInProgress - * @details \b Outputs: none - * @return the current balancing chamber fill in progress. - *************************************************************************/ -BOOL getBalancingChamberFillinProgressStatus( void ) -{ - return isBalChamberFillInProgress; + // Open balancing chamber valve combinations D23,D20 and D21,D26 + setValveState( D23_VALV, VALVE_STATE_OPEN ); + setValveState( D20_VALV, VALVE_STATE_OPEN ); + setValveState( D21_VALV, VALVE_STATE_OPEN ); + setValveState( D26_VALV, VALVE_STATE_OPEN ); } /*********************************************************************//** * @brief - * The getBalChamberSwitchingFreq function gets the balancing chamber switching - * frequency value. - * @details \b Inputs: balChamberSwitchingFreq - * @details \b Outputs: none - * @return balancing chamber switching frequency - *************************************************************************/ -F32 getBalChamberSwitchingFreq( void ) -{ - F32 result = balChamberSwitchingFreq.data; - - if ( OVERRIDE_KEY == balChamberSwitchingFreq.override ) - { - result = balChamberSwitchingFreq.ovData; - } - - return result; -} - -/*********************************************************************//** - * @brief - * The setBalChamberSwitchingOnlyStatus function sets the balancing chamber - * switching only On/Off status. - * @details \b Inputs: balanceChamberSwitchingOnly - * @details \b Outputs: none - * @return none - *************************************************************************/ -void setBalChamberSwitchingOnlyStatus( BOOL OnOff ) -{ - balanceChamberSwitchingOnly = OnOff; -} - -/*********************************************************************//** - * @brief - * The getBalChamberSwitchingOnlyStatus function gets the balancing chamber - * switching only status. - * @details \b Inputs: balanceChamberSwitchingOnly - * @details \b Outputs: none - * @return balancing chamber switching only without any pressure validation - * and dosing delivery - *************************************************************************/ -BOOL getBalChamberSwitchingOnlyStatus( void ) -{ - return balanceChamberSwitchingOnly; -} - -/*********************************************************************//** - * @brief - * The getBalChamberSwitchingPeriod function gets the balancing chamber - * switching period. - * @details \b Inputs: balChamberSwitchingPeriod - * @details \b Outputs: none - * @return balancing chamber switching period - *************************************************************************/ -U32 getBalChamberSwitchingPeriod( void ) -{ - return balChamberSwitchingPeriod; -} - -/*********************************************************************//** - * @brief * The valveControlForBCState2FillEnd function closes the valve opened * for state 2 fill/drain process. * @details \b Inputs: none @@ -441,65 +349,71 @@ /*********************************************************************//** * @brief - * The valveControlForBCState1FillStart function actuates the valve combination - * for state 1 fill/drain process. + * The valveControlForBCClosedState function closes the all balancing + * chamber valves. * @details \b Inputs: none * @details \b Outputs: valve states * @return none. *************************************************************************/ -static void valveControlForBCState1FillStart( void ) +void valveControlForBCClosedState( void ) { // Close balancing chamber valve combinations D23,D20 and D21,D26 setValveState( D23_VALV, VALVE_STATE_CLOSED ); setValveState( D20_VALV, VALVE_STATE_CLOSED ); setValveState( D21_VALV, VALVE_STATE_CLOSED ); setValveState( D26_VALV, VALVE_STATE_CLOSED ); - //Open balancing chamber valve combinations D19,D24 and D25,D22 - setValveState( D19_VALV, VALVE_STATE_OPEN ); - setValveState( D24_VALV, VALVE_STATE_OPEN ); - setValveState( D25_VALV, VALVE_STATE_OPEN ); - setValveState( D22_VALV, VALVE_STATE_OPEN ); + //Close balancing chamber valve combinations D19,D24 and D25,D22 + setValveState( D19_VALV, VALVE_STATE_CLOSED ); + setValveState( D24_VALV, VALVE_STATE_CLOSED ); + setValveState( D25_VALV, VALVE_STATE_CLOSED ); + setValveState( D22_VALV, VALVE_STATE_CLOSED ); } /*********************************************************************//** * @brief - * The valveControlForBCState1FillEnd function closes the valve opened - * for state 1 fill/drain process. + * The valveControlForBCOpenState function open the all balancing + * chamber valves. * @details \b Inputs: none * @details \b Outputs: valve states * @return none. *************************************************************************/ -static void valveControlForBCState1FillEnd( void ) +void valveControlForBCOpenState( void ) { - //Close balancing chamber valve combinations D19,D24 and D25,D22 - setValveState( D19_VALV, VALVE_STATE_CLOSED ); - setValveState( D24_VALV, VALVE_STATE_CLOSED ); - setValveState( D25_VALV, VALVE_STATE_CLOSED ); - setValveState( D22_VALV, VALVE_STATE_CLOSED ); + // Open balancing chamber valve combinations D23,D20 and D21,D26 + setValveState( D23_VALV, VALVE_STATE_OPEN ); + setValveState( D20_VALV, VALVE_STATE_OPEN ); + setValveState( D21_VALV, VALVE_STATE_OPEN ); + setValveState( D26_VALV, VALVE_STATE_OPEN ); + + //Open balancing chamber valve combinations D19,D24 and D25,D22 + setValveState( D19_VALV, VALVE_STATE_OPEN ); + setValveState( D24_VALV, VALVE_STATE_OPEN ); + setValveState( D25_VALV, VALVE_STATE_OPEN ); + setValveState( D22_VALV, VALVE_STATE_OPEN ); } /*********************************************************************//** * @brief - * The valveControlForBCState2FillStart function actuates the valve combination - * for state 2 fill/drain process. + * The valveControlForBCFreshSideOnlyOpenState function opens the fresh side + * balancing chamber valves and closes the spent side valves. * @details \b Inputs: none * @details \b Outputs: valve states * @return none. *************************************************************************/ -static void valveControlForBCState2FillStart( void ) +void valveControlForBCFreshSideOnlyOpenState( void ) { - //Close balancing chamber valve combinations D19,D24 and D25,D22 - setValveState( D19_VALV, VALVE_STATE_CLOSED ); - setValveState( D24_VALV, VALVE_STATE_CLOSED ); - setValveState( D25_VALV, VALVE_STATE_CLOSED ); - setValveState( D22_VALV, VALVE_STATE_CLOSED ); - - // Open balancing chamber valve combinations D23,D20 and D21,D26 - setValveState( D23_VALV, VALVE_STATE_OPEN ); + // Open fresh balancing chamber valves D19,D20,D21,D22 + setValveState( D19_VALV, VALVE_STATE_OPEN ); setValveState( D20_VALV, VALVE_STATE_OPEN ); setValveState( D21_VALV, VALVE_STATE_OPEN ); - setValveState( D26_VALV, VALVE_STATE_OPEN ); + setValveState( D22_VALV, VALVE_STATE_OPEN ); + + // Close spent side valves D23,D24,D25,D26 + setValveState( D23_VALV, VALVE_STATE_CLOSED ); + setValveState( D25_VALV, VALVE_STATE_CLOSED ); + setValveState( D24_VALV, VALVE_STATE_CLOSED ); + setValveState( D26_VALV, VALVE_STATE_CLOSED ); } /*********************************************************************//** @@ -509,30 +423,29 @@ * @details \b Inputs: Pressure * @details \b Outputs: valve states * @details \b Alarm: ALARM_ID_DD_BC_STATE1_FILL_START_PRESSURE_OUT_OF_RANGE - * when pressure is not in range during balacing chamber fill start. + * when pressure is not in range during balancing chamber fill start. * @return next balancing chamber state. *************************************************************************/ 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; isPressureStalbilizedDuringFill = FALSE; isPressureDroppedDuringFill = FALSE; - balChamberSWState = BAL_CHAMBER_SW_STATE1; + isSpentFillComplete = FALSE; F32 acidVolume = getF32OverrideValue( &acidDoseVolume ); F32 bicarbVolume = getF32OverrideValue( &bicarbDoseVolume ); freshDialPressure = getFilteredPressure( D18_PRES ); spentDialPressure = getFilteredPressure( D51_PRES ); - BOOL isFreshDialysatePressureInRange = ( freshDialPressure >= FRESH_DIAL_PRESSURE_MIN_PSIG ) && ( freshDialPressure <= FRESH_DIAL_PRESSURE_MAX_PSIG ); - BOOL isSpentDialysatePressureInRange = ( spentDialPressure >= SPENT_DIAL_PRESSURE_MIN_PSIG ) && ( spentDialPressure <= SPENT_DIAL_PRESSURE_MAX_PSIG ); - BOOL isBCSwitchOnlyStatus = ( TRUE == getBalChamberSwitchingOnlyStatus() ); - BOOL isDisableBCPressureAlarms = ( TRUE == getTestConfigStatus( TEST_CONFIG_DD_DISABLE_BC_PRESSURE_ALARMS ) ); - - // Check fresh and spent dialysate pressure in range or BC switch only flag set - if ( ( TRUE == isFreshDialysatePressureInRange && TRUE == isSpentDialysatePressureInRange ) || ( TRUE == isBCSwitchOnlyStatus ) || ( TRUE == isDisableBCPressureAlarms ) ) + // Check fresh dialysate pressure in range or BC switch only flag set or BC pressure alarms are disabled + if ( ( ( freshDialPressure >= FRESH_DIAL_PRESSURE_MIN_PSIG ) && ( freshDialPressure <= FRESH_DIAL_PRESSURE_MAX_PSIG ) ) || + ( TRUE == getBalChamberSwitchingOnlyStatus() ) || ( TRUE == getTestConfigStatus( TEST_CONFIG_DD_DISABLE_BC_PRESSURE_ALARMS ) ) ) { //Valve control for state 1 fill valveControlForBCState1FillStart(); @@ -543,9 +456,9 @@ // Deliver dosing during generate dialysate mode if ( TRUE != getBalChamberSwitchingOnlyStatus() ) { - // start acid and bicarb pump with the expected rate, speed in mL/min - setConcentratePumpTargetSpeed( D11_PUMP, DOSING_CONCENTRATE_PUMP_SPEED, acidVolume ); - setConcentratePumpTargetSpeed( D10_PUMP, DOSING_CONCENTRATE_PUMP_SPEED, bicarbVolume ); + // start acid and bicarb pump with the expected quantity + setConcentratePumpTargetSpeed( D11_PUMP, CONCENTRATE_PUMP_MAX_SPEED, acidVolume ); + setConcentratePumpTargetSpeed( D10_PUMP, CONCENTRATE_PUMP_MAX_SPEED, bicarbVolume ); requestConcentratePumpOn( D11_PUMP ); requestConcentratePumpOn( D10_PUMP ); } @@ -567,7 +480,7 @@ /*********************************************************************//** * @brief * The handleBalChamberConcentrateControl function handles the Acid and Bicarb - * concentrate doisng and checks the conductivity of the dialysate for the treatment. + * concentrate dosing and checks the conductivity of the dialysate for the treatment. * @details \b Inputs: balChamberSWState , Concentrate volume * @details \b Outputs: isPressureDroppedDuringFill, state * @return next balancing chamber state. @@ -578,7 +491,7 @@ freshDialPressure = getFilteredPressure( D18_PRES ); spentDialPressure = getFilteredPressure( D51_PRES ); - if ( BAL_CHAMBER_SW_STATE1 == balChamberSWState ) + if ( BAL_CHAMBER_SW_STATE1 == balChamberSWState ) { state = BAL_CHAMBER_STATE1_BICARB_ACID_DOSING_CNTRL; } @@ -601,6 +514,7 @@ ( TRUE == isConcentratePumpDosingCompleted( D10_PUMP ) ) ) || ( TRUE == getBalChamberSwitchingOnlyStatus() ) ) { + if ( BAL_CHAMBER_SW_STATE1 == balChamberSWState ) { state = BAL_CHAMBER_STATE1_VALVES_CLOSE; @@ -625,39 +539,52 @@ static BAL_CHAMBER_EXEC_STATE_T handleBalChamberState1ValvesClose( void ) { BAL_CHAMBER_EXEC_STATE_T state = BAL_CHAMBER_STATE1_VALVES_CLOSE; + freshDialPressure = getFilteredPressure( D18_PRES ); + spentDialPressure = getFilteredPressure( D51_PRES ); + BOOL isBothFillsComplete = FALSE; + BOOL isFirstCycleNotDone = FALSE; + BOOL isFillCompleteOrFirstCycle = FALSE; - freshDialPressure = getFilteredPressure( D18_PRES ); - spentDialPressure = getFilteredPressure( D51_PRES ); + // If fill is taking too long, set an alarm for fill timeout + if ( ( balChamberFillTimeoutCount > 0 ) && ( currentBalChamberFillCounter > balChamberFillTimeoutCount ) ) + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_BC_FILL_TIMEOUT_FAULT, currentBalChamberFillCounter, balChamberFillTimeoutCount ); + } - BOOL isFreshDialysatePressureInRange = ( freshDialPressure >= FRESH_DIAL_PRESSURE_MIN_PSIG ) && ( freshDialPressure <= FRESH_DIAL_PRESSURE_MAX_PSIG ); - BOOL isSpentDialysatePressureInRange = ( spentDialPressure >= SPENT_DIAL_PRESSURE_MIN_PSIG ) && ( spentDialPressure <= SPENT_DIAL_PRESSURE_MAX_PSIG ); - - // Check fresh and spent dialysate pressure back in range to indicate fill complete. - if ( getTestConfigStatus( TEST_CONFIG_DD_DISABLE_BC_PRESSURE_ALARMS ) != TRUE ) + // Check fresh dialysate pressure back in range to indicate fresh fill complete. + if ( ( freshDialPressure >= FRESH_DIAL_PRESSURE_MIN_PSIG ) && ( freshDialPressure <= FRESH_DIAL_PRESSURE_MAX_PSIG ) ) { if ( TRUE == isFreshDialysatePressureInRange && TRUE == isSpentDialysatePressureInRange ) { - if ( ++balChamberFillCompleteStablePressureCounter >= BAL_CHAMBER_FILL_COMPLETE_MS ) - { - // stabilized pressure indicating fill is complete - isPressureStalbilizedDuringFill = TRUE; - } + // stabilized pressure indicating fresh side fill is complete + isPressureStabilizedDuringFill = TRUE; } } else { isPressureStalbilizedDuringFill = FALSE; } - // Switching time met or pressure in range, close valves - if ( ( currentBalChamberSwitchingCounter >= balChamberValveClosePeriod ) || - ( TRUE == isPressureStalbilizedDuringFill ) ) + // Spent side of balancing chamber fill is complete or not + checkSpentFillComplete( spentDialPressure ); + + // Check both spent and fresh side fill is complete + isBothFillsComplete = ( TRUE == isSpentFillComplete ) && ( TRUE == isPressureStabilizedDuringFill ); + isFirstCycleNotDone = ( FALSE == isFirstCycleBCSwitchingCompleted ); + isFillCompleteOrFirstCycle = isBothFillsComplete || isFirstCycleNotDone; + + if ( TRUE == isFillCompleteOrFirstCycle ) { // close the state 1 opened valves valveControlForBCState1FillEnd(); isBalChamberFillInProgress = FALSE; + //setDialysatePumpTargetRPM( D48_PUMP, getD48PumpSpeedForBCFill(), TRUE ); + if ( TRUE == isFirstCycleBCSwitchingCompleted ) + { + setDialysatePumpTargetRPM( D48_PUMP, getD48PumpSpeedForBCFill(), TRUE ); + } - //Transition to next state + // Transition to next state state = BAL_CHAMBER_STATE1_FILL_END; } @@ -667,56 +594,52 @@ /*********************************************************************//** * @brief * The handleBalChamberState1FillEnd function check for the balancing chamber - * switching period and tranistion to next state switching. + * switching period and transition to next state switching. * @details \b Inputs: currentBalChamberSwitchingCounter, balChamberSwitchingPeriod * @details \b Outputs: balChamberFillPressureDropCounter,balChamberFillCompleteStablePressureCounter * @details \b Alarm: ALARM_ID_DD_BC_STATE1_FILL_PRESSURE_DROP_OUT_OF_RANGE - * when pressure drop is not in range during balacing chamber fill in progress. + * when pressure drop is not in range during balancing chamber fill in progress. * @details \b Alarm: ALARM_ID_DD_BC_STATE1_FILL_END_PRESSURE_OUT_OF_RANGE - * when pressure is not in range during balacing chamber fill complete. + * when pressure is not in range during balancing chamber fill complete. * @return next balancing chamber state. *************************************************************************/ static BAL_CHAMBER_EXEC_STATE_T handleBalChamberState1FillEnd( void ) { BAL_CHAMBER_EXEC_STATE_T state = BAL_CHAMBER_STATE1_FILL_END; - // On completion of cycle time, transition to next state - if ( currentBalChamberSwitchingCounter >= balChamberSwitchingPeriod ) - { - balChamberFillPressureDropCounter = 0; - balChamberFillCompleteStablePressureCounter = 0; + balChamberFillPressureDropCounter = 0; + balChamberFillCompleteStablePressureCounter = 0; - if ( TRUE != getBalChamberSwitchingOnlyStatus() ) + if ( TRUE != getBalChamberSwitchingOnlyStatus() ) + { + if ( getTestConfigStatus( TEST_CONFIG_DD_DISABLE_BC_PRESSURE_ALARMS ) != TRUE ) { - if ( getTestConfigStatus( TEST_CONFIG_DD_DISABLE_BC_PRESSURE_ALARMS ) != TRUE ) + if ( ( TRUE != isPressureDroppedDuringFill ) && ( TRUE == isFirstCycleBCSwitchingCompleted ) ) { - if ( ( TRUE != isPressureDroppedDuringFill ) && ( TRUE == isFirstCycleBCSwitchingCompleted ) ) - { - // When fill initiated, pressure is not dropped to the expected range, possible valve failures. - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DD_BC_STATE1_FILL_PRESSURE_DROP_OUT_OF_RANGE, freshDialPressure, spentDialPressure ); - } - else if ( TRUE != isPressureStalbilizedDuringFill ) - { - // Alarm when switching time expired, but still pressure not in range which indicates fill is not yet completed. - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DD_BC_STATE1_FILL_END_PRESSURE_OUT_OF_RANGE, freshDialPressure, spentDialPressure ); - } - else - { - // Move to next state when pressure is in range. - state = BAL_CHAMBER_STATE2_FILL_START; - } + // When fill initiated, pressure is not dropped to the expected range, possible valve failures. + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DD_BC_STATE1_FILL_PRESSURE_DROP_OUT_OF_RANGE, freshDialPressure, spentDialPressure ); } + else if ( TRUE != isPressureStabilizedDuringFill ) + { + // Alarm when switching time expired, but still pressure not in range which indicates fill is not yet completed. + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DD_BC_STATE1_FILL_END_PRESSURE_OUT_OF_RANGE, freshDialPressure, spentDialPressure ); + } else { - // Allow to proceed next state even though pressure is not stabilized. + // Move to next state when pressure is in range. state = BAL_CHAMBER_STATE2_FILL_START; } } else { + // Allow to proceed next state even though pressure is not stabilized. state = BAL_CHAMBER_STATE2_FILL_START; } } + else + { + state = BAL_CHAMBER_STATE2_FILL_START; + } return state; } @@ -728,7 +651,7 @@ * @details \b Inputs: fresh and spent dialysate pressure * @details \b Outputs: valve states * @details \b Alarm: ALARM_ID_DD_BC_STATE2_FILL_START_PRESSURE_OUT_OF_RANGE - * when pressure is not in range during balacing chamber state 2 fill start. + * when pressure is not in range during balancing chamber state 2 fill start. * @return next balancing chamber state. *************************************************************************/ static BAL_CHAMBER_EXEC_STATE_T handleBalChamberState2FillStart( void ) @@ -739,19 +662,18 @@ isPressureStalbilizedDuringFill = FALSE; isPressureDroppedDuringFill = FALSE; balChamberSWState = BAL_CHAMBER_SW_STATE2; + currentBalChamberFillCounter = 0; + balChamberFillTimeoutCount = 0; + isSpentFillComplete = FALSE; F32 acidVolume = getF32OverrideValue( &acidDoseVolume ); F32 bicarbVolume = getF32OverrideValue( &bicarbDoseVolume ); freshDialPressure = getFilteredPressure( D18_PRES ); spentDialPressure = getFilteredPressure( D51_PRES ); - BOOL isFreshDialysatePressureInRange = ( freshDialPressure >= FRESH_DIAL_PRESSURE_MIN_PSIG ) && ( freshDialPressure <= FRESH_DIAL_PRESSURE_MAX_PSIG ); - BOOL isSpentDialysatePressureInRange = ( spentDialPressure >= SPENT_DIAL_PRESSURE_MIN_PSIG ) && ( spentDialPressure <= SPENT_DIAL_PRESSURE_MAX_PSIG ); - BOOL isBCSwitchOnlyStatus = ( TRUE == getBalChamberSwitchingOnlyStatus() ); - BOOL isDisableBCPressureAlarms = ( TRUE == getTestConfigStatus( TEST_CONFIG_DD_DISABLE_BC_PRESSURE_ALARMS ) ); - - // Check fresh and spent dialysate pressure in range - if ( ( TRUE == isFreshDialysatePressureInRange && TRUE == isSpentDialysatePressureInRange ) || ( TRUE == isBCSwitchOnlyStatus ) || ( TRUE == isDisableBCPressureAlarms ) ) + // Check fresh dialysate pressure in range + if ( ( ( freshDialPressure >= FRESH_DIAL_PRESSURE_MIN_PSIG ) && ( freshDialPressure <= FRESH_DIAL_PRESSURE_MAX_PSIG ) ) || + ( TRUE == getBalChamberSwitchingOnlyStatus() ) || ( TRUE == getTestConfigStatus( TEST_CONFIG_DD_DISABLE_BC_PRESSURE_ALARMS ) ) ) { // Valve control for state 2 fill valveControlForBCState2FillStart(); @@ -762,9 +684,9 @@ // Deliver dosing during generate dialysate mode if ( TRUE != getBalChamberSwitchingOnlyStatus() ) { - // start acid and bicarb pump with the expected rate, speed in mL/min - setConcentratePumpTargetSpeed( D11_PUMP, DOSING_CONCENTRATE_PUMP_SPEED, acidVolume ); - setConcentratePumpTargetSpeed( D10_PUMP, DOSING_CONCENTRATE_PUMP_SPEED, bicarbVolume ); + // start acid and bicarb pump with the expected quantity + setConcentratePumpTargetSpeed( D11_PUMP, CONCENTRATE_PUMP_MAX_SPEED, acidVolume ); + setConcentratePumpTargetSpeed( D10_PUMP, CONCENTRATE_PUMP_MAX_SPEED, bicarbVolume ); requestConcentratePumpOn( D11_PUMP ); requestConcentratePumpOn( D10_PUMP ); } @@ -779,6 +701,7 @@ SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DD_BC_STATE2_FILL_START_PRESSURE_OUT_OF_RANGE, freshDialPressure, spentDialPressure ); } } + return state; } @@ -793,37 +716,50 @@ static BAL_CHAMBER_EXEC_STATE_T handleBalChamberState2ValvesClose( void ) { BAL_CHAMBER_EXEC_STATE_T state = BAL_CHAMBER_STATE2_VALVES_CLOSE; + freshDialPressure = getFilteredPressure( D18_PRES ); + spentDialPressure = getFilteredPressure( D51_PRES ); + BOOL isBothFillsComplete = FALSE; + BOOL isFirstCycleNotDone = FALSE; + BOOL isFillCompleteOrFirstCycle = FALSE; - freshDialPressure = getFilteredPressure( D18_PRES ); - spentDialPressure = getFilteredPressure( D51_PRES ); - - BOOL isFreshDialysatePressureInRange = ( freshDialPressure >= FRESH_DIAL_PRESSURE_MIN_PSIG ) && ( freshDialPressure <= FRESH_DIAL_PRESSURE_MAX_PSIG ); - BOOL isSpentDialysatePressureInRange = ( spentDialPressure >= SPENT_DIAL_PRESSURE_MIN_PSIG ) && ( spentDialPressure <= SPENT_DIAL_PRESSURE_MAX_PSIG ); - - // Check fresh and spent dialysate pressure back in range to indicate fill complete. - if ( getTestConfigStatus( TEST_CONFIG_DD_DISABLE_BC_PRESSURE_ALARMS ) != TRUE ) + // 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 ( ( TRUE == isFreshDialysatePressureInRange ) && ( TRUE == isSpentDialysatePressureInRange ) ) { - if ( ++balChamberFillCompleteStablePressureCounter >= BAL_CHAMBER_FILL_COMPLETE_MS ) - { - // stabilized pressure indicating fill is complete - isPressureStalbilizedDuringFill = TRUE; - } + // stabilized pressure indicating fresh side fill is complete + isPressureStabilizedDuringFill = TRUE; } } else { isPressureStalbilizedDuringFill = FALSE; } + // If fill is taking too long, set an alarm for fill timeout + if ( ( balChamberFillTimeoutCount > 0 ) && ( currentBalChamberFillCounter > balChamberFillTimeoutCount ) ) + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_BC_FILL_TIMEOUT_FAULT, currentBalChamberFillCounter, balChamberFillTimeoutCount ); + } + + // Spent side of balancing chamber fill is complete or not + checkSpentFillComplete( spentDialPressure ); + // Check switching cycle time or pressure check for valve closure - if ( ( currentBalChamberSwitchingCounter >= balChamberValveClosePeriod ) || - ( TRUE == isPressureStalbilizedDuringFill ) ) + isBothFillsComplete = ( TRUE == isSpentFillComplete ) && ( TRUE == isPressureStabilizedDuringFill ); + isFirstCycleNotDone = ( FALSE == isFirstCycleBCSwitchingCompleted ); + isFillCompleteOrFirstCycle = isBothFillsComplete || isFirstCycleNotDone; + + if ( TRUE == isFillCompleteOrFirstCycle ) { // close the valves valveControlForBCState2FillEnd(); isBalChamberFillInProgress = FALSE; + //setDialysatePumpTargetRPM( D48_PUMP, getD48PumpSpeedForBCFill(), TRUE ); + if ( TRUE == isFirstCycleBCSwitchingCompleted ) + { + setDialysatePumpTargetRPM( D48_PUMP, getD48PumpSpeedForBCFill(), TRUE ); + } //Transition to next state state = BAL_CHAMBER_STATE2_FILL_END; @@ -848,11 +784,8 @@ { BAL_CHAMBER_EXEC_STATE_T state = BAL_CHAMBER_STATE2_FILL_END; - // On completion of cycle time, transition to next state - if ( currentBalChamberSwitchingCounter >= balChamberSwitchingPeriod ) - { - balChamberFillPressureDropCounter = 0; - balChamberFillCompleteStablePressureCounter = 0; + balChamberFillPressureDropCounter = 0; + balChamberFillCompleteStablePressureCounter = 0; // Pressure alarm check if ( TRUE != getBalChamberSwitchingOnlyStatus() ) @@ -873,12 +806,6 @@ { // Move to next state when pressure is in range. state = BAL_CHAMBER_STATE1_FILL_START; - - // Trigger pressure drop alarm after first cycle of balancing chamber switching complete - if ( FALSE == isFirstCycleBCSwitchingCompleted ) - { - isFirstCycleBCSwitchingCompleted = TRUE; - } } } else @@ -891,13 +818,182 @@ { state = BAL_CHAMBER_STATE1_FILL_START; } - } + // Trigger pressure drop alarm after first cycle of balancing chamber switching complete + if ( FALSE == isFirstCycleBCSwitchingCompleted ) + { + isFirstCycleBCSwitchingCompleted = TRUE; + } + return state; } /*********************************************************************//** * @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. + * @details \b Inputs: balChamberExecState + * @details \b Outputs: none + * @param spentDialPressure to check the switching time for BC and set D48 speed based on it. + * @return the current state of balancing chamber states. + *************************************************************************/ +static void checkSpentFillComplete( F32 spentDialPressure ) +{ + U32 absDiffSpentFillCount = 0; + U32 adjustedSpeed = 0; + U32 spentDialPumpSpeed = getD48PumpSpeedForBCFill(); + U32 initialD48PumpSpeed = getCalculatedD48PumpSpeedForBCFill(); + U32 minD48Speed = initialD48PumpSpeed - ( initialD48PumpSpeed * D48_SPEED_RANGE_LIMIT ); + U32 maxD48Speed = initialD48PumpSpeed + ( initialD48PumpSpeed * D48_SPEED_RANGE_LIMIT ); + U32 d48SpeedPostRangeCheck = 0; + F32 qdMlpm = getTDDialysateFlowrate(); + BOOL result = FALSE; + F32 spentFillCompletePresPsig; + + // 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_LOW_MLPM ) + { + spentFillCompletePresPsig = SPENT_FILL_COMPLETE_PRES_QD_LOW_PSIG; + } + else if ( qdMlpm <= QD_THRESHOLD_HIGH_MLPM ) + { + spentFillCompletePresPsig = SPENT_FILL_COMPLETE_PRES_QD_MID_PSIG; + } + else + { + spentFillCompletePresPsig = SPENT_FILL_COMPLETE_PRES_QD_HIGH_PSIG; + } + } + + if ( ( spentDialPressure >= spentFillCompletePresPsig ) && ( 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; + } + 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 + isSpentFillComplete = TRUE; + } +} + +/*********************************************************************//** + * @brief + * The getCurrentBalancingChamberExecState function returns the current state + * of the balancing chamber. + * @details \b Inputs: balChamberExecState + * @details \b Outputs: none + * @return the current state of balancing chamber states. + *************************************************************************/ +BAL_CHAMBER_EXEC_STATE_T getCurrentBalancingChamberExecState( void ) +{ + return balChamberExecState; +} + +/*********************************************************************//** + * @brief + * The getBalancingChamberFillinProgressStatus function returns the current + * balancing chamber fill in progress status. + * @details \b Inputs: isBalChamberFillInProgress + * @details \b Outputs: none + * @return the current balancing chamber fill in progress. + *************************************************************************/ +BOOL getBalancingChamberFillinProgressStatus( void ) +{ + return isBalChamberFillInProgress; +} + +/*********************************************************************//** + * @brief + * The getBalChamberSwitchingFreq function gets the balancing chamber switching + * frequency value. + * @details \b Inputs: balChamberSwitchingFreq + * @details \b Outputs: none + * @return balancing chamber switching frequency + *************************************************************************/ +F32 getBalChamberSwitchingFreq( void ) +{ + F32 result = balChamberSwitchingFreq.data; + + if ( OVERRIDE_KEY == balChamberSwitchingFreq.override ) + { + result = balChamberSwitchingFreq.ovData; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The setBalChamberSwitchingOnlyStatus function sets the balancing chamber + * switching only On/Off status. + * @details \b Inputs: balanceChamberSwitchingOnly + * @details \b Outputs: none + * @param OnOff to set the BC switch status + * @return none + *************************************************************************/ +void setBalChamberSwitchingOnlyStatus( BOOL OnOff ) +{ + balanceChamberSwitchingOnly = OnOff; +} + +/*********************************************************************//** + * @brief + * The getBalChamberSwitchingOnlyStatus function gets the balancing chamber + * switching only status. + * @details \b Inputs: balanceChamberSwitchingOnly + * @details \b Outputs: none + * @return balancing chamber switching only without any pressure validation + * and dosing delivery + *************************************************************************/ +BOOL getBalChamberSwitchingOnlyStatus( void ) +{ + return balanceChamberSwitchingOnly; +} + +/*********************************************************************//** + * @brief + * The getBalChamberSwitchingPeriod function gets the balancing chamber + * switching period. + * @details \b Inputs: balChamberSwitchingPeriod + * @details \b Outputs: none + * @return balancing chamber switching period + *************************************************************************/ +U32 getBalChamberSwitchingPeriod( void ) +{ + return balChamberSwitchingPeriod; +} + +/*********************************************************************//** + * @brief * The getBalChamberDataPublishInterval function gets the balancing chamber * data publish interval. * @details \b Inputs: balChamberDataPublishInterval @@ -935,10 +1031,10 @@ data.balChamberExecState = (U32)balChamberExecState; data.balChamberSWState = (U32)balChamberSWState; data.balChamberSWFreq = getBalChamberSwitchingFreq(); - data.balChamberSwPeriod = balChamberSwitchingPeriod; - data.isBalChamberFillInProgress = isBalChamberFillInProgress; - data.currentBalChamberSwitchingCounter = currentBalChamberSwitchingCounter; - data.isPressureStalbilizedDuringFill = isPressureStalbilizedDuringFill; + data.balChamberSwPeriod = getD48PumpSpeedForBCFill(); + data.isBalChamberFillInProgress = isSpentFillComplete; + data.currentBalChamberSwitchingCounter = currentBalChamberFillCounter; + data.isPressureStabilizedDuringFill = isPressureStabilizedDuringFill; data.balChamberSWOnlyState = balanceChamberSwitchingOnly; broadcastData( MSG_ID_DD_BAL_CHAMBER_DATA, COMM_BUFFER_OUT_CAN_DD_BROADCAST, (U08*)&data, sizeof( BAL_CHAMBER_DATA_T ) ); @@ -1036,7 +1132,7 @@ { BOOL result = FALSE; - // Verify tester has logged in with DD + // Verify tester has logged in with TD if ( TRUE == isTestingActivated() ) { // Verify payload length is valid Index: firmware/App/Controllers/BalancingChamber.h =================================================================== diff -u -r5d60262836ddc8f80ac98f07f2cfd6707a5b7b79 -r1077fee46974061e6e0038b6c0ce0e1471715b61 --- firmware/App/Controllers/BalancingChamber.h (.../BalancingChamber.h) (revision 5d60262836ddc8f80ac98f07f2cfd6707a5b7b79) +++ firmware/App/Controllers/BalancingChamber.h (.../BalancingChamber.h) (revision 1077fee46974061e6e0038b6c0ce0e1471715b61) @@ -7,8 +7,8 @@ * * @file BalancingChamber.h * -* @author (last) Vinayakam Mani -* @date (last) 03-Oct-2025 +* @author (last) Jashwant Gantyada +* @date (last) 06-Mar-2026 * * @author (original) Vinayakam Mani * @date (original) 28-Jan-2025 Index: firmware/App/DDCommon.h =================================================================== diff -u -r202978f0c2f12bf5a1e466d6788e3a6fc6243569 -r1077fee46974061e6e0038b6c0ce0e1471715b61 --- firmware/App/DDCommon.h (.../DDCommon.h) (revision 202978f0c2f12bf5a1e466d6788e3a6fc6243569) +++ firmware/App/DDCommon.h (.../DDCommon.h) (revision 1077fee46974061e6e0038b6c0ce0e1471715b61) @@ -7,8 +7,8 @@ * * @file DDCommon.h * -* @author (last) Sameer Kalliadan Poyil -* @date (last) 10-Feb-2026 +* @author (last) Jashwant Gantyada +* @date (last) 13-Mar-2026 * * @author (original) Vinayakam Mani * @date (original) 07-Aug-2024 @@ -25,7 +25,7 @@ #define DD_VERSION_MAJOR 0 #define DD_VERSION_MINOR 0 #define DD_VERSION_MICRO 0 -#define DD_VERSION_BUILD 56 +#define DD_VERSION_BUILD 58 // ********** development build switches ********** @@ -48,9 +48,6 @@ //Uncomment below for bicarb chamber filling //#define __BICARB_CHAMBER_FILL__ 1 -//Uncomment below for Maxon controller speed change -#define __MAXON_SPEED_UPDATE__ 1 - //Uncomment below to disable heaters debug message #define __HEATERS_DEBUG__ 1 Index: firmware/App/Modes/ModeGenDialysate.c =================================================================== diff -u -r5d60262836ddc8f80ac98f07f2cfd6707a5b7b79 -r1077fee46974061e6e0038b6c0ce0e1471715b61 --- firmware/App/Modes/ModeGenDialysate.c (.../ModeGenDialysate.c) (revision 5d60262836ddc8f80ac98f07f2cfd6707a5b7b79) +++ firmware/App/Modes/ModeGenDialysate.c (.../ModeGenDialysate.c) (revision 1077fee46974061e6e0038b6c0ce0e1471715b61) @@ -7,8 +7,8 @@ * * @file ModeGenDialysate.c * -* @author (last) Sameer Kalliadan Poyil -* @date (last) 06-Feb-2026 +* @author (last) Jashwant Gantyada +* @date (last) 13-Mar-2026 * * @author (original) Vinayakam Mani * @date (original) 06-Nov-2024 @@ -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,14 @@ #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_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. +#define BICARB_CHAMBER_FILL_TIMEOUT ( 1 * MS_PER_SECOND ) ///< Bicarb chamber fill timeout. + //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., +#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 typedef struct { @@ -88,6 +95,7 @@ static U32 bypassStateDelayStartTimeMS; ///< Delay balancing chamber switching for a second to preapre pump steady state. static BOOL delayBypassStateFlag; ///< To indicate change in treatment parameters static F32 dialysateToDialyzerFlowRate; ///< Current dialysate to dialyzer flow rate (ml/min) +static U32 d48PumpSpeed; ///< Initial D48 pump speed based on the Qd. // ********** private function prototypes ********** @@ -104,6 +112,7 @@ static void checkDialysateTemperature( void ); static void monitorChamberLevelStatus( void ); static void publishGenDialysateModeData( void ); +static U32 getFreshDialPumpInitialRpm( void ); /*********************************************************************//** * @brief @@ -137,6 +146,7 @@ bicarbFillStartTimeMS = 0; pendingSpentChamberFill = FALSE; pendingBicarbChamberFill = FALSE; + d48PumpSpeed = getDialysatePumpMinRPM( D48_PUMP ); //Testing bypassStateDelayStartTimeMS = 0; delayBypassStateFlag = TRUE; @@ -160,8 +170,13 @@ *************************************************************************/ U32 transitionToGenDialysateMode( void ) { + U32 initialD48PumpSpeed = 0U; + initGenDialysateMode(); setCurrentSubState( NO_SUB_STATE ); + //calculateD48PumpSpeedForBCFill(); + initialD48PumpSpeed = getCalculatedD48PumpSpeedForBCFill(); + setD48PumpSpeedForBCFill( initialD48PumpSpeed ); transitionToUltrafiltration(); return genDialysateState; @@ -194,6 +209,26 @@ /*********************************************************************//** * @brief + * The getFreshDialPumpInitialRpm function returns fresh dialysate pump initial + * rpm based on hardwawre configuration. + * @details Inputs: FRESH_DIAL_PUMP_INITIAL_RPM, FRESH_DIAL_PUMP_INITIAL_RPM_B1_9_B2_0 + * @details Outputs: none + * @return fresh dialysate pump initial RPM for the active hardware variant + *************************************************************************/ +static U32 getFreshDialPumpInitialRpm( void ) +{ + U32 rpm = FRESH_DIAL_PUMP_INITIAL_RPM_B1_9_B2_0; + + if ( TRUE == getTestConfigStatus( TEST_CONFIG_DD_FP_ENABLE_BETA_1_0_HW ) ) + { + rpm = FRESH_DIAL_PUMP_INITIAL_RPM; + } + + return rpm; +} + +/*********************************************************************//** + * @brief * The setModeGenDStateTransition function sets the actuators and variables * for the state transition in generate dialysis mode. * @details Inputs: Valve states, Pump speed @@ -237,9 +272,9 @@ //Testing : Enable close loop once testing is complete //setDialysatePumpTargetRPM( D12_PUMP, FRESH_DIAL_PUMP_INITIAL_RPM, FALSE ); - setDialysatePumpTargetRPM( D12_PUMP, FRESH_DIAL_PUMP_INITIAL_RPM, TRUE ); + setDialysatePumpTargetRPM( D12_PUMP, getFreshDialPumpInitialRpm(), TRUE ); //setDialysatePumpTargetRPM( D48_PUMP, SPENT_DIAL_PUMP_INITIAL_RPM, FALSE ); - setDialysatePumpTargetRPM( D48_PUMP, SPENT_DIAL_PUMP_INITIAL_RPM, TRUE ); + setDialysatePumpTargetRPM( D48_PUMP, d48PumpSpeed, TRUE ); //Rinse pump On setRinsePumpState( RINSE_PUMP_STATE_ON ); @@ -269,9 +304,9 @@ startHeater( D5_HEAT ); //setDialysatePumpTargetRPM( D12_PUMP, FRESH_DIAL_PUMP_INITIAL_RPM, FALSE ); - setDialysatePumpTargetRPM( D12_PUMP, FRESH_DIAL_PUMP_INITIAL_RPM, TRUE ); + setDialysatePumpTargetRPM( D12_PUMP, getFreshDialPumpInitialRpm(), TRUE ); //setDialysatePumpTargetRPM( D48_PUMP, SPENT_DIAL_PUMP_INITIAL_RPM, FALSE ); - setDialysatePumpTargetRPM( D48_PUMP, SPENT_DIAL_PUMP_INITIAL_RPM, TRUE ); + setDialysatePumpTargetRPM( D48_PUMP, d48PumpSpeed, TRUE ); //Rinse pump On setRinsePumpState( RINSE_PUMP_STATE_ON ); @@ -319,7 +354,7 @@ setD28TempFeedbackControl( TRUE ); startHeater( D5_HEAT ); - setDialysatePumpTargetRPM( D12_PUMP, FRESH_DIAL_PUMP_INITIAL_RPM, TRUE ); + setDialysatePumpTargetRPM( D12_PUMP, getFreshDialPumpInitialRpm(), TRUE ); setDialysatePumpTargetRPM( D48_PUMP, SPENT_DIAL_PUMP_FILL_RPM, TRUE ); //Rinse pump On @@ -362,11 +397,11 @@ setRinsePumpState( RINSE_PUMP_STATE_ON ); setDialysatePumpTargetRPM( D12_PUMP, FRESH_DIAL_PUMP_INITIAL_RPM, TRUE ); - setDialysatePumpTargetRPM( D48_PUMP, SPENT_DIAL_PUMP_INITIAL_RPM, TRUE ); + setDialysatePumpTargetRPM( D48_PUMP, d48PumpSpeed, TRUE ); break; case DD_GEND_DIALYSATE_DELIVERY_PAUSE: - setDialysatePumpTargetRPM( D12_PUMP, FRESH_DIAL_PUMP_INITIAL_RPM, TRUE ); + setDialysatePumpTargetRPM( D12_PUMP, getFreshDialPumpInitialRpm(), TRUE ); signalDialysatePumpHardStop( D48_PUMP ); requestConcentratePumpOff( D11_PUMP, FALSE ); requestConcentratePumpOff( D10_PUMP, FALSE ); @@ -534,6 +569,31 @@ /*********************************************************************//** * @brief + * The getD48PumpSpeedForBCFill function returns the calculated D48 pump speed + * @details \b Inputs: d48PumpSpeed + * @details \b Outputs: none + * @return D48 pump speed. + *************************************************************************/ +U32 getD48PumpSpeedForBCFill( void ) +{ + return d48PumpSpeed; +} + +/*********************************************************************//** + * @brief + * The setD48PumpSpeedForBCFill function sets the updated D48 pump speed. + * @details \b Inputs: none + * @details \b Outputs: d48PumpSpeed + * @param pumpSpeed Dialysate pump speed + * @return none. + *************************************************************************/ +void setD48PumpSpeedForBCFill( U32 pumpSpeed ) +{ + d48PumpSpeed = pumpSpeed; +} + +/*********************************************************************//** + * @brief * The monitorChamberLevelStatus function checks the spent chamber and bicarb * chamber level status and updates the corrosponding flags. * @details \b Inputs: Spent and bicarb chamber levels. @@ -572,7 +632,7 @@ if ( dialFlowrate >= LOW_DIAL_FLOW_RATE ) { - // linear releationship seen against high dialysate flowrate Vs DeltaTemp + // linear relationship seen against high dialysate flowrate Vs DeltaTemp // deltaTemp = (-0.0029 * Qd) + 3.47 deltaTemp = ( LINEAR_SLOPE_FACTOR * dialFlowrate ) + LINEAR_INTERCEPT_FACTOR; } @@ -589,6 +649,47 @@ /*********************************************************************//** * @brief + * 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 in RPM (Diener 1000 or 2000 formula per test config). + *************************************************************************/ +U32 getCalculatedD48PumpSpeedForBCFill( void ) +{ + F32 dialFlowrate = getTDDialysateFlowrate(); + F32 slope; + F32 intercept; + F32 calculatedSpeed; + U32 rpm; + + if ( TRUE == getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DIENER_2000_PUMP ) ) + { + slope = PUMP_SPEED_SLOPE_FACTOR_DIENER_2000; + intercept = PUMP_SPEED_INTERCEPT_FACTOR_DIENER_2000; + } + else + { + slope = PUMP_SPEED_SLOPE_FACTOR_DIENER_1000; + intercept = PUMP_SPEED_INTERCEPT_FACTOR_DIENER_1000; + } + + // Calculate nominal speed from Qd. + calculatedSpeed = ( slope * dialFlowrate ) + intercept; + + // Prevent negative before converting to unsigned and round up using ceilf. + if ( calculatedSpeed < 0.0F ) + { + calculatedSpeed = 0.0F; + } + + rpm = (U32)ceilf( calculatedSpeed ); + + return rpm; +} + +/*********************************************************************//** + * @brief * The handleGenDDialysateIsolatedUFState function performs the * Isolated ultrafiltration operations. * @details \b Inputs: none. @@ -876,6 +977,8 @@ *************************************************************************/ void updateTreatmentSettings( void ) { + F32 initialPumpSpeed = 0.0F; + // Update any dynamic treatment parameter changes if ( TRUE == isTreatmentParamUpdated ) { @@ -894,6 +997,11 @@ //TODO: update others parameters setting as needed. signalUFRateUpdate(); + //Update D48 pump speed + //calculateD48PumpSpeedForBCFill(); + initialPumpSpeed = getCalculatedD48PumpSpeedForBCFill(); + setD48PumpSpeedForBCFill( initialPumpSpeed ); + //reset the flag isTreatmentParamUpdated = FALSE; } Index: firmware/App/Services/FpgaDD.c =================================================================== diff -u -rf469421f00fff93217379150c82b5c291a0afa64 -r1077fee46974061e6e0038b6c0ce0e1471715b61 --- firmware/App/Services/FpgaDD.c (.../FpgaDD.c) (revision f469421f00fff93217379150c82b5c291a0afa64) +++ firmware/App/Services/FpgaDD.c (.../FpgaDD.c) (revision 1077fee46974061e6e0038b6c0ce0e1471715b61) @@ -8,8 +8,8 @@ * * @file FpgaDD.c * -* @author (last) Raghu Kallala -* @date (last) 23-Feb-2026 +* @author (last) Jashwant Gantyada +* @date (last) 12-Mar-2026 * * @author (original) Vinayakam Mani * @date (original) 26-Aug-2024 @@ -143,6 +143,10 @@ #define PUMP_SPEED_OFFSET 168.7F ///< Speed Scale adjustment intercept factor #define PUMP_SPEED_FULL_SCALE 3187.0F ///< Speed scale adjustment slope factor +#define DIENER_1000_PUMP_SLOPE 0.000296F ///< Speed adjustment slope factor (Diener 1000 pump) +#define DIENER_1000_PUMP_INTERCEPT 0.07040F ///< Speed adjustment intercept factor (Diener 1000 pump) +#define DIENER_1000_PUMP_SPEED_FULL_SCALE 3150 ///< Maximum speed factor (Diener 1000 pump) + #pragma pack(push,1) /// FPGA header struct. typedef struct @@ -1087,16 +1091,16 @@ *************************************************************************/ void setFPGAD48PumpSpeed( U16 speed ) { -#ifdef __MAXON_SPEED_UPDATE__ //TODO: Enable for Beat 1/1.9 with Diener silencer 2000 pump. + if ( TRUE == getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DIENER_2000_PUMP )) { U16 currentSpeed =(U16)( ( ( speed + PUMP_SPEED_OFFSET ) / PUMP_SPEED_FULL_SCALE ) * MAX_PUMP_SPEED ); SET_FPGA_ACTUATOR_FIELD( fpgaD48PumpSpeed, currentSpeed ); } -#else + else { - SET_FPGA_ACTUATOR_FIELD( fpgaD48PumpSpeed, speed ); + U16 currentSpeed = (U16)( ( ( DIENER_1000_PUMP_SLOPE * speed ) + DIENER_1000_PUMP_INTERCEPT) * DIENER_1000_PUMP_SPEED_FULL_SCALE ); + SET_FPGA_ACTUATOR_FIELD( fpgaD48PumpSpeed, currentSpeed ); } -#endif } /*********************************************************************//** @@ -1110,16 +1114,8 @@ *************************************************************************/ void setFPGAD12PumpSpeed( U16 speed ) { -#ifdef __MAXON_SPEED_UPDATE__ /* Enable for B1.0/B1.9 with Diener Silencer 2000 pumps */ - { - U16 currentSpeed =(U16)( ( ( speed + PUMP_SPEED_OFFSET ) / PUMP_SPEED_FULL_SCALE ) * MAX_PUMP_SPEED ); - SET_FPGA_ACTUATOR_FIELD( fpgaD12PumpSpeed, currentSpeed ); - } -#else - { - SET_FPGA_ACTUATOR_FIELD( fpgaD12PumpSpeed, speed ); - } -#endif + U16 currentSpeed =(U16)( ( ( speed + PUMP_SPEED_OFFSET ) / PUMP_SPEED_FULL_SCALE ) * MAX_PUMP_SPEED ); + SET_FPGA_ACTUATOR_FIELD( fpgaD12PumpSpeed, currentSpeed ); } /*********************************************************************//**