Index: firmware/App/Controllers/SyringePump.c =================================================================== diff -u -r4efd42acbcbde896a1e9e532db77a72bebea0bdc -rbc538f960d0bc8c72991817ea52efac4775ce953 --- firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision 4efd42acbcbde896a1e9e532db77a72bebea0bdc) +++ firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision bc538f960d0bc8c72991817ea52efac4775ce953) @@ -37,7 +37,6 @@ /// Default publication interval for syringe pump data. #define SYRINGE_PUMP_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) -#define SYRINGE_PUMP_OCCLUSION_CHECK_DELAY ( 1 * MS_PER_SECOND ) ///< Delay 1 second then check for syringe pump prime occlusion. #define BD_SYRINGE_ID_RADIUS_CM ( 1.4427 / 2.0 ) ///< Radius from inner diameter (in cm) of supported BD syringe. /// Milliliters per mm of syringe plunger travel. @@ -60,10 +59,7 @@ #define MIN_HEPARIN_CONTINUOUS_RATE 0.2 ///< Minimum continuous Heparin flow rate (in mL/hr). #define MAX_HEPARIN_CONTINUOUS_RATE 1.0 ///< Maximum continuous Heparin flow rate (in mL/hr). -#define MIN_HEPARIN_BOLUS_RATE 1.2 ///< Minimum Heparin bolus flow rate (in mL/hr). -#define MAX_HEPARIN_BOLUS_RATE 24.0 ///< Maximum Heparin bolus flow rate (in mL/hr). -#define HEPARIN_BOLUS_TIME_HR ( 5.0 / MIN_PER_HOUR ) ///< Duration (in hours) of Heparin bolus. -#define HEPARIN_BOLUS_TARGET_RATE_ML_PER_HR 40.0 ///< Heparin bolus target rate (in mL/hr). +#define HEPARIN_BOLUS_TARGET_RATE 40.0 ///< Heparin bolus target rate (in ml/hr); #define SYRINGE_PUMP_RETRACT_RATE 3600.0 ///< Retract rate is 5 mL/ 5 s = 1 mL/s = 3,600 mL/hr. #define SYRINGE_PUMP_SEEK_RATE 3600.0 ///< Seek plunger rate is 5 mL/ 5 s = 1 mL/s = 3,600 mL/hr. #define SYRINGE_PUMP_PRIME_RATE 635.0 ///< Prime rate is 0.5 mm ^ 2 x PI x 450 mm = 0.353 mL / 2s = 635 mL/hr. @@ -83,7 +79,7 @@ #define SYRINGE_PUMP_DAC_FULL_SCALE_BITS 4096.0 ///< Syringe pump DAC has has 4096 full scale counts (12-bit). #define SYRINGE_FORCE_OCCLUSION_THRESHOLD_V 3.2 ///< Force sensor threshold (in V) above which an occlusion is detected. -#define SYRINGE_FORCE_OCCLUSION_THRESHOLD_VOLT 0.5 ///< Force sensor threshold (in V) above which an occlusion is detected. +#define SYRINGE_FORCE_OCCLUSION_DIFF_V 0.5 ///< Force sensor difference (in V) which an occlusion alarm is triggered. #define SYRINGE_FORCE_PLUNGER_THRESHOLD_V 0.25 ///< Force sensor threshold (in V) above which we have engaged with plunger. #define SYRINGE_PUMP_SYRINGE_DETECT_THRESHOLD_V 2.0 ///< Syringe pump syringe detected threshold (in V). #define SYRINGE_PUMP_HOME_DETECT_THRESHOLD_V 0.25 ///< Syringe pump home detected threshold (in V). @@ -93,7 +89,7 @@ #define TEN_PCT_OVER_ALLOWANCE 1.1 ///< Allow 10 percent over target before alarming on over travel. #define FIVE_PCT_OVER_ALLOWANCE 1.05 ///< Allow 5 percent over target before alarming on over travel. -/// Expected position of empty in relation to home postion. +/// Expected position of empty in relation to home position. #define SYRINGE_PUMP_EMPTY_POS ( SYRINGE_ENCODER_COUNTS_PER_ML * 10.84 ) /// Margin of error for empty position determination. #define SYRINGE_PUMP_EMPTY_POS_MARGIN ( SYRINGE_ENCODER_COUNTS_PER_ML * 0.5 ) @@ -190,7 +186,7 @@ static OVERRIDE_U32_T syringePumpADCReadCtr = {0, 0, 0, 0}; ///< Syringe pump ADC read counter reported by FPGA. static F32 syringePumpSetRate; ///< Set rate for syringe pump (in mL/hr). -static F32 forceAtStartOfPriming; ///< Force sensor reading in Volts at the start of the priming operation. +static F32 forceAtEndOfSeek; ///< Force sensor reading in Volts at the end of seek. static U32 syringePumpSetToggleTime; ///< Set rate for syringe pump (in uSec/toggle). static U32 syringePumpRampUpToggleTime; ///< Current ramp rate for syringe pump (in uSec/toggle). static F32 syringePumpSafetyVolumeDelivered; ///< Calculated volume (in mL) (from set rate over time). @@ -216,7 +212,6 @@ static BOOL syringePumpPlungerFound; ///< Flag indicates plunger was found. static BOOL syringeVolumeAdequate; ///< Flag indicates whether Heparin volume is sufficient to complete treatment. static BOOL syringePumpPrimeCompleted; ///< Flag indicates prime operation was completed. -static BOOL syringePumpCheckForOcclusionFlag; ///< Flag indicates it is time to check for prime occlusion. static BOOL syringePumpDACVrefWriteInProgress; ///< Flag indicates DAC Vref write is in progress. static F32 syringePumpDACVref; ///< DAC Vref setting for force sensor. @@ -225,7 +220,6 @@ static U32 syringePumpStallCtr; ///< Counts time when position is not changing during ramp. static U32 syringePumpStallRetryCount; ///< Counts pump ramp up stall retries. -static U32 syringeOcclusionDelayStartTime; ///< Used to calculate the 1 second delay time before check for prime occlusion. static HD_HEPARIN_FORCE_SENSOR_CAL_RECORD_T forceSensorCalRecord; ///< HD heparin force sensor calibration record. // ********** private function prototypes ********** @@ -255,8 +249,6 @@ static void calcSafetyVolumeDelivered( void ); static BOOL checkDirection( BOOL stopPump, MOTOR_DIR_T expDir ); static BOOL checkOcclusionOrEmpty( BOOL stopPump ); -static BOOL checkForPrimeOcclusion( BOOL stopPump ); -static BOOL checkForPrimeEmpty( BOOL stopPump ); static BOOL checkSyringeRemoved( BOOL stopPump ); static BOOL checkMaxTravel( BOOL stopPump, S32 maxPos ); static BOOL checkMeasRate( BOOL stopPump, F32 pctMargin ); @@ -298,7 +290,6 @@ syringePumpPlungerFound = FALSE; syringeVolumeAdequate = FALSE; syringePumpPrimeCompleted = FALSE; - syringePumpCheckForOcclusionFlag = FALSE; lastSyringePumpADCReadCtr = 0; @@ -530,7 +521,7 @@ if ( ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) && ( TRUE == isSyringeDetected() ) && ( heparinDeliveryState != HEPARIN_STATE_OFF ) && ( TRUE == syringePumpPlungerFound ) ) { - forceAtStartOfPriming = getSyringePumpForceV(); // Get the force sensor reading when syringe pump prime has been requested + forceAtEndOfSeek = getSyringePumpForceV(); // Get the force sensor reading when syringe pump prime has been requested (after seek) syringePumpSetRate = SYRINGE_PUMP_PRIME_RATE; syringePumpPrimeRequested = TRUE; resetHeparinVolumeDelivered(); @@ -563,10 +554,10 @@ *************************************************************************/ BOOL startHeparinBolus( void ) { - F32 tgtRate = HEPARIN_BOLUS_TARGET_RATE_ML_PER_HR; // fixed rate + F32 tgtRate = HEPARIN_BOLUS_TARGET_RATE; // fixed rate // If valid to start a bolus, kick it off - if ( ( tgtRate >= MIN_HEPARIN_BOLUS_RATE ) && ( tgtRate <= MAX_HEPARIN_BOLUS_RATE ) && ( FALSE == isSyringePumpHome() ) ) + if ( FALSE == isSyringePumpHome() ) { if ( ( TRUE == isSyringeDetected() ) && ( TRUE == syringePumpPrimeCompleted ) && ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) && ( HEPARIN_STATE_STOPPED == heparinDeliveryState ) ) @@ -1313,7 +1304,7 @@ F32 contRate = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_DISPENSE_RATE ); U32 preStop = getTreatmentParameterU32( TREATMENT_PARAM_HEPARIN_PRE_STOP_TIME ); U32 setTxDur = getTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION ); - F32 hepDurHr = ( (F32)( setTxDur - preStop ) / (F32)MIN_PER_HOUR ) - HEPARIN_BOLUS_TIME_HR; + F32 hepDurHr = ( (F32)( setTxDur - preStop ) / (F32)MIN_PER_HOUR ); F32 txVolume = SYRINGE_PUMP_PRIME_VOLUME_ML + bolusVol + ( hepDurHr * contRate ); F32 syringeVol = ( SYRINGE_PUMP_EMPTY_POS - (F32)pos ) / SYRINGE_ENCODER_COUNTS_PER_ML; @@ -1324,14 +1315,14 @@ if ( ( getSyringePumpForceV() >= SYRINGE_FORCE_PLUNGER_THRESHOLD_V ) || ( syringeVol < txVolume ) ) { stopPump = TRUE; - syringePumpPlungerFound = TRUE; syringePumpVolumeDelivered.data = 0.0; syringePumpSafetyVolumeDelivered = 0.0; syringePumpVolumeStartPosition = pos; // Check estimated syringe volume needed for treatment vs. volume detected - if insufficient for treatment needs, alarm if ( syringeVol >= txVolume ) { + syringePumpPlungerFound = TRUE; syringeVolumeAdequate = TRUE; } else @@ -1378,32 +1369,15 @@ rampSyringePump(); // Has prime volume been delivered? - if ( ( getSyringePumpVolumeDelivered() >= SYRINGE_PUMP_PRIME_VOLUME_ML ) && ( FALSE == syringePumpCheckForOcclusionFlag ) ) + if ( getSyringePumpVolumeDelivered() >= SYRINGE_PUMP_PRIME_VOLUME_ML ) { stopPump = TRUE; - // syringePumpPrimeCompleted = TRUE; - syringePumpCheckForOcclusionFlag = TRUE; // It is time to check for prime occlusion - syringeOcclusionDelayStartTime = getMSTimerCount(); // Get the current time to check for occlusion after 1 second has elapsed + syringePumpPrimeCompleted = TRUE; syringePumpVolumeDelivered.data = 0.0; syringePumpSafetyVolumeDelivered = 0.0; syringePumpVolumeStartPosition = syringePumpPosition.data; } - // When syringe pump has primed, wait for 1 second then check for occlusion before declaring syringe pump prime is completed - if( TRUE == syringePumpCheckForOcclusionFlag ) - { - if ( TRUE == didTimeout( syringeOcclusionDelayStartTime, SYRINGE_PUMP_OCCLUSION_CHECK_DELAY ) ) - { - stopPump = checkForPrimeOcclusion( stopPump ); - syringePumpPrimeCompleted = TRUE; - syringePumpCheckForOcclusionFlag = FALSE; - result = SYRINGE_PUMP_OFF_STATE; // Move to off state when check for occlusion is completed - } - } - - // Is the syringe pump empty? - stopPump = checkForPrimeEmpty( stopPump ); - // Has syringe been removed? stopPump = checkSyringeRemoved( stopPump ); @@ -1417,7 +1391,7 @@ if ( TRUE == stopPump ) { stopSyringePump(); - // result = SYRINGE_PUMP_OFF_STATE; + result = SYRINGE_PUMP_OFF_STATE; } return result; @@ -1622,16 +1596,16 @@ * @param stopPump flag passed in by caller indicating whether pump should be stopped * @return TRUE if pump should be stopped, FALSE if not *************************************************************************/ -static BOOL checkForPrimeOcclusion( BOOL stopPump ) +BOOL checkForPrimeOcclusion( BOOL stopPump ) { BOOL result = stopPump; - F32 forceAtEndOfPriming = getSyringePumpForceV(); // Read the force sensor at the end of the priming - F32 forceDelta = forceAtEndOfPriming - forceAtStartOfPriming; // Occlusion is detected if force at end is > than force at begin by ~ 0.5 volts + F32 forceAtEndOfPriming = getSyringePumpForceV(); // Read the force sensor at the end of the priming + F32 forceDelta = forceAtEndOfPriming - forceAtEndOfSeek; // Occlusion is detected if force at end of prime is > than force at end of seek by ~ 0.5 volts - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_OCCLUSION, ( forceDelta >= SYRINGE_FORCE_OCCLUSION_THRESHOLD_VOLT ) ) ) + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_OCCLUSION, ( forceDelta >= SYRINGE_FORCE_OCCLUSION_DIFF_V ) ) ) { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SYRINGE_PUMP_OCCLUSION, forceAtStartOfPriming, forceAtEndOfPriming ) // reuse this alarm after prime - forceAtStartOfPriming = 0.0; // reset this value in case we want to prime again + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SYRINGE_PUMP_OCCLUSION, forceAtEndOfSeek, forceAtEndOfPriming ) // reuse this alarm after prime + forceAtEndOfSeek = 0.0; // reset this value in case we want to prime again result = TRUE; } @@ -1640,31 +1614,6 @@ /*********************************************************************//** * @brief - * The checkForPrimeEmpty function checks the force sensor for excessive - * pressure. Would indicate occlusion or jam or empty syringe. - * @details Inputs: syringePumpMeasForce.data, syringePumpPosition.data - * @details Outputs: alarm triggered if max force detected - * @param stopPump flag passed in by caller indicating whether pump should be stopped - * @return TRUE if pump should be stopped, FALSE if not - *************************************************************************/ -static BOOL checkForPrimeEmpty( BOOL stopPump ) -{ - BOOL result = stopPump; - F32 force = getSyringePumpForceV(); - S32 pos = getSyringePumpPosition(); - - if ( fabs( pos - SYRINGE_PUMP_EMPTY_POS ) < SYRINGE_PUMP_EMPTY_POS_MARGIN ) - { - heparinDeliveryState = HEPARIN_STATE_EMPTY; - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SYRINGE_PUMP_SYRINGE_EMPTY, (F32)pos, force ) - result = TRUE; - } - - return result; -} - -/*********************************************************************//** - * @brief * The checkSyringeRemoved function checks whether the syringe has been removed. * This function should only be called from states that require the syringe to * be installed. Index: firmware/App/Controllers/SyringePump.h =================================================================== diff -u -r4efd42acbcbde896a1e9e532db77a72bebea0bdc -rbc538f960d0bc8c72991817ea52efac4775ce953 --- firmware/App/Controllers/SyringePump.h (.../SyringePump.h) (revision 4efd42acbcbde896a1e9e532db77a72bebea0bdc) +++ firmware/App/Controllers/SyringePump.h (.../SyringePump.h) (revision bc538f960d0bc8c72991817ea52efac4775ce953) @@ -84,6 +84,7 @@ BOOL retractSyringePump( void ); BOOL seekSyringePlunger( void ); BOOL primeSyringePump( void ); +BOOL checkForPrimeOcclusion( BOOL stopPump ); void resetHeparinVolumeDelivered( void ); BOOL startHeparinBolus( void ); BOOL startHeparinContinuous( void ); Index: firmware/App/Modes/SelfTests.c =================================================================== diff -u -r4efd42acbcbde896a1e9e532db77a72bebea0bdc -rbc538f960d0bc8c72991817ea52efac4775ce953 --- firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision 4efd42acbcbde896a1e9e532db77a72bebea0bdc) +++ firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision bc538f960d0bc8c72991817ea52efac4775ce953) @@ -41,6 +41,7 @@ #define PUMP_RUN_SELF_TEST_TIME_MS ( 15 * MS_PER_SECOND ) ///< Self-test time to run pumps in ms. #define PUMP_SELF_TEST_FLOW_RATE_ML_MIN 100 ///< Self-test pump flow rate in mL/min. +#define SYRINGE_PUMP_OCCLUSION_CHECK_DELAY ( 1 * MS_PER_SECOND ) ///< Delay 1 second then check for syringe pump prime occlusion. #define BLOOD_PUMP_RUN_TIME_PRESSURE_SELF_TEST ( 5 * MS_PER_SECOND ) ///< Pressure self-test time to run blood pump in ms. #define NORMALIZED_PRESSURE_SELF_TEST_TIME ( 4 * MS_PER_SECOND ) ///< Time to wait for pressure to normalize in ms. @@ -112,6 +113,7 @@ static U32 selfTestStartTime; ///< Starting time of self-test (in ms). static U32 selfTestPreviousPublishDataTime; ///< Last time self-test time data is being published (in ms). +static U32 syringeOcclusionDelayStartTime; ///< Used to calculate the 1 second delay time before check for prime occlusion. static BOOL useHeparin; ///< Flag indicates the user of heparin. @@ -135,6 +137,7 @@ static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsState( SELF_TEST_STATUS_T *result ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestPressureSensorsNormalState( SELF_TEST_STATUS_T *result ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestSyringePumpPrimeState( void ); +static DRY_SELF_TESTS_STATE_T handleDrySelfTestSyringePumpOcclusionDetectionState( void ); static DRY_SELF_TESTS_STATE_T handleDrySelfTestStoppedState( void ); static WET_SELF_TESTS_STATE_T handleWetSelfTestStartState( void ); @@ -422,6 +425,10 @@ currentDrySelfTestsState = handleDrySelfTestSyringePumpPrimeState(); break; + case DRY_SELF_TESTS_SYRINGE_PUMP_OCCLUSION_DETECTION_STATE: + currentDrySelfTestsState = handleDrySelfTestSyringePumpOcclusionDetectionState(); + break; + case DRY_SELF_TESTS_STOPPED_STATE: currentDrySelfTestsState = handleDrySelfTestStoppedState(); break; @@ -486,7 +493,6 @@ *************************************************************************/ void transitionToWetSelfTests() { - F32 bolusVol = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ); signalDialInPumpHardStop(); // turn off DPi that was on in previous dialysate bypass state wetSelfTestsResult = FALSE; currentWetSelfTestsState = WET_SELF_TESTS_START_STATE; @@ -497,11 +503,6 @@ selfTestStartTime = getMSTimerCount(); selfTestPreviousPublishDataTime = getMSTimerCount(); - if ( ( bolusVol > 0.0 ) && ( getSyringePumpVolumeDelivered() < bolusVol ) ) - { - startHeparinBolus(); // moved here from startHeparinPump() in Dialysis.c - } - resetSelfTestsFlags(); } @@ -985,7 +986,8 @@ { if ( TRUE == isSyringePumpPrimed() ) { - state = DRY_SELF_TESTS_COMPLETE_STATE; + state = DRY_SELF_TESTS_SYRINGE_PUMP_OCCLUSION_DETECTION_STATE; + syringeOcclusionDelayStartTime = getMSTimerCount(); // Get the current time to check for occlusion after 1 second has elapsed } else { @@ -1021,6 +1023,28 @@ /*********************************************************************//** * @brief + * The handleDrySelfTestSyringePumpPrimeState function handles the prime + * operation for syringe pump. + * @details Inputs: none + * @details Outputs: none + * @return the next state of dry self-tests state machine + *************************************************************************/ +static DRY_SELF_TESTS_STATE_T handleDrySelfTestSyringePumpOcclusionDetectionState( void ) +{ + DRY_SELF_TESTS_STATE_T state = DRY_SELF_TESTS_SYRINGE_PUMP_OCCLUSION_DETECTION_STATE; + BOOL stopPump = FALSE; + + if ( TRUE == didTimeout( syringeOcclusionDelayStartTime, SYRINGE_PUMP_OCCLUSION_CHECK_DELAY ) ) + { + stopPump = checkForPrimeOcclusion( stopPump ); + state = DRY_SELF_TESTS_COMPLETE_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief * The handleDrySelfTestStoppedState function handles the stopped dry self-tests * operation. * @details Inputs: none @@ -1086,8 +1110,16 @@ if ( FALSE == cmdResp.rejected ) { + F32 bolusVol = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ); + setDialInPumpTargetFlowRate( DIP_FLOW_RATE_SETUP_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); fmdIntegratedVolume = 0.0; + + if ( ( bolusVol > 0.0 ) && ( getSyringePumpVolumeDelivered() < bolusVol ) ) + { + startHeparinBolus(); // moved here from startHeparinPump() in Dialysis.c + } + state = WET_SELF_TESTS_SETUP_STATE; } } Index: firmware/source/sys_selftest.c =================================================================== diff -u -r26d736280fef713e7639cd2b98eed975e2eb4353 -rbc538f960d0bc8c72991817ea52efac4775ce953 --- firmware/source/sys_selftest.c (.../sys_selftest.c) (revision 26d736280fef713e7639cd2b98eed975e2eb4353) +++ firmware/source/sys_selftest.c (.../sys_selftest.c) (revision bc538f960d0bc8c72991817ea52efac4775ce953) @@ -43,16 +43,14 @@ /* USER CODE BEGIN (0) */ -/* USER CODE END */ - #include "Common.h" #include "HDDefs.h" #include "SystemCommMessages.h" +/* USER CODE END */ #include "sys_selftest.h" #include "sys_core.h" #include "sys_pmu.h" - /** @fn void selftestFailNotification(uint32 flag) * @brief Self test fail service routine * @@ -1128,7 +1126,6 @@ *(volatile uint32_t*)( &marker + LR_OFFSET_WORD_IN_STACK ) = contentOfLinkRegister + LR_OFFSET_ADJUSTMENT; SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, (U32)SW_FAULT_ID_ILLEGAL_MEM_ACCESS, contentOfLinkRegister ) // log LR to determine what caused violation /* USER CODE END */ - } /** @fn void stcSelfCheckFail(void) Index: firmware/source/sys_startup.c =================================================================== diff -u -r65280b3e6fda421cc2130e7e73f41e9fd23b51c9 -rbc538f960d0bc8c72991817ea52efac4775ce953 --- firmware/source/sys_startup.c (.../sys_startup.c) (revision 65280b3e6fda421cc2130e7e73f41e9fd23b51c9) +++ firmware/source/sys_startup.c (.../sys_startup.c) (revision bc538f960d0bc8c72991817ea52efac4775ce953) @@ -158,7 +158,7 @@ handlePLLLockFail(); } /* clear all reset status flags */ - // SYS_EXCEPTION = 0xFFFFU; commented out for testing in handlePOSTStateStart() + SYS_EXCEPTION = 0xFFFFU; /* USER CODE BEGIN (13) */ /* USER CODE END */