Index: firmware/App/Services/Reservoirs.c =================================================================== diff -u -rc7890e8beda1708d2dea0762dcc40ca5a12222e3 -rd4670b91145b97cb5a4a35dea604bff6c849c62d --- firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision c7890e8beda1708d2dea0762dcc40ca5a12222e3) +++ firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision d4670b91145b97cb5a4a35dea604bff6c849c62d) @@ -9,6 +9,7 @@ #include "DialInFlow.h" #include "MessageSupport.h" #include "ModeTreatment.h" +#include "ModeTreatmentParams.h" #include "OperationModes.h" #include "Reservoirs.h" #include "TaskGeneral.h" @@ -17,10 +18,11 @@ // ********** private definitions ********** #define RESERVOIR_SETTLE_TIME_MS 5000 ///< Allocated time to settle the filled reservoir in milliseconds. +#define RESERVOIR_CYCLE_EXTRA_MARGIN_TIME_MS 5000 ///< Reservoir extra time in during the cycle for error in milliseconds. #define MAX_RESERVOIR_VOLUME_ML 1950.0 ///< Maximum allowed fluid in a reservoir in milliliters. #define MAX_RESERVOIR_DILUTION 0.15 ///< Maximum reservoir dilution limit. -#define MAX_RESERVOIR_RECIRCULATION 0.1 ///< Maximum reservoir recirculation limit. +#define MAX_RESERVOIR_RECIRCULATION 0.5 ///< Maximum reservoir recirculation limit. TODo this used to be 10% #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. @@ -50,7 +52,7 @@ NUM_OF_TREATMENT_RESERVOIR_MGMT_STATES ///< Number of treatment reservoir management states. } TREATMENT_RESERVOIR_MGMT_STATE_T; -// TODO update the init function with all the newest variables +// TODO update the init function with all the newest variables and add the doxygen comments static TREATMENT_RESERVOIR_MGMT_STATE_T reservoirsState; ///< Treatment mode's reservoirs state. static U32 timeStartMS = 0; ///< Active reservoir start time in milliseconds. static U32 timeDepleteMS = 0; ///< Active reservoir depletion time in milliseconds. @@ -63,10 +65,12 @@ static F32 volSpentUFML = 0.0; static DG_RESERVOIR_ID_T activeReservoir; static F32 recirculationLevelPct = 0.0; -static U32 reservoirSwitchStartTime = 0; -static U32 timeFillReservoirMS = 0; -static U32 timeWaitToFillMS = 0; +static U32 reservoirSwitchStartTimeMS = 0; +static U32 timeFillReservoirMS = 0; // TODO is this needed? +static S32 timeWaitToFillMS = 0; +static F32 tempVar = 0.0; // TODO remove + // TODO set the reservoirs alarms properties in the alarmsDefs.h so the alarms will be recoverable // ********** private function prototypes ********** @@ -98,14 +102,27 @@ { // TODO don't forget to update the variables and the doxygen reservoirsState = TREATMENT_RESERVOIR_MGMT_START_STATE; - timeStartMS = 0; + timeStartMS = getMSTimerCount(); timeDepleteMS = 0; volSpentML = 0.0; reservoirPublicationCounter = 0; } /*********************************************************************//** * @brief + * The resetReservoirsVariables function resets the reservoirs variables for + * the next run. + * @details Inputs: none + * @details Outputs: timeStartMS + * @return none + *************************************************************************/ +void resetReservoirsVariables( void ) +{ + timeStartMS = getMSTimerCount(); +} + +/*********************************************************************//** + * @brief * The execReservoirs function executes the state machine for the treatment * reservoir management during treatment mode. * @details Inputs: reservoirsStatus @@ -218,7 +235,8 @@ { F32 fillFlowRate = 0.0; - F32 dialysateFlow = getDGDialysateFlowRateLMin(); + // Get the current dialysate flow rate set by the user and convert it L/min + F32 dialysateFlow = (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ) / ML_PER_LITER; if ( dialysateFlow <= DIALYSATE_FLOW_RATE_350_ML_PER_MIN ) { @@ -235,6 +253,10 @@ fillFlowRate = TGT_FILL_FLOW_FOR_DIA_FLOW_550_TO_600_ML_PER_MIN; } + // TODO remove + tempVar = fillFlowRate; + // TODO remove + return fillFlowRate; } @@ -252,9 +274,9 @@ F32 totalTargetFillFlow = targetFillFlowRate + ( targetFillFlowRate * ratios.acidMixingRatio ) + ( targetFillFlowRate * ratios.bicarbMixingRatio ); - U32 timeFillMS = ( FILL_RESERVOIR_TO_VOLUME_ML / ( ML_PER_LITER * totalTargetFillFlow ) ) * SEC_PER_MIN * MS_PER_SECOND; + U32 timeFillMS = ( FILL_RESERVOIR_TO_VOLUME_ML / ( ML_PER_LITER * totalTargetFillFlow ) ) * SEC_PER_MIN * MS_PER_SECOND; - U32 timeTotalFillMS = timeFillMS + ratios.fillPrepTimeMS; + U32 timeTotalFillMS = timeFillMS + ratios.fillPrepTimeMS; return timeTotalFillMS; } @@ -272,8 +294,16 @@ { RESERVOIRS_MANAGEMENT_DATA_T data; - data.reservoirsExecState = (U32)reservoirsState; + data.reservoirsExecState = (U32)reservoirsState; + data.activeReservoirUFVolML = volSpentUFML; + data.activeReservoirVolSpentML = volSpentML; + data.dilutionLevelPct = dilutionLevel * 100; + data.recircLevelPct = recirculationLevelPct * 100; + data.timeDepletionMS = timeDepleteMS; + data.timeWaitFillMS = timeWaitToFillMS; + data.tempRemoveTragetFillFlow = tempVar; + broadcastData( MSG_ID_HD_RESERVOIRS_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( RESERVOIRS_MANAGEMENT_DATA_T ) ); reservoirPublicationCounter = 0; @@ -339,36 +369,52 @@ { TREATMENT_RESERVOIR_MGMT_STATE_T state = TREATMENT_RESERVOIR_MGMT_WAIT_TO_FILL_STATE; + // TODo add comments + + F32 targetFillFlowRateLPM = getTargetFillFlowRateLPM(); + + volSpentUFML = getReservoirUltrafiltrationVol( activeReservoir ); + // Calculate the dilution level - dilutionLevel = volSpentML / (F32)FILL_RESERVOIR_TO_VOLUME_ML; + dilutionLevel = volSpentUFML / (F32)FILL_RESERVOIR_TO_VOLUME_ML; // 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 if ( ( dilutionLevel >= MAX_RESERVOIR_DILUTION ) || ( volSpentML >= (F32)FILL_RESERVOIR_TO_VOLUME_ML ) ) { if ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == dgSubMode ) { - cmdStartDGFill( FILL_RESERVOIR_TO_VOLUME_ML, getTargetFillFlowRateLPM() ); + cmdStartDGFill( FILL_RESERVOIR_TO_VOLUME_ML, targetFillFlowRateLPM ); } - - state = TREATMENT_RESERVOIR_MGMT_FILL_RESERVOIR_STATE; } else { F32 volFreshML = FILL_RESERVOIR_TO_VOLUME_ML - volSpentML; - F32 timeFreshRemainingMS = volFreshML / ( getDGDialysateFlowRateLMin() * 1000.0 ); + F32 timeFreshRemainingMS = ( volFreshML / (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ) ) * SEC_PER_MIN * MS_PER_SECOND; F32 volMaxUFML = FILL_RESERVOIR_TO_VOLUME_ML * MAX_RESERVOIR_DILUTION; - volSpentUFML = getReservoirUltrafiltrationVol( activeReservoir ); - F32 volRemainingUFML = volMaxUFML - volSpentUFML; - F32 timeDepleteRemainingMS = ( volRemainingUFML / getCurrentUFSetRate() ) * SEC_PER_MIN * MS_PER_SECOND; - timeDepleteMS = MIN( timeFreshRemainingMS, timeDepleteRemainingMS ); - timeWaitToFillMS = timeFillReservoirMS - reservoirSwitchStartTime; + F32 ultrafiltrationFlowMLP = getCurrentUFSetRate(); - if ( timeDepleteMS >= timeWaitToFillMS ) + if ( ultrafiltrationFlowMLP > NEARLY_ZERO ) { - cmdStartDGFill( FILL_RESERVOIR_TO_VOLUME_ML, getTargetFillFlowRateLPM() ); + F32 volRemainingUFML = volMaxUFML - volSpentUFML; + F32 timeDepleteRemainingMS = ( volRemainingUFML / ultrafiltrationFlowMLP ) * SEC_PER_MIN * MS_PER_SECOND; + timeDepleteMS = MIN( timeFreshRemainingMS, timeDepleteRemainingMS ); } + else + { + timeDepleteMS = timeFreshRemainingMS; + } + timeWaitToFillMS = timeDepleteMS - getFillTimeMS() + RESERVOIR_SETTLE_TIME_MS + RESERVOIR_CYCLE_EXTRA_MARGIN_TIME_MS; + + if ( timeWaitToFillMS <= 0 ) + { + cmdStartDGFill( FILL_RESERVOIR_TO_VOLUME_ML, targetFillFlowRateLPM ); + } + } + + if ( DG_MODE_FILL == dgOpMode ) + { state = TREATMENT_RESERVOIR_MGMT_FILL_RESERVOIR_STATE; } @@ -388,7 +434,7 @@ TREATMENT_RESERVOIR_MGMT_STATE_T state = TREATMENT_RESERVOIR_MGMT_FILL_RESERVOIR_STATE; // Check the recirculation level - recirculationLevelPct = ( (F32)FILL_RESERVOIR_TO_VOLUME_ML - volSpentML ) / (F32)FILL_RESERVOIR_TO_VOLUME_ML; + recirculationLevelPct = volSpentML / (F32)FILL_RESERVOIR_TO_VOLUME_ML; // If the recirculation level has exceeded the max allowed, raise the alarm to stop using the active reservoir as it has been // diluted to much @@ -403,7 +449,7 @@ clearAlarmCondition( ALARM_ID_HD_ACTIVE_RESERVOIR_DEPLETION_TIME_OUT ); clearAlarmCondition( ALARM_ID_HD_ACTIVE_RESERVOIR_WEIGHT_OUT_OF_RANGE ); - reservoirSwitchStartTime = getMSTimerCount(); + reservoirSwitchStartTimeMS = getMSTimerCount(); state = TREATMENT_RESERVOIR_MGMT_WAIT_FOR_FILL_SETTLE_STATE; } @@ -423,7 +469,7 @@ TREATMENT_RESERVOIR_MGMT_STATE_T state = TREATMENT_RESERVOIR_MGMT_WAIT_FOR_FILL_SETTLE_STATE; // Wait for the reservoir to settle and then send the commands to switch the active reservoir - if ( TRUE == didTimeout( reservoirSwitchStartTime, RESERVOIR_SETTLE_TIME_MS ) ) + if ( TRUE == didTimeout( reservoirSwitchStartTimeMS, RESERVOIR_SETTLE_TIME_MS ) ) { DG_RESERVOIR_ID_T inactiveRes = getDGInactiveReservoir(); @@ -442,7 +488,7 @@ timeFillReservoirMS = getFillTimeMS(); // Wait for used reservoir to settle - reservoirSwitchStartTime = getMSTimerCount(); + reservoirSwitchStartTimeMS = getMSTimerCount(); state = TREATMENT_RESERVOIR_MGMT_WAIT_FOR_SWITCH_SETTLE_STATE; } @@ -462,7 +508,7 @@ { TREATMENT_RESERVOIR_MGMT_STATE_T state = TREATMENT_RESERVOIR_MGMT_WAIT_FOR_SWITCH_SETTLE_STATE; - if ( TRUE == didTimeout( reservoirSwitchStartTime, RESERVOIR_SETTLE_TIME_MS ) ) + if ( TRUE == didTimeout( reservoirSwitchStartTimeMS, RESERVOIR_SETTLE_TIME_MS ) ) { // Signal dialysis sub-mode to capture final volume of prior reservoir after settling. setFinalReservoirVolume();