Index: firmware/App/Modes/Prime.c =================================================================== diff -u -ree1d1669c5438e67f1ef6bae3d8591373754f289 -r64f6bd52b1c84609e1920810b32722f0ce4f4e60 --- firmware/App/Modes/Prime.c (.../Prime.c) (revision ee1d1669c5438e67f1ef6bae3d8591373754f289) +++ firmware/App/Modes/Prime.c (.../Prime.c) (revision 64f6bd52b1c84609e1920810b32722f0ce4f4e60) @@ -7,8 +7,8 @@ * * @file Prime.c * -* @author (last) Dara Navaei -* @date (last) 12-Jul-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. @@ -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. @@ -731,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 ) ) @@ -782,7 +788,7 @@ { 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 - STEADY_VOLUME_DIALYSATE_PRIME_HISTERESIS_ML ) ) { @@ -799,12 +805,24 @@ { minimumReservoirVolume = currentReservoirVolume; } - - steadyVolumeSamplingStartTime = getMSTimerCount(); // re-armed the timer for the next dVolume/dt check } } - 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(); } Index: firmware/App/Modes/SelfTests.c =================================================================== diff -u -ree1d1669c5438e67f1ef6bae3d8591373754f289 -r64f6bd52b1c84609e1920810b32722f0ce4f4e60 --- firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision ee1d1669c5438e67f1ef6bae3d8591373754f289) +++ firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision 64f6bd52b1c84609e1920810b32722f0ce4f4e60) @@ -7,8 +7,8 @@ * * @file SelfTests.c * -* @author (last) Dara Navaei -* @date (last) 13-Jul-2023 +* @author (last) Sean Nash +* @date (last) 20-Jul-2023 * * @author (original) Quang Nguyen * @date (original) 28-Jan-2021 @@ -133,6 +133,7 @@ static BOOL useHeparin; ///< Flag indicates the user of heparin. static BOOL selfTestsResumeRequested; ///< Flag indicates user requesting self-tests resume. static BOOL cartridgeUsedTestRun; ///< Flag indicates whether the used cartridge test has been run. +static BOOL occlusionBaselineWasSet; ///< Flag indicates whether the blood pump occlusion baseline for installed cartridge has been set. static BOOL doorStateAfterCartridgeInstall; ///< Flag indicates state of front door for saline clamp check after cartridge installed. // ********** private function prototypes ********** @@ -246,6 +247,7 @@ setValvePosition( VDO, VALVE_POSITION_A_INSERT_EJECT ); setValvePosition( VBA, VALVE_POSITION_A_INSERT_EJECT ); setValvePosition( VBV, VALVE_POSITION_A_INSERT_EJECT ); + setValveAirTrap( STATE_CLOSED ); } /*********************************************************************//** @@ -426,6 +428,7 @@ previousNormalVenousPressure = 0.0; dryPressureTestsCompleted = FALSE; cartridgeUsedTestRun = FALSE; + occlusionBaselineWasSet = FALSE; selfTestStartTime = getMSTimerCount(); selfTestPreviousPublishDataTime = getMSTimerCount(); selfTestCartridgeSettleTime = getMSTimerCount(); @@ -960,6 +963,7 @@ if ( TRUE == didTimeout( selfTestCartridgeSettleTime, CARTRIDGE_INSERT_PRESSURE_SETTLE_TIME_MS ) ) { setOcclusionInstallLevel(); // Record occlusion pressure level after a new cartridge is installed + occlusionBaselineWasSet = TRUE; doorClosedRequired( TRUE, TRUE ); state = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; } @@ -1000,7 +1004,7 @@ setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); setValvePosition( VBA, VALVE_POSITION_B_OPEN ); - setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBV, VALVE_POSITION_A_INSERT_EJECT ); } if ( TRUE == doesAlarmStatusIndicateStop() ) @@ -1031,6 +1035,7 @@ ( AIR_TRAP_LEVEL_AIR == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_LOWER ) ) && ( AIR_TRAP_LEVEL_AIR == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_UPPER ) ) ) { + resetArtVenPressureOffsets(); state = DRY_SELF_TESTS_CARTRIDGE_LOADED_CHECK_STATE; } else @@ -1071,10 +1076,11 @@ if ( SELF_TEST_STATUS_PASSED == execPresOcclDryTest() ) { + setArtVenPressureOffsets(); setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); - setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); - setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBA, VALVE_POSITION_B_OPEN ); // need open path from PBA to VBT + setValvePosition( VBV, VALVE_POSITION_A_INSERT_EJECT ); // need open path from PBA to VBT setValveAirTrap( STATE_OPEN ); pressureSelfTestPreNormalStartTime = getMSTimerCount(); state = DRY_SELF_TESTS_PRESSURE_SENSORS_NORMAL_SETUP_STATE; @@ -1088,6 +1094,10 @@ if ( TRUE == doesAlarmStatusIndicateStop() ) { + if ( TRUE == isAlarmActive( ALARM_ID_HD_NO_CARTRIDGE_LOADED ) ) + { + occlusionBaselineWasSet = FALSE; // need to get baseline again after cartridge installed properly + } state = DRY_SELF_TESTS_STOPPED_STATE; setupForSelfTestsStop(); } @@ -1399,8 +1409,8 @@ } // After VBT opened, start looking to see if pressures normalize - if ( ( STATE_OPEN == getValveAirTrapStatus() ) && ( arterialPressureDiff <= NORMAL_PRESSURE_DIFF_TOLERANCE_MMHG ) && - ( venousPressureDiff <= NORMAL_PRESSURE_DIFF_TOLERANCE_MMHG ) ) + if ( ( STATE_OPEN == getValveAirTrapStatus() ) && + ( arterialPressureDiff <= NORMAL_PRESSURE_DIFF_TOLERANCE_MMHG ) && ( venousPressureDiff <= NORMAL_PRESSURE_DIFF_TOLERANCE_MMHG ) ) { dryPressureTestsCompleted = TRUE; state = DRY_SELF_TESTS_SYRINGE_PUMP_PRIME_STATE; @@ -1509,7 +1519,8 @@ * @brief * The handleDrySelfTestStoppedState function handles the stopped dry self-tests * operation. - * @details Inputs: selfTestsResumeRequested + * @details Inputs: selfTestsResumeRequested, occlusionBaselineWasSet, + * dryPressureTestsCompleted, cartridgeUsedTestRun * @details Outputs: selfTestsResumeRequested, selfTestStartTime, selfTestCartridgeSettleTime * @return the next state of dry self-tests state machine *************************************************************************/ @@ -1544,10 +1555,10 @@ selfTestStartTime = getMSTimerCount(); selfTestsResumeRequested = FALSE; selfTestCartridgeSettleTime = getMSTimerCount(); + doorClosedRequired( TRUE, TRUE ); if ( TRUE == dryPressureTestsCompleted ) { - doorClosedRequired( TRUE, TRUE ); state = DRY_SELF_TESTS_SYRINGE_PUMP_PRIME_STATE; } else @@ -1556,8 +1567,15 @@ setValvePosition( VBA, VALVE_POSITION_B_OPEN ); if ( TRUE == cartridgeUsedTestRun ) { + doorClosedRequired( TRUE, TRUE ); + resetArtVenPressureOffsets(); state = DRY_SELF_TESTS_CARTRIDGE_LOADED_CHECK_STATE; } + else if ( occlusionBaselineWasSet != TRUE ) + { + selfTestCartridgeSettleTime = getMSTimerCount(); + state = DRY_SELF_TESTS_START_STATE; + } else { state = DRY_SELF_TESTS_WAIT_FOR_DOOR_CLOSE_STATE; @@ -1702,7 +1720,7 @@ { signalDialInPumpHardStop(); - if ( getMeasuredDialInFlowRate() <= NEARLY_ZERO ) + if ( getMeasuredDialInPumpSpeed() <= NEARLY_ZERO ) { if ( TRUE == zeroBloodLeak() ) {