Index: firmware/App/Services/Reservoirs.c =================================================================== diff -u -r867eed1d3a71f8fac87ac6dece093a391663188a -r5addd92e279ebc0871364fee70e3ac74db21001a --- firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision 867eed1d3a71f8fac87ac6dece093a391663188a) +++ firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision 5addd92e279ebc0871364fee70e3ac74db21001a) @@ -67,6 +67,8 @@ static U32 reservoirSwitchStartTimeMS = 0; ///< Reservoir switch start time in milliseconds. static S32 timeWaitToFillMS = 0; ///< Time to wait to fill in milliseconds. static F32 targetFillFlowLPM = 0.0; ///< Target fill flow in liters/minutes. +static U32 previousDialysateFlowMLP = 0; ///< Previous dialysate flow rate in mL/min. +static F32 previousUFFlowMLP = 0.0; ///< Previous ultrafiltration flow rate in mL/min. // ********** private function prototypes ********** @@ -75,6 +77,7 @@ static void checkReservoirMaxVolume( void ); static F32 getTargetFillFlowRateLPM( void ); static U32 getFillTimeMS( void ); +static void calculateActiveReservoirCycleTime( void ); static void publishReservoirData( void ); static TREATMENT_RESERVOIR_MGMT_STATE_T handleReservoirMgmtStartState( void ); @@ -92,7 +95,8 @@ * @details Outputs: reservoirsState, timeStartMS, timeDepletionMS, volTotalMl, * volSpentMl, reservoirsPublicationCounter, dilutionLevelPct, dgOpMode, dgSubMode, * timeReservoirInUseMS, volSpentUFML, activeReservoir, recirculationLevelPct, - * reservoirSwitchStartTimeMS, timeWaitToFillMS, targetFillFlowLPM + * reservoirSwitchStartTimeMS, timeWaitToFillMS, targetFillFlowLPM, + * previousDialysateFlowRate * @return none *************************************************************************/ void initReservoirs( void ) @@ -113,6 +117,7 @@ reservoirSwitchStartTimeMS = 0; timeWaitToFillMS = 0; targetFillFlowLPM = 0.0; + previousDialysateFlowMLP = 0; } /*********************************************************************//** @@ -148,6 +153,7 @@ checkReservoirDepletionTime(); checkReservoirMaxVolume(); + calculateActiveReservoirCycleTime(); // TODO do we need this? Should we not call the reservoir management exec function in saline bolus? @@ -195,15 +201,16 @@ /*********************************************************************//** * @brief - * The getReservoirCycleTime function returns the depletion time which is the - * cycle time in milliseconds. + * The setHeatersTemperatureAndTime function is an API to call other internal + * functions to set the trimmer's heater target temperature and times that are + * required to calculated the heaters target temperature in DG. * @details Inputs: none - * @details Outputs: timeDepleteMS - * @return timeDepleteMS which is the reservoir cycle time + * @details Outputs: none + * @return none *************************************************************************/ -U32 getReservoirCycleTime( void ) +void setHeatersTemperatureAndTime( void ) { - return timeDepleteMS; + calculateActiveReservoirCycleTime(); } // ********** private functions ********** @@ -303,6 +310,51 @@ /*********************************************************************//** * @brief + * The calculateActiveReservoirCycleTime function calculates the active reservoir + * cycle time in milliseconds. If the target dialysate flow or target ultrafilter + * flow has changed the function sends the new active reservoir cycle time + * to the DG. + * @details Inputs: previousDialysateFlowMLP, previousUFFlowMLP + * @details Outputs: previousDialysateFlowMLP, previousUFFlowMLP + * @return none + *************************************************************************/ +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 targetUFFlowMLP = getCurrentUFSetRate(); + F32 timeReservoirCycleMS = fillTimeMS; + + // 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 + F32 timeUFDepletionMS = ( (F32)FILL_RESERVOIR_TO_VOLUME_ML / targetUFFlowMLP ) * SEC_PER_MIN * MS_PER_SECOND; + timeReservoirCycleMS = MIN( fillTimeMS, timeUFDepletionMS ); + } + + // If the target dialysate flow rate has changed, it means the cycle time (depletion time) has changed + // So the new value has to be sent again. + if ( ( previousDialysateFlowMLP != dialysateFlowMLP ) || ( previousUFFlowMLP != targetUFFlowMLP ) ) + { + DG_CMD_DIALYSATE_HEATING_PARAMS_T params; + params.trimmerTargetTemperature = getTreatmentParameterF32( TREATMENT_PARAM_DIALYSATE_TEMPERATURE ); + params.timeReservoirWait2SwitchMS = RESERVOIR_SETTLE_TIME_MS + RESERVOIR_CYCLE_EXTRA_MARGIN_TIME_MS; + params.timeReservoirFillMS = fillTimeMS; + params.timeReservoirCycleMS = timeReservoirCycleMS; + params.dialysateFlowLPM = dialysateFlowMLP / ML_PER_LITER; + + cmdSetDGDialysateHeatingParams( params ); + + // Update the previous dialysate flow and UF flow regardless of which one changed + // If anything of have not changed, then the update does not change anything + previousDialysateFlowMLP = dialysateFlowMLP; + previousUFFlowMLP = targetUFFlowMLP; + } +} + +/*********************************************************************//** + * @brief * The publishReservoirData function publishes reservoirs data during treatment. * @details Inputs: reservoirsPublicationCounter * @details Outputs: reservoirsPublicationCounter @@ -411,8 +463,9 @@ // Using the fresh remaining volume, time to spent the fresh remaining is calculated by dividing the volume to // target dialysate flow rate. The target dialysate flow rate is used to be able to respond to the flow changes // by the user + U32 targetDialysateFlowMLP = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); F32 volFreshML = FILL_RESERVOIR_TO_VOLUME_ML - volSpentML; - F32 timeFreshRemainingMS = ( volFreshML / (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ) ) * SEC_PER_MIN * MS_PER_SECOND; + F32 timeFreshRemainingMS = ( volFreshML / (F32)targetDialysateFlowMLP ) * SEC_PER_MIN * MS_PER_SECOND; F32 volMaxUFML = FILL_RESERVOIR_TO_VOLUME_ML * MAX_RESERVOIR_DILUTION; F32 ultrafiltrationFlowMLP = getCurrentUFSetRate();