Index: firmware/App/Controllers/Fans.c =================================================================== diff -u -r09e6cf9de34acf18f6e1138bf56ac0edb4821186 -r284948857d8d212e25bd379fa3e7f6305fbc56e4 --- firmware/App/Controllers/Fans.c (.../Fans.c) (revision 09e6cf9de34acf18f6e1138bf56ac0edb4821186) +++ firmware/App/Controllers/Fans.c (.../Fans.c) (revision 284948857d8d212e25bd379fa3e7f6305fbc56e4) @@ -348,7 +348,7 @@ F32 maxTemperature = 0.0; - // NOTE: a for loop was not used because the venous pressure sensor's temperature + // NOTE: A for loop was not used because the venous pressure sensor's temperature // is not used as one of temperature values to decide the hottest temperature temperature = getTemperatureValue( THERMISTOR_ONBOARD_NTC ); maxTemperature = ( temperature > maxTemperature ? temperature : maxTemperature ); Index: firmware/App/Modes/ModeTreatment.c =================================================================== diff -u -r113f1633a8d944d0bdd644c9b866ed58822a14b7 -r284948857d8d212e25bd379fa3e7f6305fbc56e4 --- firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 113f1633a8d944d0bdd644c9b866ed58822a14b7) +++ firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 284948857d8d212e25bd379fa3e7f6305fbc56e4) @@ -843,7 +843,6 @@ // Otherwise execute state machine for treatment stop sub-mode else { - //execTreatmentReservoirMgmt(); TODO DEBUG_DENALI remove this later. Not now later! execReservoirs(); execTreatmentStop(); } Index: firmware/App/Services/Reservoirs.c =================================================================== diff -u -rd4670b91145b97cb5a4a35dea604bff6c849c62d -r284948857d8d212e25bd379fa3e7f6305fbc56e4 --- firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision d4670b91145b97cb5a4a35dea604bff6c849c62d) +++ firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision 284948857d8d212e25bd379fa3e7f6305fbc56e4) @@ -2,7 +2,7 @@ // TODO the copyright will be added automatically -#include +#include // For reservoir management calculations #include "DGInterface.h" #include "Dialysis.h" @@ -18,11 +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 RESERVOIR_CYCLE_EXTRA_MARGIN_TIME_MS 8000 ///< 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.5 ///< Maximum reservoir recirculation limit. TODo this used to be 10% +#define MAX_RESERVOIR_RECIRCULATION 1.1 ///< 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. @@ -52,27 +52,22 @@ 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 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. static F32 volSpentML = 0.0; ///< Active reservoir spent volume in milliliters. static U32 reservoirPublicationCounter = 0; ///< Reservoirs data publication timer counter. -static F32 dilutionLevel = 0.0; -static DG_OP_MODE_T dgOpMode = DG_MODE_INIT; -static U32 dgSubMode = 0; -static U32 timeReservoirInUseMS = 0; -static F32 volSpentUFML = 0.0; -static DG_RESERVOIR_ID_T activeReservoir; -static F32 recirculationLevelPct = 0.0; -static U32 reservoirSwitchStartTimeMS = 0; -static U32 timeFillReservoirMS = 0; // TODO is this needed? -static S32 timeWaitToFillMS = 0; +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 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. +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 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 ********** // Reservoir management functions @@ -95,17 +90,29 @@ * state machine. * @details Inputs: none * @details Outputs: reservoirsState, timeStartMS, timeDepletionMS, volTotalMl, - * volSpentMl, reservoirsPublicationCounter TODO add all the variables later + * volSpentMl, reservoirsPublicationCounter, dilutionLevelPct, dgOpMode, dgSubMode, + * timeReservoirInUseMS, volSpentUFML, activeReservoir, recirculationLevelPct, + * reservoirSwitchStartTimeMS, timeWaitToFillMS, targetFillFlowLPM * @return none *************************************************************************/ void initReservoirs( void ) { - // TODO don't forget to update the variables and the doxygen + // Initialize the variables reservoirsState = TREATMENT_RESERVOIR_MGMT_START_STATE; timeStartMS = getMSTimerCount(); timeDepleteMS = 0; volSpentML = 0.0; reservoirPublicationCounter = 0; + dilutionLevelPct = 0.0; + dgOpMode = DG_MODE_INIT; + dgSubMode = 0; + timeReservoirInUseMS = 0; + volSpentUFML = 0.0; + activeReservoir = DG_RESERVOIR_1; + recirculationLevelPct = 0.0; + reservoirSwitchStartTimeMS = 0; + timeWaitToFillMS = 0; + targetFillFlowLPM = 0.0; } /*********************************************************************//** @@ -134,6 +141,7 @@ U32 msSinceLastVolumeCalc = calcTimeSince( timeStartMS ); F32 flowRateMLPerMS = (F32)getTargetDialInFlowRate() / (F32)( MS_PER_SECOND * SEC_PER_MIN ); + // Updated the static variables activeReservoir = getDGActiveReservoir(); dgOpMode = getDGOpMode(); dgSubMode = getDGSubMode(); @@ -253,9 +261,7 @@ fillFlowRate = TGT_FILL_FLOW_FOR_DIA_FLOW_550_TO_600_ML_PER_MIN; } - // TODO remove - tempVar = fillFlowRate; - // TODO remove + targetFillFlowLPM = fillFlowRate; return fillFlowRate; } @@ -271,11 +277,12 @@ { DG_MIXING_RATIOS_T ratios = getDGMixingRatios(); F32 targetFillFlowRate = getTargetFillFlowRateLPM(); + // The target fill flow rate is RO flow rate plus acid and bicarb flow rates 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; - + // Add the prepare time in the DG mode fill to the calculated fill time in milliseconds U32 timeTotalFillMS = timeFillMS + ratios.fillPrepTimeMS; return timeTotalFillMS; @@ -297,13 +304,12 @@ data.reservoirsExecState = (U32)reservoirsState; data.activeReservoirUFVolML = volSpentUFML; data.activeReservoirVolSpentML = volSpentML; - data.dilutionLevelPct = dilutionLevel * 100; + data.dilLevelPct = dilutionLevelPct * 100; data.recircLevelPct = recirculationLevelPct * 100; data.timeDepletionMS = timeDepleteMS; data.timeWaitFillMS = timeWaitToFillMS; + data.tempRemoveTragetFillFlow = targetFillFlowLPM; - data.tempRemoveTragetFillFlow = tempVar; - broadcastData( MSG_ID_HD_RESERVOIRS_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( RESERVOIRS_MANAGEMENT_DATA_T ) ); reservoirPublicationCounter = 0; @@ -369,18 +375,17 @@ { TREATMENT_RESERVOIR_MGMT_STATE_T state = TREATMENT_RESERVOIR_MGMT_WAIT_TO_FILL_STATE; - // TODo add comments - + // Get the target fill flow rate in L/min F32 targetFillFlowRateLPM = getTargetFillFlowRateLPM(); - volSpentUFML = getReservoirUltrafiltrationVol( activeReservoir ); + // 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; - // Calculate the dilution level - 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 ( ( dilutionLevelPct >= MAX_RESERVOIR_DILUTION ) || ( volSpentML >= (F32)FILL_RESERVOIR_TO_VOLUME_ML ) ) { if ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == dgSubMode ) { @@ -389,13 +394,22 @@ } else { + // The fresh left volume in the reservoir is the nominal volume - the spent volume + // 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 F32 volFreshML = FILL_RESERVOIR_TO_VOLUME_ML - volSpentML; 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; F32 ultrafiltrationFlowMLP = getCurrentUFSetRate(); + // If the ultra-filtration volume is not 0 check the depletion time for that too if ( ultrafiltrationFlowMLP > NEARLY_ZERO ) { + // 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 + // The depletion time is then used to calculate the time to wait to fill and whether to trigger a fill command or not F32 volRemainingUFML = volMaxUFML - volSpentUFML; F32 timeDepleteRemainingMS = ( volRemainingUFML / ultrafiltrationFlowMLP ) * SEC_PER_MIN * MS_PER_SECOND; timeDepleteMS = MIN( timeFreshRemainingMS, timeDepleteRemainingMS ); @@ -405,8 +419,12 @@ timeDepleteMS = timeFreshRemainingMS; } - timeWaitToFillMS = timeDepleteMS - getFillTimeMS() + RESERVOIR_SETTLE_TIME_MS + RESERVOIR_CYCLE_EXTRA_MARGIN_TIME_MS; + // Time to wait prior to next fill is depletion time - the whole group of how much time is needed to fill a reservoir + + // the time it takes to wait for a reservoir to settle and the extra margin time for ramp up of the RO and drain pumps and + // any other extra times. + timeWaitToFillMS = timeDepleteMS - ( getFillTimeMS() + RESERVOIR_SETTLE_TIME_MS + RESERVOIR_CYCLE_EXTRA_MARGIN_TIME_MS ); + // If the wait time has elapsed, trigger a fill command if ( timeWaitToFillMS <= 0 ) { cmdStartDGFill( FILL_RESERVOIR_TO_VOLUME_ML, targetFillFlowRateLPM ); @@ -415,6 +433,10 @@ if ( DG_MODE_FILL == dgOpMode ) { + // Reset the variables for the next wait to fill cycle + timeDepleteMS = 0; + timeWaitToFillMS = 0; + state = TREATMENT_RESERVOIR_MGMT_FILL_RESERVOIR_STATE; } @@ -442,6 +464,8 @@ { 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 if ( ( DG_MODE_GENE == dgOpMode ) && ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == dgSubMode ) ) { // Clear any of the recoverable conditions in case they were raised during the fill or wait to fill @@ -485,8 +509,6 @@ // Get ready for the next delivery volSpentML = 0.0; - timeFillReservoirMS = getFillTimeMS(); - // Wait for used reservoir to settle reservoirSwitchStartTimeMS = getMSTimerCount(); Index: firmware/App/Services/Reservoirs.h =================================================================== diff -u -rd4670b91145b97cb5a4a35dea604bff6c849c62d -r284948857d8d212e25bd379fa3e7f6305fbc56e4 --- firmware/App/Services/Reservoirs.h (.../Reservoirs.h) (revision d4670b91145b97cb5a4a35dea604bff6c849c62d) +++ firmware/App/Services/Reservoirs.h (.../Reservoirs.h) (revision 284948857d8d212e25bd379fa3e7f6305fbc56e4) @@ -26,7 +26,7 @@ U32 reservoirsExecState; ///< Reservoirs exec state. F32 activeReservoirUFVolML; ///< Active reservoir ultrafiltration volume milliliters. F32 activeReservoirVolSpentML; - F32 dilutionLevelPct; + F32 dilLevelPct; F32 recircLevelPct; U32 timeDepletionMS; U32 timeWaitFillMS;