Index: firmware/App/Services/Reservoirs.c =================================================================== diff -u -rd611c5eeaee076a6fbf79cf94f80fff05fd5d9a9 -rd33b56765d3eeb3853eb84697d05c8a91441e00f --- firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision d611c5eeaee076a6fbf79cf94f80fff05fd5d9a9) +++ firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision d33b56765d3eeb3853eb84697d05c8a91441e00f) @@ -58,6 +58,7 @@ #define DIA_FLOW_TO_FILL_FLOW_CONSTANT 2.0F ///< Dialysate flow rate to fill flow rate constant. #define MAX_RESERVOIR_VOL_BEFORE_SWITCH_ML 1900.0F ///< Maximum reservoir volume before we switch reservoirs (in mL). +#define FILL_VOLUME_INTERCEPT_ML_QD_ABOVE_400_MLPM 1100 ///< Fill volume intercept in milliliters for Qd above 400 mL/min. // ********** private data ********** @@ -106,6 +107,7 @@ static F32 getReservoirRecirculationMaxPercent( void ); static void publishReservoirData( void ); static BOOL isDialysateTempAlarmActive( void ); +static U32 getTargetFillVolumeBasedOnDialysateFlowML( void ); static TREATMENT_RESERVOIR_MGMT_STATE_T handleReservoirMgmtStartState( void ); static TREATMENT_RESERVOIR_MGMT_STATE_T handleReservoirMgmtDrainState( void ); @@ -194,7 +196,7 @@ volSpentML += ( flowRateMLPerMS * msSinceLastVolumeCalc ); timeReservoirInUse++; // Check the recirculation level - recirculationLevelPct = volSpentML / (F32)FILL_RESERVOIR_TO_VOLUME_ML; + recirculationLevelPct = volSpentML / (F32)getTargetFillVolumeBasedOnDialysateFlowML(); } // Update the reservoir start time @@ -314,7 +316,7 @@ F32 totalTargetFillFlow = targetFillFlowRate + ( targetFillFlowRate * ratios.acidMixingRatio ) + ( targetFillFlowRate * ratios.bicarbMixingRatio ); // Time fill = Fill volume / Qfill. Qfill is converted from L/min to mL/min and the time is converted from minutes to milliseconds - U32 timeFillMS = ( FILL_RESERVOIR_TO_VOLUME_ML / ( ML_PER_LITER * totalTargetFillFlow ) ) * SEC_PER_MIN * MS_PER_SECOND; + U32 timeFillMS = ( getTargetFillVolumeBasedOnDialysateFlowML() / ( ML_PER_LITER * totalTargetFillFlow ) ) * SEC_PER_MIN * MS_PER_SECOND; // Add the prepare time in the DG mode fill to the calculated fill time in milliseconds U32 timeTotalFillMS = timeFillMS + ratios.timeFillPrepMS; @@ -334,21 +336,21 @@ static void calculateActiveReservoirCycleTime( void ) { U32 dialysateFlowMLP = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); - F32 fillTimeMS = ( (F32)FILL_RESERVOIR_TO_VOLUME_ML / ( getTargetFillFlowRateLPM() * ML_PER_LITER ) ) * SEC_PER_MIN * MS_PER_SECOND; + F32 fillTimeMS = ( (F32)getTargetFillVolumeBasedOnDialysateFlowML() / ( getTargetFillFlowRateLPM() * ML_PER_LITER ) ) * SEC_PER_MIN * MS_PER_SECOND; F32 targetUFFlowMLP = getCurrentUFSetRate(); - F32 timeDepletionMS = ( (F32)FILL_RESERVOIR_TO_VOLUME_ML / dialysateFlowMLP ) * SEC_PER_MIN * MS_PER_SECOND; + F32 timeDepletionMS = ( (F32)getTargetFillVolumeBasedOnDialysateFlowML() / dialysateFlowMLP ) * SEC_PER_MIN * MS_PER_SECOND; F32 timeTotalCycleMS = fillTimeMS + RESERVOIR_FRESH_SETTLE_TIME_MS + RESERVOIR_CYCLE_EXTRA_MARGIN_TIME_MS + ratios.timeFillPrepMS; F32 timeReservoirCycleMS = 0.0F; F32 timeUFDepletionMS = NEARLY_INFINITY; - F32 volFreshML = FILL_RESERVOIR_TO_VOLUME_ML - volSpentML; + F32 volFreshML = getTargetFillVolumeBasedOnDialysateFlowML() - volSpentML; F32 timeFreshRemainingMS = ( volFreshML / (F32)dialysateFlowMLP ) * SEC_PER_MIN * MS_PER_SECOND; - F32 volMaxUFML = FILL_RESERVOIR_TO_VOLUME_ML * MAX_RESERVOIR_DILUTION; + F32 volMaxUFML = getTargetFillVolumeBasedOnDialysateFlowML() * MAX_RESERVOIR_DILUTION; // Check if target UF flow is not zero to consider it in the calculations too if ( targetUFFlowMLP > NEARLY_ZERO ) { // If UF is not 0, the active reservoir cycle time is minimum of UF depletion and fill time - timeUFDepletionMS = ( ( (F32)FILL_RESERVOIR_TO_VOLUME_ML * RESERVOIR_DILUTION_RATIO ) / targetUFFlowMLP ) * SEC_PER_MIN * MS_PER_SECOND; + timeUFDepletionMS = ( ( (F32)getTargetFillVolumeBasedOnDialysateFlowML() * RESERVOIR_DILUTION_RATIO ) / targetUFFlowMLP ) * SEC_PER_MIN * MS_PER_SECOND; // Calculate the ultra-filtration remaining volume // Using the ultra-filtration remaining volume and the ultra-filtration target flow rate calculate the time // The depletion time in milliseconds is the minimum time of the fresh remaining time and the depletion remaining time @@ -518,24 +520,24 @@ // Get the ultra-filtration volume milliliters // Get the dilution level in percent = spent ultra-filtration volume / target fill volume in milliliters volSpentUFML = getReservoirUltrafiltrationVol( activeReservoir ); - dilutionLevelPct = volSpentUFML / (F32)FILL_RESERVOIR_TO_VOLUME_ML; + dilutionLevelPct = volSpentUFML / (F32)getTargetFillVolumeBasedOnDialysateFlowML(); // Check if the dilution level has exceeded the limit or the spent volume is more than the amount of volume in the reservoir // If it has, trigger the fill command. This if should not happen and the predictive dilution level should trigger just in time // in advance - if ( ( dilutionLevelPct >= MAX_RESERVOIR_DILUTION ) || ( volSpentML >= (F32)FILL_RESERVOIR_TO_VOLUME_ML ) ) + if ( ( dilutionLevelPct >= MAX_RESERVOIR_DILUTION ) || ( volSpentML >= (F32)getTargetFillVolumeBasedOnDialysateFlowML() ) ) { if ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == dgSubMode ) { - cmdStartDGFill( FILL_RESERVOIR_TO_VOLUME_ML, targetFillFlowRateLPM ); + cmdStartDGFill( getTargetFillVolumeBasedOnDialysateFlowML(), targetFillFlowRateLPM ); } } // If we have active dialysate temp alarms, we want to fill immediately. else if ( TRUE == isDialysateTempAlarmActive() ) { if ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == dgSubMode ) { - cmdStartDGFill( FILL_RESERVOIR_TO_VOLUME_ML, targetFillFlowRateLPM ); + cmdStartDGFill( getTargetFillVolumeBasedOnDialysateFlowML(), targetFillFlowRateLPM ); } } else @@ -548,7 +550,7 @@ // If the wait time has elapsed, trigger a fill command if ( timeWaitToFillMS <= 0 ) { - cmdStartDGFill( FILL_RESERVOIR_TO_VOLUME_ML, targetFillFlowRateLPM ); + cmdStartDGFill( getTargetFillVolumeBasedOnDialysateFlowML(), targetFillFlowRateLPM ); } } @@ -618,11 +620,11 @@ // Get the ultra-filtration volume milliliters // Get the dilution level in percent = spent ultra-filtration volume / target fill volume in milliliters volSpentUFML = getReservoirUltrafiltrationVol( activeReservoir ); - dilutionLevelPct = volSpentUFML / (F32)FILL_RESERVOIR_TO_VOLUME_ML; + dilutionLevelPct = volSpentUFML / (F32)getTargetFillVolumeBasedOnDialysateFlowML(); // Wait for the reservoir to settle and then send the commands to switch the active reservoir if ( ( TRUE == didTimeout( reservoirSwitchStartTimeMS, RESERVOIR_FRESH_SETTLE_TIME_MS ) ) && - ( ( dilutionLevelPct >= MAX_RESERVOIR_DILUTION ) || ( volSpentML >= (F32)FILL_RESERVOIR_TO_VOLUME_ML ) || ( TRUE == isDialysateTempAlarmActive() ) ) ) + ( ( dilutionLevelPct >= MAX_RESERVOIR_DILUTION ) || ( volSpentML >= (F32)getTargetFillVolumeBasedOnDialysateFlowML() ) || ( TRUE == isDialysateTempAlarmActive() ) ) ) { DG_SWITCH_RSRVRS_CMD_T rsrvrCmd; @@ -703,4 +705,25 @@ return result; } +/*********************************************************************//** + * @brief + * The getTargetFillVolumeBasedOnDialysateFlowML function calculates the + * target fill volume in milliliters. + * @details Inputs: none + * @details Outputs: none + * @return Fill target volume in milliliters + *************************************************************************/ +static U32 getTargetFillVolumeBasedOnDialysateFlowML( void ) +{ + U32 targetFillVolumeML = FILL_RESERVOIR_TO_VOLUME_ML; + U32 dialysateFlowMLP = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); + + if ( dialysateFlowMLP >= RESERVOIR_FLOW_400_MLP ) + { + targetFillVolumeML = dialysateFlowMLP + FILL_VOLUME_INTERCEPT_ML_QD_ABOVE_400_MLPM; + } + + return targetFillVolumeML; +} + /**@}*/