Index: firmware/App/Services/Reservoirs.c =================================================================== diff -u -r5b448e81db260e5b041699a83c6f2a3faa260ea9 -rfb1673d2282822995ed233f3e9ea5dfb0567780d --- firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision 5b448e81db260e5b041699a83c6f2a3faa260ea9) +++ firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision fb1673d2282822995ed233f3e9ea5dfb0567780d) @@ -25,8 +25,9 @@ #define MAX_RESERVOIR_DILUTION 0.15F ///< Maximum reservoir dilution limit. #define MAX_RESERVOIR_RECIRCULATION 1.1F ///< Maximum reservoir recirculation limit. -#define MAX_RESERVOIR_DEPLETION_TIME_MS ( 30 * SEC_PER_MIN * MS_PER_SECOND ) ///< Maximum allowed depletion time in milliseconds. -#define RESERVOIR_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the reservoir data is published on the CAN bus. +#define MAX_RESERVOIR_DEPLETION_TIME_MS ( 30 * SEC_PER_MIN * MS_PER_SECOND ) ///< Maximum allowed depletion time in milliseconds. +#define RESERVOIR_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the reservoir data is published on the CAN bus. +#define RESERVOIR_DEPLETION_INTERVAL ( MAX_RESERVOIR_DEPLETION_TIME_MS / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) for maximum allowed depletion time. #define DIALYSATE_FLOW_RATE_350_ML_PER_MIN 0.35F ///< Dialysate flow rate 350 mL/min. #define DIALYSATE_FLOW_RATE_400_ML_PER_MIN 0.4F ///< Dialysate flow rate 400 mL/min. @@ -39,6 +40,8 @@ #define DIA_FLOW_TO_FILL_FLOW_FIRST_ORDER_COEFF 7.5F ///< Dialysate flow rate to fill flow rate first order coefficient. #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). + // ********** private data ********** /// States of the treatment reservoir management state machine. @@ -61,7 +64,7 @@ static F32 dilutionLevelPct = 0.0; ///< Reservoir dilution level. static DG_OP_MODE_T dgOpMode = DG_MODE_INIT; ///< DG operation mode. static U32 dgSubMode = 0; ///< DG operation submode. -static U32 timeReservoirInUseMS = 0; ///< Reservoir time in use in milliseconds. +static U32 timeReservoirInUse = 0; ///< Reservoir time in use in milliseconds. static F32 volSpentUFML = 0.0; ///< Ultrafiltration volume in milliliters. static DG_RESERVOIR_ID_T activeReservoir; ///< Active reservoir. static F32 recirculationLevelPct = 0.0; ///< Recirculation level in percent. @@ -103,7 +106,7 @@ * @details Inputs: none * @details Outputs: reservoirsState, timeStartMS, timeDepletionMS, volTotalMl, * volSpentMl, reservoirsPublicationCounter, dilutionLevelPct, dgOpMode, dgSubMode, - * timeReservoirInUseMS, volSpentUFML, activeReservoir, recirculationLevelPct, + * timeReservoirInUse, volSpentUFML, activeReservoir, recirculationLevelPct, * reservoirSwitchStartTimeMS, timeWaitToFillMS, targetFillFlowLPM, ratios * previousDialysateFlowRate * @return none @@ -119,7 +122,7 @@ dilutionLevelPct = 0.0; dgOpMode = DG_MODE_INIT; dgSubMode = 0; - timeReservoirInUseMS = 0; + timeReservoirInUse = 0; volSpentUFML = 0.0; activeReservoir = DG_RESERVOIR_1; recirculationLevelPct = 0.0; @@ -149,8 +152,8 @@ * @brief * The execReservoirs function executes the state machine for the treatment * reservoir management during treatment mode. - * @details Inputs: reservoirsStatus - * @details Outputs: reservoirsStatus + * @details Inputs: reservoirsState + * @details Outputs: reservoirsState, timeReservoirInUse, volSpentML * @return none *************************************************************************/ void execReservoirs( void ) @@ -168,13 +171,17 @@ checkReservoirMaxVolume(); calculateActiveReservoirCycleTime(); - // TODO do we need this? Should we not call the reservoir management exec function in saline bolus? - - // Calculate volume used from active reservoir - do not accumulate if saline bolus is in progress - if ( getSalineBolusState() != SALINE_BOLUS_STATE_IN_PROGRESS ) + // Calculate volume used from active reservoir - do not accumulate if not performing dialysis or saline bolus is in progress + if ( ( TREATMENT_DIALYSIS_STATE == getTreatmentState() ) && ( getDialysisState() != DIALYSIS_SALINE_BOLUS_STATE ) ) { volSpentML += ( flowRateMLPerMS * msSinceLastVolumeCalc ); + + if ( TREATMENT_DIALYSIS_STATE == getTreatmentState()) + { + ++timeReservoirInUse; + } } + // Update the reservoir start time timeStartMS = getMSTimerCount(); @@ -240,13 +247,13 @@ static void checkReservoirDepletionTime( void ) { // Check if the time that the reservoir has been use has exceeded the limit - if ( TRUE == didTimeout( timeReservoirInUseMS, MAX_RESERVOIR_DEPLETION_TIME_MS ) ) + if ( timeReservoirInUse >= RESERVOIR_DEPLETION_INTERVAL ) { #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_RESERVOIRS_ALARMS ) != SW_CONFIG_ENABLE_VALUE ) #endif { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_ACTIVE_RESERVOIR_DEPLETION_TIME_OUT, calcTimeSince( timeReservoirInUseMS ) ) + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_ACTIVE_RESERVOIR_DEPLETION_TIME_OUT, (timeReservoirInUse * TASK_GENERAL_INTERVAL) ) } } } @@ -515,9 +522,7 @@ timeWaitToFillMS = timeDepleteMS - ( getFillTimeMS() + RESERVOIR_SETTLE_TIME_MS + RESERVOIR_CYCLE_EXTRA_MARGIN_TIME_MS ); // If the wait time has elapsed, trigger a fill command - // TODO uncomment - //if ( timeWaitToFillMS <= 0 ) - // TODO uncomment + if ( timeWaitToFillMS <= 0 ) { cmdStartDGFill( FILL_RESERVOIR_TO_VOLUME_ML, targetFillFlowRateLPM ); } @@ -560,7 +565,6 @@ { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_ACTIVE_RESERVOIR_RECIRCULATION_OUT_OF_RANGE, recirculationLevelPct ) } - } // Check if DG has moved out of the fill mode @@ -589,10 +593,16 @@ static TREATMENT_RESERVOIR_MGMT_STATE_T handleReservoirMgmtWaitForFillSettleState( void ) { TREATMENT_RESERVOIR_MGMT_STATE_T state = TREATMENT_RESERVOIR_MGMT_WAIT_FOR_FILL_SETTLE_STATE; + DG_RESERVOIR_ID_T active = getDGActiveReservoir(); + // 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; + // Wait for the reservoir to settle and then send the commands to switch the active reservoir TODO - restore #define below if ( ( TRUE == didTimeout( reservoirSwitchStartTimeMS, 15000 /*RESERVOIR_SETTLE_TIME_MS*/ ) ) && - ( ( dilutionLevelPct >= MAX_RESERVOIR_DILUTION ) || ( volSpentML >= (F32)FILL_RESERVOIR_TO_VOLUME_ML ) ) ) + ( ( dilutionLevelPct >= MAX_RESERVOIR_DILUTION ) || ( volSpentML >= (F32)FILL_RESERVOIR_TO_VOLUME_ML ) || ( getReservoirWeight( active ) > MAX_RESERVOIR_VOL_BEFORE_SWITCH_ML ) ) ) { DG_RESERVOIR_ID_T inactiveRes = getDGInactiveReservoir(); @@ -651,7 +661,7 @@ setFinalReservoirVolume(); // Switched the active reservoir so reset the reservoir in use timer - timeReservoirInUseMS = getMSTimerCount(); + timeReservoirInUse = 0; // Reset to start state to restart drain, fill, switch process. state = TREATMENT_RESERVOIR_MGMT_START_STATE;