Index: firmware/App/Controllers/SyringePump.c =================================================================== diff -u -r26d736280fef713e7639cd2b98eed975e2eb4353 -r880dd112d3477bf4cbec0865126802f8a3d3f910 --- firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision 26d736280fef713e7639cd2b98eed975e2eb4353) +++ firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision 880dd112d3477bf4cbec0865126802f8a3d3f910) @@ -37,6 +37,7 @@ /// 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.402 / 2.0 ) ///< Radius from inner diameter (in cm) of supported BD syringe. /// Milliliters per mm of syringe plunger travel. @@ -82,6 +83,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_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). @@ -188,6 +190,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 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). @@ -213,6 +216,7 @@ 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. @@ -221,6 +225,7 @@ 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 ********** @@ -250,6 +255,8 @@ 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 ); @@ -291,6 +298,7 @@ syringePumpPlungerFound = FALSE; syringeVolumeAdequate = FALSE; syringePumpPrimeCompleted = FALSE; + syringePumpCheckForOcclusionFlag = FALSE; lastSyringePumpADCReadCtr = 0; @@ -522,6 +530,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 syringePumpSetRate = SYRINGE_PUMP_PRIME_RATE; syringePumpPrimeRequested = TRUE; resetHeparinVolumeDelivered(); @@ -1353,32 +1362,46 @@ rampSyringePump(); // Has prime volume been delivered? - if ( getSyringePumpVolumeDelivered() >= SYRINGE_PUMP_PRIME_VOLUME_ML ) + if ( ( getSyringePumpVolumeDelivered() >= SYRINGE_PUMP_PRIME_VOLUME_ML ) && ( FALSE == syringePumpCheckForOcclusionFlag ) ) { stopPump = TRUE; - syringePumpPrimeCompleted = 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 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 ); - // Check for occlusion - stopPump = checkOcclusionOrEmpty( stopPump ); - // Check position > max travel stopPump = checkMaxTravel( stopPump, syringePumpVolumeStartPosition + ( SYRINGE_PUMP_PRIME_VOLUME_ML * TEN_PCT_OVER_ALLOWANCE * SYRINGE_ENCODER_COUNTS_PER_ML ) ); // Check pump direction stopPump = checkDirection( stopPump, MOTOR_DIR_FORWARD ); - // If anything found that would require stopping the pump, stop pump and go to off state + // If anything found that would require stopping the pump, stop pump if ( TRUE == stopPump ) { stopSyringePump(); - result = SYRINGE_PUMP_OFF_STATE; + // result = SYRINGE_PUMP_OFF_STATE; } return result; @@ -1558,14 +1581,14 @@ { S32 pos = getSyringePumpPosition(); - if ( fabs( pos - SYRINGE_PUMP_EMPTY_POS ) < SYRINGE_PUMP_EMPTY_POS_MARGIN ) + 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 ) } else { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SYRINGE_PUMP_OCCLUSION, (F32)pos, force ) + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SYRINGE_PUMP_OCCLUSION, (F32)pos, force ) // reuse this alarm after prime } result = TRUE; } @@ -1575,6 +1598,56 @@ /*********************************************************************//** * @brief + * The checkForPrimeOcclusion 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 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 + + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_OCCLUSION, ( forceDelta >= SYRINGE_FORCE_OCCLUSION_THRESHOLD_VOLT ) ) ) + { + 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 + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @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.