Index: firmware/App/Controllers/DryBiCart.c =================================================================== diff -u -rd2f5fe93cb4abd8bf8c3bc4a9aa17146c7414062 -r96468474a209ba55660ba0f1c7441bb381d24ff8 --- firmware/App/Controllers/DryBiCart.c (.../DryBiCart.c) (revision d2f5fe93cb4abd8bf8c3bc4a9aa17146c7414062) +++ firmware/App/Controllers/DryBiCart.c (.../DryBiCart.c) (revision 96468474a209ba55660ba0f1c7441bb381d24ff8) @@ -8,7 +8,7 @@ * @file DryBiCart.c * * @author (last) Sameer Kalliadan Poyil -* @date (last) 16-Apr-2026 +* @date (last) 29-Apr-2026 * * @author (original) Vinayakam Mani * @date (original) 19-Nov-2025 @@ -46,15 +46,15 @@ // Dry Bicart Fill #define DRY_BICART_FILL_PERSISTANCE_DURATION_MS 200 ///< Fill persistence duration to overcome the pressure over shoot for beta 1.9 and beta 2.0. -#define DRY_BICART_FILL_DURATION_MIN_MS ( 2 * MS_PER_SECOND + \ - DRY_BICART_FILL_PERSISTANCE_DURATION_MS) ///< Minimum fill duration to be met to end the fill cycle. +#define DRY_BICART_FILL_DURATION_MIN_MS ( ( 2 * MS_PER_SECOND ) + \ + DRY_BICART_FILL_PERSISTANCE_DURATION_MS ) ///< Minimum fill duration to be met to end the fill cycle. #define DRY_BICART_FILL_COMPLETE_TIME_MS ( 1 * MS_PER_SECOND ) ///< Wait time to reset the request flag after fill complete #define DRY_BICART_FILL_DURATION_DIFF_MS 750 ///< Fill duration difference between last and current fill cycle. -#define PRESSURE_OFFSET_PSI 1 ///< Dry bicart pressure offset. +#define PRESSURE_OFFSET_PSI 2 ///< Dry bicart pressure offset. #define DRY_BICART_FILL_COMPLETE_PRESSURE ( 10.0F + PRESSURE_OFFSET_PSI ) ///< Maximum pressure reached to indicate the dry bicart fill being completed. #define DRY_BICART_FILL_INITIATE_PRESSURE 1.5F ///< Minimum pressure required to initiate the dry bicart fill process. -#define DRY_BICART_FILL_COMPLETE_SUPPLY_PRESSURE 6.0F ///< Maximum pressure allowed at bicart fill during supply process/state +#define DRY_BICART_FILL_COMPLETE_SUPPLY_PRESSURE 8.0F ///< Maximum pressure allowed at bicart fill during supply process/state #define DRY_BICART_FILL_INITIATE_SUPPLY_PRESSURE 3.0F ///< Minimum pressure required to initiate the dry bicart fill during supply process/state #define MAX_DRY_BICART_FILL_COMPLETE_PRESSURE 15 ///< Very Max dry bicart fill complete pressure for persistence on d66 @@ -110,10 +110,10 @@ #define MIX_NO_FEED_FORWARD 0.0F ///< Feedforward term for dialysate closed loop control -#define MIX_CONTROL_INTERVAL_MS ( 15 * MS_PER_SECOND ) ///< Dialysate dosing control interval in ms -#define BICARB_MIX_CONTROL_INTERVAL ( 3 * MS_PER_SECOND /\ +#define MIX_CONTROL_INTERVAL_MS ( 15 * MS_PER_SECOND ) ///< Dialysate dosing control interval in ms +#define BICARB_MIX_CONTROL_INTERVAL ( 3 * MS_PER_SECOND /\ TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the dialysate mix is controlled. -#define ACID_MIX_CONTROL_INTERVAL ( MIX_CONTROL_INTERVAL_MS /\ +#define ACID_MIX_CONTROL_INTERVAL ( MIX_CONTROL_INTERVAL_MS /\ TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the dialysate mix is controlled. #define BICARB_DEADBAND_CONTROL 50.0F ///< Dry Bicarb dead band control #define ACID_DEADBAND_CONTROL 100.0F ///< Acid dead band control @@ -192,6 +192,7 @@ static U32 dryBiCartDrainCondStableCount; ///< Debounce counter for "zero" conductivity static U32 dryBiCartDrainTimePeriod; ///< Dry bicart drain time period +static U32 dryBiCartPersistanceStartTime; ///< Dry bicart fill start time. static DRY_BICART_OPERATION_T dryBicartStartRequest; ///< Dry bicart operation, fill or supply or drain request // drybicart mixing @@ -212,7 +213,7 @@ static OVERRIDE_F32_T dryBiCartDialysateTargetConductivity; ///< Acid bicarb mix conductivity static OVERRIDE_F32_T dryBiCartDialysateDeltaConductivity; ///< Acid bicarb delta conductivity -static OVERRIDE_F32_T dryBiCartMixControlInterval; ///< Mix control interval +static OVERRIDE_U32_T dryBiCartMixControlInterval; ///< Mix control interval static PI_CONTROLLER_SIGNALS_DATA bicarbControlSignals; ///< Bicarb closed loop control signal data static PI_CONTROLLER_SIGNALS_DATA acidControlSignals; ///< Acid closed loop control signal data @@ -260,7 +261,7 @@ static F32 getAcidKiGainCoefficient( void ); static F32 getDryBicartLowerCartPressure( void ); static F32 getDryBicartUpperCartPressure( void ); -static F32 getDryBicartMixControlInterval( void ); +static U32 getDryBicartMixControlInterval( void ); // publish the status static void publishDryBicartData( void ); @@ -381,7 +382,7 @@ dryBiCartMixControlInterval.data = BICARB_MIX_CONTROL_INTERVAL; dryBiCartMixControlInterval.ovData = BICARB_MIX_CONTROL_INTERVAL; - dryBiCartMixControlInterval.ovInitData = 0.0F; + dryBiCartMixControlInterval.ovInitData = 0; dryBiCartMixControlInterval.override = OVERRIDE_RESET; dryBiCartFillStartTime = 0; @@ -395,6 +396,7 @@ dryBiCartDrainLastCondSampleTime = 0; dryBiCartDrainCondStableCount = 0; dryBiCartDrainTimePeriod = 0; + dryBiCartPersistanceStartTime = 0; initializePIController( PI_CONTROLLER_ID_BICARB_VOL, 0.0F,\ getBicarbKpGainCoefficient(), getBicarbKiGainCoefficient(),\ @@ -1011,9 +1013,9 @@ * @details \b Outputs: none * @return TRUE if successful, FALSE if not. *************************************************************************/ -static F32 getDryBicartMixControlInterval( void ) +static U32 getDryBicartMixControlInterval( void ) { - F32 result = getF32OverrideValue( &dryBiCartMixControlInterval ); + U32 result = getU32OverrideValue( &dryBiCartMixControlInterval ); return result; } @@ -1097,38 +1099,51 @@ { DIALYSATE_MIXING_STATE_T state = DIALYSATE_MIXING_CONTROL_TO_TARGET_STATE; - // control at set minimum interval or interval is expired and balance chamber fill is complete - if ( ( ++dialysateMix[ mixId ].controlTimerCounter >= getDryBicartMixControlInterval() ) ) + if ( BICARB_MIX_ID == mixId ) { - dialysateMix[ mixId ].controlTimerCounter = 0; - - // Control based on the measured and target conductivity - if ( BICARB_MIX_ID == mixId ) + // control interval for bicarb + if ( ( ++dialysateMix[ mixId ].controlTimerCounter >= getDryBicartMixControlInterval() ) ) { + dialysateMix[ mixId ].controlTimerCounter = 0; + + // Control based on the measured and target conductivity PI_CONTROLLER_SIGNALS_DATA debugBicarbControl; F32 measuredBicarbConductivity; measuredBicarbConductivity = getFilteredConductivity( D17_COND ); + F32 bicarbMixVol = runPIController( PI_CONTROLLER_ID_BICARB_VOL, getBicarbTargetConductivity(), measuredBicarbConductivity ); - //Set bicarb dosing vol - setBicarbMixVol( bicarbMixVol ); + if ( fabs ( getBicarbTargetConductivity() - measuredBicarbConductivity ) > BICARB_DEADBAND_CONTROL ) + { + //Set bicarb mix vol only if its above dead band threshold, else use the previous set vlaue + setBicarbMixVol( bicarbMixVol ); + } + debugBicarbControl = getDebugPIControllerSignals( PI_CONTROLLER_ID_BICARB_VOL ); memcpy( (void*)&bicarbControlSignals, (void*)&debugBicarbControl, sizeof(PI_CONTROLLER_SIGNALS_DATA) ); } - // ACID Mix - else if ( ACID_MIX_ID == mixId ) + } + + if ( ACID_MIX_ID == mixId ) + { + // control interval for acid + if ( ( ++dialysateMix[ mixId ].controlTimerCounter >= ACID_MIX_CONTROL_INTERVAL ) ) { - F32 measuredAcidBicarbMixConductivity; + dialysateMix[ mixId ].controlTimerCounter = 0; + + F32 measuredAcidBicarbMixConductivity = getFilteredConductivity( D27_COND ); PI_CONTROLLER_SIGNALS_DATA debugAcidControl; - measuredAcidBicarbMixConductivity = getFilteredConductivity( D27_COND ); - F32 acidMixVol = runPIController( PI_CONTROLLER_ID_ACID_VOL, getAcidBicarbTargetConductivity(), measuredAcidBicarbMixConductivity ); - //Set acid dosing vol - setAcidMixVol( acidMixVol ); + if ( fabs ( getAcidBicarbTargetConductivity() - measuredAcidBicarbMixConductivity ) > ACID_DEADBAND_CONTROL ) + { + // set acid mix volume if its above dead band threshold , else use previous set value + setAcidMixVol( acidMixVol ); + } + debugAcidControl = getDebugPIControllerSignals( PI_CONTROLLER_ID_ACID_VOL ); memcpy( (void*)&acidControlSignals, (void*)&debugAcidControl, sizeof(PI_CONTROLLER_SIGNALS_DATA) ); @@ -1244,12 +1259,37 @@ // Close dry bicart inlet water if bicart is filled with water if ( d66Pressure >= DRY_BICART_FILL_COMPLETE_PRESSURE ) { - setValveState( D65_VALV, VALVE_STATE_CLOSED ); - lastFillDurationInMS = currentFillDurationInMS; - currentFillDurationInMS = calcTimeSince( dryBiCartFillStartTime ); - //Increment number of fill cycle - biCartFillCycleCounter++; - state = DRY_BICART_DEGAS_START_STATE; + // start the persistance timer once d66 reaches 11 PSI + if ( 0 == dryBiCartPersistanceStartTime ) + { + dryBiCartPersistanceStartTime = getMSTimerCount(); + } + // to check the the maximum cart pressure during persistence on D66 + if ( d66Pressure >= MAX_DRY_BICART_FILL_COMPLETE_PRESSURE ) + { + setValveState( D65_VALV, VALVE_STATE_CLOSED ); + + lastFillDurationInMS = currentFillDurationInMS; + currentFillDurationInMS = calcTimeSince( dryBiCartFillStartTime ); + //Increment number of fill cycle + biCartFillCycleCounter++; + dryBiCartPersistanceStartTime = 0; + + state = DRY_BICART_DEGAS_START_STATE; + } + // 200 ms persistence on D66 pressure since pressure overshoot just after D65 opening + if ( TRUE == didTimeout( dryBiCartPersistanceStartTime, DRY_BICART_FILL_PERSISTANCE_DURATION_MS ) ) + { + setValveState( D65_VALV, VALVE_STATE_CLOSED ); + + lastFillDurationInMS = currentFillDurationInMS; + currentFillDurationInMS = calcTimeSince( dryBiCartFillStartTime ); + //Increment number of fill cycle + biCartFillCycleCounter++; + dryBiCartPersistanceStartTime = 0; + + state = DRY_BICART_DEGAS_START_STATE; + } } //TODO:Handle timeout alarm for opening D65 valve too long @@ -1451,6 +1491,7 @@ setValveState( D65_VALV, VALVE_STATE_OPEN ); //setValveState( D3_VALV, VALVE_STATE_OPEN ); dryBiCarbSupplyStartTime = getMSTimerCount(); + dryBiCartPersistanceStartTime = 0; return state; } @@ -1474,12 +1515,14 @@ if ( d66Pressure >= MAX_DRY_BICART_FILL_COMPLETE_PRESSURE ) { setValveState( D65_VALV, VALVE_STATE_CLOSED ); + dryBiCartPersistanceStartTime = 0; state = BICARB_CHAMBER_CHECK_LEVEL_STATE; } // 200 ms persistence on D66 pressure since pressure overshoot just after D65 opening - if ( TRUE == didTimeout( dryBiCarbSupplyStartTime, DRY_BICART_FILL_PERSISTANCE_DURATION_MS ) ) + if ( TRUE == didTimeout( dryBiCartPersistanceStartTime, DRY_BICART_FILL_PERSISTANCE_DURATION_MS ) ) { setValveState( D65_VALV, VALVE_STATE_CLOSED ); + dryBiCartPersistanceStartTime = 0; state = BICARB_CHAMBER_CHECK_LEVEL_STATE; } // Close water inlet valve as D66 pressure reaches 11 PSI. @@ -1591,15 +1634,21 @@ // Close water inlet valve as fill is complete. else if ( d66Pressure >= getDryBicartUpperCartPressure() ) { + if ( 0 == dryBiCartPersistanceStartTime ) + { + dryBiCartPersistanceStartTime = getMSTimerCount(); + } // to check the the maximum cart pressure during persistence on D66 if ( d66Pressure >= MAX_DRY_BICART_FILL_COMPLETE_PRESSURE ) { setValveState( D65_VALV, VALVE_STATE_CLOSED ); + dryBiCartPersistanceStartTime = 0; } // 200 ms persistence on D66 pressure since pressure overshoot just after D65 opening - if ( TRUE == didTimeout( dryBiCarbSupplyStartTime, DRY_BICART_FILL_PERSISTANCE_DURATION_MS ) ) + if ( TRUE == didTimeout( dryBiCartPersistanceStartTime, DRY_BICART_FILL_PERSISTANCE_DURATION_MS ) ) { setValveState( D65_VALV, VALVE_STATE_CLOSED ); + dryBiCartPersistanceStartTime = 0; } } @@ -1630,7 +1679,7 @@ { setValveState( D85_VALV, VALVE_STATE_CLOSED ); - dryBiCarbSypplyVentStartTime = getMSTimerCount(); + state = BICARB_SUPPLY_VENT_END_STATE; } @@ -2209,4 +2258,21 @@ return result; } +/*********************************************************************//** + * @brief + * The testDryBiCartMixControlIntervalOverride function sets the override value + * of mix control interval + * @details Inputs: dryBiCartMixControlInterval + * @details Outputs: dryBiCartMixControlInterval + * @param message Override message from Dialin which includes the override + * value to override the bicart lower pressure. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testDryBiCartMixControlIntervalOverride( MESSAGE_T *message ) +{ + BOOL result = u32Override( message, &dryBiCartMixControlInterval, 0, BICARB_MIX_CONTROL_INTERVAL ); + + return result; +} + /**@}*/