Index: firmware/App/Controllers/PresOccl.c =================================================================== diff -u -rd608769332d4ffe19f39a18caca14d6155f13e0a -r6f5bb3935a079cf48c836b2227db430c069bac40 --- firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision d608769332d4ffe19f39a18caca14d6155f13e0a) +++ firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 6f5bb3935a079cf48c836b2227db430c069bac40) @@ -110,6 +110,8 @@ #define SIZE_OF_LONG_ART_ROLLING_AVG ( ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) * 10 ) /// Measured arterial pressure is filtered w/ 1 second moving average for inline pressure. #define SIZE_OF_SHORT_ART_ROLLING_AVG ( ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) * 1 ) +/// Measured arterial pressure is filtered w/ 10 second moving average for pressure compensation of flow. +#define SIZE_OF_LONG_VEN_ROLLING_AVG ( ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) * 10 ) /// Measured venous pressure is filtered w/ 1 second moving average for inline pressure and unfiltered for occlusion detection. #define SIZE_OF_SHORT_VEN_ROLLING_AVG ( ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) * 1 ) @@ -160,6 +162,7 @@ static U32 stabilizationStartTimeMs; ///< Timestamp taken when pressure limit stabilization began (ms). static F32 longFilteredArterialPressure; ///< Measured arterial pressure after long (10 s) filter. static F32 shortFilteredArterialPressure; ///< Measured arterial pressure after short (1 s) filter. +static F32 longFilteredVenousPressure; ///< Measured venous pressure after long (10 s) filter. static F32 shortFilteredVenousPressure; ///< Measured venous pressure after short (1 s) filter. static U32 bloodPumpOcclusionAfterCartridgeInstall; ///< Measured blood pump occlusion reading taken after cartridge install. @@ -176,10 +179,16 @@ static F32 artPressureReadingsShortTotal = 0.0; ///< Rolling total - used to calc average. static U32 artPressureReadingsShortCount = 0; ///< Number of samples in flow rolling average buffer. +static F32 venPressureReadingsLong[ SIZE_OF_LONG_VEN_ROLLING_AVG ]; ///< Holds flow samples for long venous pressure rolling average. +static U32 venPressureReadingsLongIdx = 0; ///< Index for next sample in rolling average array. +static F32 venPressureReadingsLongTotal = 0.0; ///< Rolling total - used to calc average. +static U32 venPressureReadingsLongCount = 0; ///< Number of samples in flow rolling average buffer. + static F32 venPressureReadingsShort[ SIZE_OF_SHORT_VEN_ROLLING_AVG ]; ///< Holds flow samples for long arterial pressure rolling average. static U32 venPressureReadingsShortIdx = 0; ///< Index for next sample in rolling average array. static F32 venPressureReadingsShortTotal = 0.0; ///< Rolling total - used to calc average. static U32 venPressureReadingsShortCount = 0; ///< Number of samples in flow rolling average buffer. + static PRESSURE_SELF_TEST_STATE_T presOcclPostState; ///< Pressure self test post state. static HD_PRESSURE_SENSORS_CAL_RECORD_T pressureSensorsCalRecord; ///< Pressure sensors calibration record. static HD_OCCLUSION_SENSORS_CAL_RECORD_T occlusionSensorsCalRecord; ///< Occlusion sensors calibration record. @@ -235,6 +244,7 @@ venLowPresExemptAfterAirTrapFillTimerCtr = 0; longFilteredArterialPressure = 0.0F; shortFilteredArterialPressure = 0.0F; + longFilteredVenousPressure = 0.0F; shortFilteredVenousPressure = 0.0F; presOcclDataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; presOcclState = PRESSURE_WAIT_FOR_POST_STATE; @@ -358,8 +368,8 @@ *************************************************************************/ void updatePressureLimitWindows( void ) { - F32 filtArt = getFilteredArterialPressure(); - F32 filtVen = getFilteredVenousPressure(); + F32 filtArt = getLongFilteredArterialPressure(); + F32 filtVen = getLongFilteredVenousPressure(); S32 curArtPres = FLOAT_TO_INT_WITH_ROUND( filtArt ); S32 curVenPres = FLOAT_TO_INT_WITH_ROUND( filtVen ); @@ -950,6 +960,19 @@ { return shortFilteredVenousPressure; } + +/*********************************************************************//** + * @brief + * The getLongFilteredVenousPressure function gets the current long filtered + * venous pressure. + * @details Inputs: longFilteredVenousPressure + * @details Outputs: none + * @return the current long filtered venous pressure (in mmHg). + *************************************************************************/ +F32 getLongFilteredVenousPressure( void ) +{ + return longFilteredVenousPressure; +} /*********************************************************************//** * @brief @@ -1008,6 +1031,17 @@ artPressureReadingsShortCount = INC_CAP( artPressureReadingsShortCount, SIZE_OF_SHORT_ART_ROLLING_AVG ); shortFilteredArterialPressure = artPressureReadingsShortTotal / (F32)artPressureReadingsShortCount; + // Long filter for venous pressure. + if ( venPressureReadingsLongCount >= SIZE_OF_LONG_VEN_ROLLING_AVG ) + { + venPressureReadingsLongTotal -= venPressureReadingsLong[ venPressureReadingsLongIdx ]; + } + venPressureReadingsLong[ venPressureReadingsLongIdx ] = venPres; + venPressureReadingsLongTotal += venPres; + venPressureReadingsLongIdx = INC_WRAP( venPressureReadingsLongIdx, 0, SIZE_OF_LONG_VEN_ROLLING_AVG - 1 ); + venPressureReadingsLongCount = INC_CAP( venPressureReadingsLongCount, SIZE_OF_LONG_VEN_ROLLING_AVG ); + longFilteredVenousPressure = venPressureReadingsLongTotal / (F32)venPressureReadingsLongCount; + // Short filter for venous pressure. if ( venPressureReadingsShortCount >= SIZE_OF_SHORT_VEN_ROLLING_AVG ) { @@ -1035,14 +1069,16 @@ { PRESSURE_OCCLUSION_DATA_T data; - data.arterialPressure = shortFilteredArterialPressure; - data.venousPressure = shortFilteredVenousPressure; - data.bldPumpOcclusion = getMeasuredBloodPumpOcclusion(); - data.presLimitState = currPresLimitsState; - data.artMinLimit = currentArterialMinLimit; - data.artMaxLimit = currentArterialMaxLimit; - data.venMinLimit = currentVenousMinLimit; - data.venMaxLimit = currentVenousMaxLimit; + data.arterialPressure = shortFilteredArterialPressure; + data.venousPressure = shortFilteredVenousPressure; + data.bldPumpOcclusion = getMeasuredBloodPumpOcclusion(); + data.presLimitState = currPresLimitsState; + data.artMinLimit = currentArterialMinLimit; + data.artMaxLimit = currentArterialMaxLimit; + data.venMinLimit = currentVenousMinLimit; + data.venMaxLimit = currentVenousMaxLimit; + data.arterialLongFilterPres = longFilteredArterialPressure; + data.venousLongFilterPres = longFilteredVenousPressure; broadcastData( MSG_ID_PRESSURE_OCCLUSION_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( PRESSURE_OCCLUSION_DATA_T ) ); presOcclDataPublicationTimerCounter = 0; Index: firmware/App/Controllers/PresOccl.h =================================================================== diff -u -rd608769332d4ffe19f39a18caca14d6155f13e0a -r6f5bb3935a079cf48c836b2227db430c069bac40 --- firmware/App/Controllers/PresOccl.h (.../PresOccl.h) (revision d608769332d4ffe19f39a18caca14d6155f13e0a) +++ firmware/App/Controllers/PresOccl.h (.../PresOccl.h) (revision 6f5bb3935a079cf48c836b2227db430c069bac40) @@ -71,6 +71,8 @@ S32 artMaxLimit; ///< Current arterial maximum pressure limit (mmHg) S32 venMinLimit; ///< Current venous minimum pressure limit (mmHg) S32 venMaxLimit; ///< Current venous maximum pressure limit (mmHg) + F32 arterialLongFilterPres; ///< Latest long filtered arterial pressure (mmHg) + F32 venousLongFilterPres; ///< Latest long filtered venous pressure (mmHg) } PRESSURE_OCCLUSION_DATA_T; // ********** public function prototypes ********** @@ -90,7 +92,8 @@ F32 getFilteredArterialPressure( void ); F32 getLongFilteredArterialPressure( void ); F32 getMeasuredVenousPressure( void ); -F32 getFilteredVenousPressure( void ); +F32 getFilteredVenousPressure( void ); +F32 getLongFilteredVenousPressure( void ); U32 getMeasuredBloodPumpOcclusion( void ); BOOL isCartridgeLoaded( void ); Index: firmware/App/Modes/ModeTreatment.c =================================================================== diff -u -rd608769332d4ffe19f39a18caca14d6155f13e0a -r6f5bb3935a079cf48c836b2227db430c069bac40 --- firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision d608769332d4ffe19f39a18caca14d6155f13e0a) +++ firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 6f5bb3935a079cf48c836b2227db430c069bac40) @@ -1101,6 +1101,9 @@ S32 timeDiff = 0; F32 rateDiff = 0.0; HD_OP_MODE_T currMode = getCurrentOperationMode(); + S32 txSecRem = CALC_TREAT_TIME_REMAINING_IN_SECS(); + S32 txMinEla = CALC_ELAPSED_TREAT_TIME_IN_SECS() / SEC_PER_MIN; + F32 txMinRem = (F32)txSecRem / (F32)SEC_PER_MIN; // Reset pending UF/time settings changes to current values in case request is rejected pendingUFVolumeChange = presMaxUFVolumeML; @@ -1115,9 +1118,12 @@ { DIALYSIS_STATE_T currDialysisState = getDialysisState(); UF_STATE_T currUFState = getUltrafiltrationState(); - F32 uFRate = uFVolume / ((F32)presTreatmentTimeSecs / (F32)SEC_PER_MIN); // What UF rate would be if user selected to adjust it - U32 trtTime = (S32)( uFVolume / presUFRate ) + 1; // What the treatment duration would be if user selected to adjust it - U32 dialVolume = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ) * trtTime; // What dialysate volume would be if user selected to adjust time + F32 colUFVol = getUltrafiltrationReferenceVolume(); // How much UF volume have we taken so far? + F32 remUFVol = uFVolume - colUFVol; // What would remaining UF volume be after subtracting UF volume already taken + F32 remUFVolCap = RANGE( remUFVol, 0.0F, (F32)MAX_UF_VOLUME_ML ); // Enforce valid range on remaining UF volume + F32 uFRate = remUFVolCap / txMinRem; // What UF rate would be if user selected to adjust it + U32 trtTime = ( fabs( presUFRate ) < NEARLY_ZERO ? txMinEla + 1 : (S32)( remUFVolCap / presUFRate ) + txMinEla + 1 ); // What the treatment duration would be if user selected to adjust it + U32 dialVolume = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ) * trtTime; // What dialysate volume would be if user selected to adjust time // UF should already be paused but let's make sure. if ( ( TREATMENT_DIALYSIS_STATE == currentTreatmentState ) && Index: firmware/App/Modes/Prime.c =================================================================== diff -u -rffaf9f13166d7a9beb4252fad804c488f870aaaa -r6f5bb3935a079cf48c836b2227db430c069bac40 --- firmware/App/Modes/Prime.c (.../Prime.c) (revision ffaf9f13166d7a9beb4252fad804c488f870aaaa) +++ firmware/App/Modes/Prime.c (.../Prime.c) (revision 6f5bb3935a079cf48c836b2227db430c069bac40) @@ -62,8 +62,10 @@ #define STEADY_VOLUME_COUNT_SEC ( 10000 / LOAD_CELL_STEADY_VOLUME_SAMPLING_TIME ) ///< Counter must be greater than 10 seconds before steady volume is true. #define STEADY_VOLUME_DIALYSATE_PRIME_TIME_LIMIT_MS ( 90 * MS_PER_SECOND ) ///< Time in msec for the reservoir volume to stabilize during dialysate prime state. #define STEADY_VOLUME_BYPASS_PRIME_TIME_LIMIT_MS ( 62 * MS_PER_SECOND ) ///< Time in msec for the reservoir volume to stabilize during bypass dialysate prime state. -#define STEADY_VOLUME_DIALYSATE_PRIME_HISTERESIS_ML ( 0.3F ) ///< mL of histeresis for the steady state check that determines when bypass line is primed. -#define STEADY_VOLUME_BYPASS_PRIME_HISTERESIS_ML ( 0.3F ) ///< mL of histeresis for the steady state check that determines when bypass line is primed. +#define STEADY_VOLUME_DIALYSATE_PRIME_HISTERESIS_ML 0.3F ///< mL of histeresis for the steady state check that determines when bypass line is primed. +#define STEADY_VOLUME_BYPASS_PRIME_HISTERESIS_ML 0.3F ///< mL of histeresis for the steady state check that determines when bypass line is primed. +#define PRESSURE_OFFSET_DIALYSATE_PRIME_MMHG 50.0F ///< +/- offset from start pressure that defines a range to keep PBo in during dialysate dialyzer prime state. +#define DPO_RATE_STEP_PER_SEC_DIALYSATE_PRIME_ML_MIN 1 ///< DPo rate step to maintain pressure during dialysate dialyzer prime state. #define VENOUS_PRESSURE_BUBBLE_CLEAR_MAX_MMHG ( 200.0F ) ///< Maximum venous pressure reading (in mmHg) for bubble clear. #define BUBBLE_CLEAR_WAIT_TIME_INITIAL_MS ( 10 * MS_PER_SECOND ) ///< Time in msec to wait for initial bubble clear pressure. @@ -134,6 +136,8 @@ static U32 primeSalineDialyzerStartTime; ///< Starting time of priming saline dialyzer circuit. static U32 primeSalineDialyzerBubbleClearStartTime; ///< Starting time of priming saline dialyzer bubble clear. static U32 primeDialysateDialyzerStartTime; ///< Starting time of priming dialysate dialyzer circuit. +static F32 primeDialysateDialyzerStartVenPres; ///< Starting venous pressure (mmHg) for dialysate dialyzer prime state. +static U32 primeDialysateDialyzerDPoRate; ///< Record of last given DPo target rate for dialysate dialyzer prime state. static U32 primeDialysateBypassStartTime; ///< Starting time of priming dialysate bypass circuit. static U32 steadyVolumeSamplingStartTime; ///< Load cell steady volume sampling interval starting time. static F32 minimumReservoirVolume; ///< Minimum reservoir volume in mL. @@ -726,13 +730,15 @@ signalBloodPumpHardStop(); setDialInPumpTargetFlowRate( DIALYSATE_PUMP_PRIME_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); setDialOutPumpTargetRate( DPO_PUMP_PRIME_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + primeDialysateDialyzerDPoRate = DPO_PUMP_PRIME_FLOW_RATE_ML_MIN; // Calculate the time out value that must passed prior to checking for the steady state volume in the reservoir - primeDialysateDialyzerTimeLimit = (U32)( ( ( DIALYSATE_DIALYZER_TUBE_VOLUME_ML + dialyzerDialysateVolume ) * SEC_PER_MIN * MS_PER_SECOND ) / DIALYSATE_PUMP_PRIME_FLOW_RATE_ML_MIN ); - minimumReservoirVolume = getLoadCellWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); - steadyVolumeCount = 0; - steadyVolumeSamplingStartTime = getMSTimerCount(); - primeDialysateDialyzerStartTime = getMSTimerCount(); + primeDialysateDialyzerTimeLimit = (U32)( ( ( DIALYSATE_DIALYZER_TUBE_VOLUME_ML + dialyzerDialysateVolume ) * SEC_PER_MIN * MS_PER_SECOND ) / DIALYSATE_PUMP_PRIME_FLOW_RATE_ML_MIN ); + minimumReservoirVolume = getLoadCellWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); + steadyVolumeCount = 0; + steadyVolumeSamplingStartTime = getMSTimerCount(); + primeDialysateDialyzerStartTime = getMSTimerCount(); + primeDialysateDialyzerStartVenPres = getFilteredVenousPressure(); #ifndef _RELEASE_ if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_PRIMING ) ) @@ -777,8 +783,21 @@ { if ( TRUE == didTimeout( steadyVolumeSamplingStartTime, LOAD_CELL_STEADY_VOLUME_SAMPLING_TIME ) ) { - F32 const currentReservoirVolume = getLoadCellWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); + F32 currentReservoirVolume = getLoadCellWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); + F32 venPres = getFilteredVenousPressure(); + // Adjust DPo speed to maintain venous pressure if necessary + if ( venPres > ( primeDialysateDialyzerStartVenPres + PRESSURE_OFFSET_DIALYSATE_PRIME_MMHG ) ) + { + primeDialysateDialyzerDPoRate += DPO_RATE_STEP_PER_SEC_DIALYSATE_PRIME_ML_MIN; + setDialOutPumpTargetRate( primeDialysateDialyzerDPoRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + } + else if ( venPres < ( primeDialysateDialyzerStartVenPres - PRESSURE_OFFSET_DIALYSATE_PRIME_MMHG ) ) + { + primeDialysateDialyzerDPoRate -= DPO_RATE_STEP_PER_SEC_DIALYSATE_PRIME_ML_MIN; + setDialOutPumpTargetRate( primeDialysateDialyzerDPoRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + } + if ( currentReservoirVolume >= ( minimumReservoirVolume - STEADY_VOLUME_DIALYSATE_PRIME_HISTERESIS_ML ) ) { if ( ++steadyVolumeCount >= STEADY_VOLUME_COUNT_SEC )