Index: firmware/App/Modes/Prime.c =================================================================== diff -u -rfa95951ccfc032581bd603881f2f76f17ac00b6b -rca238a4fc2400ffaf3c2a90c6e923a87b8dac4d2 --- firmware/App/Modes/Prime.c (.../Prime.c) (revision fa95951ccfc032581bd603881f2f76f17ac00b6b) +++ firmware/App/Modes/Prime.c (.../Prime.c) (revision ca238a4fc2400ffaf3c2a90c6e923a87b8dac4d2) @@ -7,8 +7,8 @@ * * @file Prime.c * -* @author (last) Michael Garthwaite -* @date (last) 14-Jun-2023 +* @author (last) Sean Nash +* @date (last) 17-Jul-2023 * * @author (original) Quang Nguyen * @date (original) 08-Dec-2020 @@ -47,8 +47,8 @@ #define BLOOD_PUMP_FAST_FLOW_RATE_CIRC_BLOOD_CIRCUIT_ML_MIN 300 ///< Blood pump fast flow rate during prime recirculate blood circuit state. #define BLOOD_PUMP_FLOW_RATE_SALINE_DIALYZER_ML_MIN 300 ///< Blood pump flow rate during prime the saline dialyzer dialysate state. #define DIALYSATE_PUMP_PRIME_FLOW_RATE_ML_MIN 300 ///< Dialysate pump flow rate during priming fluid path. -#define DIALYSATE_PUMP_FAST_PRIME_FLOW_RATE_ML_MIN 600 ///< Dialysate pump flow rate during priming fluid path. -#define DPO_PUMP_PRIME_FLOW_RATE_ML_MIN 225 ///< Dialysate outlet pump flow rate needed to match PWM with dialysate inlet pump @ 300 mL/min in open loop mode. +#define DIALYSATE_PUMP_FAST_PRIME_FLOW_RATE_ML_MIN 600 ///< Dialysate pump faster flow rate during priming fluid path. +#define DPO_PUMP_PRIME_FLOW_RATE_ML_MIN 240 ///< Dialysate outlet pump flow rate needed to match PWM with dialysate inlet pump @ 300 mL/min in open loop mode. #define DIALYSATE_DIALYZER_TUBE_VOLUME_ML 115 ///< This total tube volume is used to calculate the Dpi & Dpo time out in the dialysate dialyzer state. #define DIALYSATE_DIALYZER_BYPASS_TUBE_VOLUME_ML 75 ///< This volume is used to calculate the DPi pump time out in the dialyzer bypass state. @@ -57,13 +57,15 @@ #define NO_AIR_DETECTED_COUNT ( 40 * MS_PER_SECOND ) ///< No air detected time period count. #define PURGE_AIR_TIME_OUT_COUNT ( 240 * MS_PER_SECOND ) ///< Time period count for purge air time out. -#define PRIME_SALINE_DIALYZER_TIME_OUT_COUNT ( 60 * MS_PER_SECOND ) ///< Time period count for prime saline dialyzer time out. #define LOAD_CELL_STEADY_VOLUME_SAMPLING_TIME ( 1 * MS_PER_SECOND ) ///< Time load cell reading steady state detection sampling time in seconds. #define PRIME_DIALYSATE_BYPASS_TIME_LIMIT ( 8 * MS_PER_SECOND ) ///< Time limit for priming dialysate bypass circuit. #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 ( 55 * MS_PER_SECOND ) ///< Time in msec for the reservoir volume to stabilize during dialysate prime state. +#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_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. @@ -432,15 +436,20 @@ *************************************************************************/ static void broadcastPrimingStatus( void ) { - U32 const elapsedPrimeTimeInSecs = calcTimeSince( primeStartTime ) / MS_PER_SECOND; + U32 elapsedPrimeTimeInSecs = calcTimeSince( primeStartTime ) / MS_PER_SECOND; + // If the elapsed time is greater than the maximum prime time, it is capped to max prime time so the remaining time + // is a large number + elapsedPrimeTimeInSecs = CAP( elapsedPrimeTimeInSecs, MAX_PRIME_TIME ); + // timeout alarm that used to trigger when max prime time elapsed was removed. if ( ++primeStatusBroadcastTimerCounter >= PRIME_DATA_PUB_INTERVAL ) { PRIMING_DATA_PAYLOAD_T primeData; - primeData.totalTime = MAX_PRIME_TIME; - primeData.remainingTime = MAX_PRIME_TIME - elapsedPrimeTimeInSecs; + primeData.totalTime = MAX_PRIME_TIME; + primeData.remainingTime = MAX_PRIME_TIME - elapsedPrimeTimeInSecs; + broadcastData( MSG_ID_HD_PRIMING_STATUS_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&primeData, sizeof( PRIMING_DATA_PAYLOAD_T ) ); primeStatusBroadcastTimerCounter = 0; } @@ -726,13 +735,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 ) ) @@ -762,8 +773,10 @@ * @brief * The handlePrimeDialysateDialyzerState function handles priming for * dialysate dialyzer fluid path. - * @details Inputs: reservoir 1 filtered weight - * @details Outputs: primed dialysate dialyzer fluid path + * @details Inputs: reservoir 1 filtered weight, minimumReservoirVolume, + * steadyVolumeCount + * @details Outputs: primed dialysate dialyzer fluid path, minimumReservoirVolume, + * steadyVolumeCount * @return current state *************************************************************************/ static HD_PRE_TREATMENT_PRIME_STATE_T handlePrimeDialysateDialyzerState( void ) @@ -775,9 +788,9 @@ { 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 ); - if ( currentReservoirVolume >= minimumReservoirVolume ) + if ( currentReservoirVolume >= ( minimumReservoirVolume - STEADY_VOLUME_DIALYSATE_PRIME_HISTERESIS_ML ) ) { if ( ++steadyVolumeCount >= STEADY_VOLUME_COUNT_SEC ) { @@ -786,15 +799,30 @@ } else { - minimumReservoirVolume = currentReservoirVolume; steadyVolumeCount = 0; // required 10 seconds continuous steady volume to transition to next state } - - steadyVolumeSamplingStartTime = getMSTimerCount(); // re-armed the timer for the next dVolume/dt check + if ( currentReservoirVolume < minimumReservoirVolume ) + { + minimumReservoirVolume = currentReservoirVolume; + } } } - else + + // Adjust DPo speed to maintain venous pressure if necessary (re-using 1 sec steady volume timer to do this @ 1Hz) + if ( TRUE == didTimeout( steadyVolumeSamplingStartTime, LOAD_CELL_STEADY_VOLUME_SAMPLING_TIME ) ) { + F32 venPres = getFilteredVenousPressure(); + + 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 ); + } steadyVolumeSamplingStartTime = getMSTimerCount(); } @@ -864,11 +892,6 @@ { state = HD_PRIME_RESERVOIR_TWO_FILL_COMPLETE_STATE; } - // TODO: Rework alarm and timeout logic here. PRIME_SALINE_DIALYZER_TIME_OUT_COUNT may not be reached. - if ( TRUE == didTimeout( primeSalineDialyzerStartTime, PRIME_SALINE_DIALYZER_TIME_OUT_COUNT ) ) - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_PRIME_SALINE_DIALYZER_TIME_OUT, PRIME_SALINE_DIALYZER_TIME_OUT_COUNT ); // Trigger HD prime saline dialyzer time out alarm. - } if ( TRUE == doesAlarmStatusIndicateStop() ) {