Index: firmware/App/Controllers/SyringePump.c =================================================================== diff -u -rfaaa80bfef7fdcfea8c03163db14c83300d64a23 -r4e312ba52d5baaace2aa2ae171143be651862300 --- firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision faaa80bfef7fdcfea8c03163db14c83300d64a23) +++ firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision 4e312ba52d5baaace2aa2ae171143be651862300) @@ -67,11 +67,11 @@ #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. #define SYRINGE_PUMP_MAX_RATE 11000.0 ///< Maximum rate of the syringe pump (in mL/hr). -#define SYRINGE_PUMP_RATE_ALARM_PERSISTENCE ( MS_PER_SECOND * 3 / TASK_PRIORITY_INTERVAL ) ///< Alarm persistence period for syringe pump speed check alarms. -#define SYRINGE_PUMP_DIR_ALARM_PERSISTENCE ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Alarm persistence period for syringe pump direction check alarms. -#define SYRINGE_PUMP_OFF_ALARM_PERSISTENCE ( 500 / TASK_PRIORITY_INTERVAL ) ///< Alarm persistence period for syringe pump off check alarms. -#define SYRINGE_PUMP_OCCLUSION_ALARM_PERSISTENCE ( 30 / TASK_PRIORITY_INTERVAL ) ///< Alarm persistence period for syringe pump occlusion alarms. -#define SYRINGE_PUMP_ADC_READ_PERSISTENCE ( 100 / TASK_PRIORITY_INTERVAL ) ///< Syringe pump ADC stale read alarm persistence time (100 ms). +#define SYRINGE_PUMP_RATE_ALARM_PERSISTENCE 3000 ///< Alarm persistence period (in ms) for syringe pump speed check alarms. +#define SYRINGE_PUMP_DIR_ALARM_PERSISTENCE 1000 ///< Alarm persistence period (in ms) for syringe pump direction check alarms. +#define SYRINGE_PUMP_OFF_ALARM_PERSISTENCE 500 ///< Alarm persistence period (in ms) for syringe pump off check alarms. +#define SYRINGE_PUMP_OCCLUSION_ALARM_PERSISTENCE 30 ///< Alarm persistence period (in ms) for syringe pump occlusion alarms. +#define SYRINGE_PUMP_ADC_READ_PERSISTENCE 100 ///< Syringe pump ADC stale read alarm persistence time (in ms). #define STEPS_TO_MICROSTEPS( s ) ( (s) * 32.0 ) ///< Macro conversion from steps to microsteps. #define MICROSTEPS_TO_STEPS( m ) ( (m) / 32.0 ) ///< Macro conversion from microsteps to steps. @@ -98,7 +98,7 @@ #define SYRINGE_PUMP_RETRACT_POS_MIN ( SYRINGE_ENCODER_COUNTS_PER_ML * -0.5 ) #define SYRINGE_PUMP_START_RAMP_SPEED 300000 ///< Starting speed for all syringe pump operations to ramp up from. -#define SYRINGE_PUMP_RAMP_DIVISOR 5 ///< Used for ramping profile. +#define SYRINGE_PUMP_RAMP_DIVISOR 15 ///< Used for ramping profile. #define SYRINGE_PUMP_RATE_CHECK_MARGIN 0.05 ///< 5 pct margin on commanded vs. measured rate check. #define SYRINGE_PUMP_VOLUME_CHECK_MARGIN 0.05 ///< 5 pct margin on commanded vs. encoder based volume check. @@ -143,6 +143,10 @@ #define SYRINGE_PUMP_ENCODER_DIRECTION_ERROR_BITS 0x3F ///< Syringe pump encoder direction error counter bits in FPGA register. #define SYRINGE_PUMP_ENCODER_DIRECTION_BIT 0x80 ///< Syringe pump encoder direction bit in FPGA register. +#define SYRINGE_PUMP_RAMP_STALL_TIME ( 1500 / TASK_PRIORITY_INTERVAL ) ///< Syringe pump ramp stall timeout. +#define SYRINGE_PUMP_RAMP_STALL_RETRIES 3 ///< Syringe pump ramp stall retries allowed. +#define SYRINGE_PUMP_STALL_SPEED_THRESHOLD 0.05 ///< Minimum syringe pump speed to be considered not stalled. + /// Defined states for the syringe pump control state machine. typedef enum SyringePump_States { @@ -167,12 +171,16 @@ /// Interval (in ms) at which to publish syringe pump data to CAN bus. static OVERRIDE_U32_T syringePumpDataPublishInterval = { SYRINGE_PUMP_DATA_PUB_INTERVAL, SYRINGE_PUMP_DATA_PUB_INTERVAL, 0, 0 }; -static OVERRIDE_F32_T syringePumpMeasRate = {0.0, 0.0, 0.0, 0 }; ///< Measured rate for syringe pump (in mL/hr). -static OVERRIDE_F32_T syringePumpMeasForce = {0.0, 0.0, 0.0, 0 }; ///< Measured driver force (in V). -static OVERRIDE_F32_T syringePumpMeasSyringeDetectionSwitch = {0, 0, 0, 0 }; ///< Measured syringe detect switch (in V). -static OVERRIDE_F32_T syringePumpMeasHome = {0.0, 0.0, 0.0, 0 }; ///< Measured optical home (in V). -static OVERRIDE_S32_T syringePumpPosition = {0, 0, 0, 0 }; ///< Encoder based position (in steps). -static OVERRIDE_F32_T syringePumpVolumeDelivered = {0.0, 0.0, 0.0, 0 }; ///< Measured volume delivered (in mL). +static OVERRIDE_F32_T syringePumpMeasRate = { 0.0, 0.0, 0.0, 0 }; ///< Measured rate for syringe pump (in mL/hr). +static OVERRIDE_F32_T syringePumpMeasForce = { 0.0, 0.0, 0.0, 0 }; ///< Measured driver force (in V). +static OVERRIDE_F32_T syringePumpMeasSyringeDetectionSwitch = { 0, 0, 0, 0 }; ///< Measured syringe detect switch (in V). +static OVERRIDE_F32_T syringePumpMeasHome = { 0.0, 0.0, 0.0, 0 }; ///< Measured optical home (in V). +static OVERRIDE_S32_T syringePumpPosition = { 0, 0, 0, 0 }; ///< Encoder based position (in steps). +static OVERRIDE_F32_T syringePumpVolumeDelivered = { 0.0, 0.0, 0.0, 0 }; ///< Measured volume delivered (in mL). +static OVERRIDE_U32_T syringePumpStatus = {0, 0, 0, 0}; ///< Syringe pump status reported by FPGA. +static OVERRIDE_U32_T syringePumpEncoderStatus = {0, 0, 0, 0}; ///< Syringe pump encoder status reported by FPGA. +static OVERRIDE_U32_T syringePumpADCandDACStatus = {0, 0, 0, 0}; ///< Syringe pump ADC and DAC status reported by FPGA. +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 U32 syringePumpSetToggleTime; ///< Set rate for syringe pump (in uSec/toggle). @@ -201,14 +209,10 @@ static F32 syringePumpDACVref; ///< DAC Vref setting for force sensor. static U08 lastSyringePumpADCReadCtr; ///< Remember last ADC read counter to check new reads are fresh. -static U32 syringePumpADCReadErrorCtr; ///< Stale ADC read error persistence timer counter. -static U32 syringePumpEncoderDirectionErrorCtr; ///< Encoder direction error persistence timer counter. -static U32 syringePumpControllerDirectionErrorCtr; ///< Controller direction error persistence timer counter. -static U32 syringePumpRunningWhileBPOffErrorCtr; ///< Pump running while BP off error persistence timer counter. -static U32 syringePumpRunningWhileOffErrorCtr; ///< Pump running while in off state error persistence timer counter. -static U32 syringePumpRateErrorCtr; ///< Pump rate error persistence timer counter. -static U32 syringePumpOcclusionErrorCtr; ///< Pump occlusion error persistence timer counter. +static U32 syringePumpStallCtr; ///< Counts time when position is not changing during ramp. +static U32 syringePumpStallRetryCount; ///< Counts pump ramp up stall retries. + // ********** private function prototypes ********** static void resetSyringePumpRequestFlags( void ); @@ -219,6 +223,10 @@ static F32 getSyringePumpSyringeDetectorV( void ); static F32 getSyringePumpHomeDetectorV( void ); static F32 getSyringePumpForceV( void ); +static U08 getSyringePumpStatus( void ); +static U08 getSyringePumpEncoderStatus( void ); +static U08 getSyringePumpADCReadCounter( void ); +static U08 getSyringePumpADCandDACStatus( void ); static SYRINGE_PUMP_STATE_T handleSyringePumpInitState( void ); static SYRINGE_PUMP_STATE_T handleSyringePumpOffState( void ); static SYRINGE_PUMP_STATE_T handleSyringePumpRetractState( void ); @@ -271,14 +279,19 @@ syringePumpPrimeCompleted = FALSE; lastSyringePumpADCReadCtr = 0; - syringePumpADCReadErrorCtr = 0; - syringePumpEncoderDirectionErrorCtr = 0; - syringePumpControllerDirectionErrorCtr = 0; - syringePumpRunningWhileBPOffErrorCtr = 0; - syringePumpRunningWhileOffErrorCtr = 0; - syringePumpRateErrorCtr = 0; - syringePumpOcclusionErrorCtr = 0; + syringePumpStallCtr = 0; + syringePumpStallRetryCount = 0; + + // Initialize persistent alarms + initPersistentAlarm( ALARM_ID_HD_SYRINGE_PUMP_ADC_ERROR, 0, SYRINGE_PUMP_ADC_READ_PERSISTENCE ); + initPersistentAlarm( ALARM_ID_HD_SYRINGE_PUMP_ENCODER_DIRECTION_ERROR, 0, SYRINGE_PUMP_DIR_ALARM_PERSISTENCE ); + initPersistentAlarm( ALARM_ID_HD_SYRINGE_PUMP_CONTROLLER_DIRECTION_ERROR, 0, SYRINGE_PUMP_DIR_ALARM_PERSISTENCE ); + initPersistentAlarm( ALARM_ID_HD_SYRINGE_PUMP_RUNNING_WHILE_BP_OFF_ERROR, 0, SYRINGE_PUMP_OFF_ALARM_PERSISTENCE ); + initPersistentAlarm( ALARM_ID_HD_SYRINGE_PUMP_NOT_STOPPED_ERROR, 0, SYRINGE_PUMP_OFF_ALARM_PERSISTENCE ); + initPersistentAlarm( ALARM_ID_HD_SYRINGE_PUMP_SPEED_ERROR, 0, SYRINGE_PUMP_RATE_ALARM_PERSISTENCE ); + initPersistentAlarm( ALARM_ID_HD_SYRINGE_PUMP_OCCLUSION, 0, SYRINGE_PUMP_OCCLUSION_ALARM_PERSISTENCE ); + // Reset request flags resetSyringePumpRequestFlags(); } @@ -488,6 +501,10 @@ { syringePumpSetRate = SYRINGE_PUMP_PRIME_RATE; syringePumpPrimeRequested = TRUE; + // Reset volume and start pos before starting prime operation + syringePumpVolumeDelivered.data = 0.0; + syringePumpSafetyVolumeDelivered = 0.0; + syringePumpVolumeStartPosition = getSyringePumpPosition(); } return syringePumpPrimeRequested; @@ -515,6 +532,10 @@ { syringePumpSetRate = tgtRate; syringePumpBolusRequested = TRUE; + // Reset volume and start pos before starting bolus operation + syringePumpVolumeDelivered.data = 0.0; + syringePumpSafetyVolumeDelivered = 0.0; + syringePumpVolumeStartPosition = getSyringePumpPosition(); } } else @@ -724,6 +745,85 @@ /*********************************************************************//** * @brief + * The getSyringePumpStatus function gets the current syringe pump status. + * @details Inputs: syringePumpStatus + * @details Outputs: none + * @return the current syringe pump status. + *************************************************************************/ +static U08 getSyringePumpStatus() +{ + U08 result = (U08)(syringePumpStatus.data & MASK_OFF_U32_MSBS); + + if ( OVERRIDE_KEY == syringePumpStatus.override ) + { + result = (U08)(syringePumpStatus.ovData & MASK_OFF_U32_MSBS); + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getSyringePumpEncoderStatus function gets the current syringe pump + * encoder status. + * @details Inputs: syringePumpEncoderStatus + * @details Outputs: none + * @return the current syringe pump encoder status. + *************************************************************************/ +static U08 getSyringePumpEncoderStatus() +{ + U08 result = (U08)(syringePumpEncoderStatus.data & MASK_OFF_U32_MSBS); + + if ( OVERRIDE_KEY == syringePumpEncoderStatus.override ) + { + result = (U08)(syringePumpEncoderStatus.ovData & MASK_OFF_U32_MSBS); + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getSyringePumpADCReadCounter function gets the current syringe pump + * ADC read counter. + * @details Inputs: syringePumpADCReadCtr + * @details Outputs: none + * @return the current syringe pump ADC read counter. + *************************************************************************/ +static U08 getSyringePumpADCReadCounter() +{ + U08 result = (U08)(syringePumpADCReadCtr.data & MASK_OFF_U32_MSBS); + + if ( OVERRIDE_KEY == syringePumpADCReadCtr.override ) + { + result = (U08)(syringePumpADCReadCtr.ovData & MASK_OFF_U32_MSBS); + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getSyringePumpADCandDACStatus function gets the current syringe pump + * ADC and DAC status reported by the FPGA. + * @details Inputs: syringePumpADCandDACStatus + * @details Outputs: none + * @return the current syringe pump ADC and DAC status. + *************************************************************************/ +static U08 getSyringePumpADCandDACStatus() +{ + U08 result = (U08)(syringePumpADCandDACStatus.data & MASK_OFF_U32_MSBS); + + if ( OVERRIDE_KEY == syringePumpADCandDACStatus.override ) + { + result = (U08)(syringePumpADCandDACStatus.ovData & MASK_OFF_U32_MSBS); + } + + return result; +} + +/*********************************************************************//** + * @brief * The isSyringeDetected function determines whether a syringe is currently * detected. * @details Inputs: syringePumpMeasSyringeDetectionSwitch @@ -832,10 +932,13 @@ static void execSyringePumpMonitor( void ) { S32 encPosition = getFPGASyringePumpEncoderPosition(); - U08 pmpStatus = getFPGASyringePumpStatus(); - U08 encStatus = getFPGASyringePumpEncoderStatus(); - U08 adcReadCtr = getFPGASyringePumpADCReadCounter(); + // Get latest FPGA status + syringePumpStatus.data = (U32)getFPGASyringePumpStatus(); + syringePumpEncoderStatus.data = (U32)getFPGASyringePumpEncoderStatus(); + syringePumpADCandDACStatus.data = (U32)getFPGASyringePumpADCandDACStatus(); + syringePumpADCReadCtr.data = (U32)getFPGASyringePumpADCReadCounter(); + // Get latest ADC data and convert to V syringePumpMeasHome.data = ( (F32)getFPGASyringePumpADCChannel2() * SYRINGE_PUMP_ADC_REF_V ) / SYRINGE_PUMP_ADC_FULL_SCALE_BITS; syringePumpMeasSyringeDetectionSwitch.data = ( (F32)getFPGASyringePumpADCChannel1() * SYRINGE_PUMP_ADC_REF_V ) / SYRINGE_PUMP_ADC_FULL_SCALE_BITS; @@ -849,46 +952,36 @@ // Calculate measured rate (mL/hr) calcMeasRate(); // Get measured direction - syringePumpControllerMeasuredDirection = ( ( encStatus & SYRINGE_PUMP_ENCODER_DIRECTION_BIT ) != 0 ? MOTOR_DIR_REVERSE : MOTOR_DIR_FORWARD ); + syringePumpControllerMeasuredDirection = ( ( getSyringePumpEncoderStatus() & SYRINGE_PUMP_ENCODER_DIRECTION_BIT ) != 0 ? MOTOR_DIR_REVERSE : MOTOR_DIR_FORWARD ); // Calculate direction from encoder position relative to last syringePumpEncoderMeasuredDirection = ( getSyringePumpPosition() - syringePumpLastPosition >= 0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); // Check if syringe pump is on while BP is off - if ( ( ( SYRINGE_PUMP_HEP_BOLUS_STATE == syringePumpState ) || ( SYRINGE_PUMP_HEP_CONTINUOUS_STATE == syringePumpState ) ) && - ( isBloodPumpRunning() != TRUE ) ) { - if ( ++syringePumpRunningWhileBPOffErrorCtr > SYRINGE_PUMP_OFF_ALARM_PERSISTENCE ) + BOOL runWhileOff = ( ( ( SYRINGE_PUMP_HEP_BOLUS_STATE == syringePumpState ) || ( SYRINGE_PUMP_HEP_CONTINUOUS_STATE == syringePumpState ) ) && + ( isBloodPumpRunning() != TRUE ) ); + + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_RUNNING_WHILE_BP_OFF_ERROR, runWhileOff ) ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_SYRINGE_PUMP_RUNNING_WHILE_BP_OFF_ERROR, (U32)syringePumpState ); } } - else - { - syringePumpRunningWhileBPOffErrorCtr = 0; - } if ( syringePumpDACVrefWriteInProgress != TRUE ) { -#ifndef USING_DEBUGGER // Check ADC read is fresh (takes FPGA a while to configure ADC so don't check until after init/POST mode - if ( ( getCurrentOperationMode() > MODE_INIT ) && ( lastSyringePumpADCReadCtr == adcReadCtr ) ) + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_ADC_ERROR, + ( ( getCurrentOperationMode() > MODE_INIT ) && ( lastSyringePumpADCReadCtr == getSyringePumpADCReadCounter() ) ) ) ) { - if ( ++syringePumpADCReadErrorCtr > SYRINGE_PUMP_ADC_READ_PERSISTENCE ) - { - activateAlarmNoData( ALARM_ID_HD_SYRINGE_PUMP_ADC_ERROR ); - } +// activateAlarmNoData( ALARM_ID_HD_SYRINGE_PUMP_ADC_ERROR ); } - else - { - syringePumpADCReadErrorCtr = 0; - } -#endif - lastSyringePumpADCReadCtr = adcReadCtr; + lastSyringePumpADCReadCtr = getSyringePumpADCReadCounter(); + // Check pump status - if ( pmpStatus != 0 ) + if ( getSyringePumpStatus() != 0 ) { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_SYRINGE_PUMP_FAULT, (U32)pmpStatus ); + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_SYRINGE_PUMP_FAULT, (U32)getSyringePumpStatus() ); } } } @@ -986,18 +1079,11 @@ SYRINGE_PUMP_STATE_T result = SYRINGE_PUMP_OFF_STATE; // Check position is not changing while stopped - if ( syringePumpLastPosition != getSyringePumpPosition() ) + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_NOT_STOPPED_ERROR, ( syringePumpLastPosition != getSyringePumpPosition() ) ) ) { - if ( ++syringePumpRunningWhileOffErrorCtr > SYRINGE_PUMP_OFF_ALARM_PERSISTENCE ) - { activateAlarmNoData( ALARM_ID_HD_SYRINGE_PUMP_NOT_STOPPED_ERROR ); activateSafetyShutdown(); - } } - else - { - syringePumpRunningWhileOffErrorCtr = 0; - } // Check for request flags if ( TRUE == syringePumpRetractRequested ) @@ -1069,6 +1155,30 @@ SYRINGE_PUMP_STATE_T result = SYRINGE_PUMP_RETRACT_STATE; BOOL stopPump = FALSE; + // Check for stall + if ( getSyringePumpMeasRate() < SYRINGE_PUMP_STALL_SPEED_THRESHOLD ) + { + if ( ++syringePumpStallCtr > SYRINGE_PUMP_RAMP_STALL_TIME ) + { + if ( ++syringePumpStallRetryCount <= SYRINGE_PUMP_RAMP_STALL_RETRIES ) + { + syringePumpSetToggleTime++; // lower target rate + syringePumpRampTimerCtr = 0; // restart ramp + syringePumpRampUpToggleTime = SYRINGE_PUMP_START_RAMP_SPEED; + syringePumpStallCtr = 0; // reset stall counter + } + else + { + stopPump = TRUE; + // TODO - stall alarm? + } + } + } + else + { + syringePumpStallCtr = 0; + } + // Handle ramp up rampSyringePump(); @@ -1158,9 +1268,6 @@ // Has syringe been removed? stopPump = checkSyringeRemoved( stopPump ); - // Check for occlusion - stopPump = checkOcclusionOrEmpty( stopPump ); - // Check max position > empty + 0.5 mL stopPump = checkMaxTravel( stopPump, SYRINGE_PUMP_EMPTY_POS + SYRINGE_PUMP_EMPTY_POS_MARGIN ); @@ -1331,10 +1438,10 @@ static SYRINGE_PUMP_STATE_T handleSyringePumpCalibrateForceSensorState( void ) { SYRINGE_PUMP_STATE_T result = SYRINGE_PUMP_CONFIG_FORCE_SENSOR_STATE; - U08 adcDACStatus= getFPGASyringePumpADCandDACStatus(); + U08 adcDACStatus= getSyringePumpADCandDACStatus(); // Wait for DAC setting write to EEPROM to complete - if ( ( getFPGASyringePumpADCandDACStatus() & SYRINGE_PUMP_ADC_DAC_ERROR_COUNT_DAC_WR_DONE ) != 0 ) + if ( ( adcDACStatus & SYRINGE_PUMP_ADC_DAC_ERROR_COUNT_DAC_WR_DONE ) != 0 ) { syringePumpDACVrefWriteInProgress = FALSE; // Switch back from DAC to ADC control @@ -1365,26 +1472,16 @@ { BOOL result = stopPump; - if ( syringePumpEncoderMeasuredDirection != expDir ) + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_ENCODER_DIRECTION_ERROR, ( syringePumpEncoderMeasuredDirection != expDir ) ) ) { - if ( ++syringePumpEncoderDirectionErrorCtr > SYRINGE_PUMP_DIR_ALARM_PERSISTENCE ) - { - result = TRUE; - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SYRINGE_PUMP_ENCODER_DIRECTION_ERROR, (U32)syringePumpEncoderMeasuredDirection, (U32)syringePumpState ); - } + result = TRUE; + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SYRINGE_PUMP_ENCODER_DIRECTION_ERROR, (U32)syringePumpEncoderMeasuredDirection, (U32)syringePumpState ); } - else if ( syringePumpControllerMeasuredDirection != expDir ) + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_CONTROLLER_DIRECTION_ERROR, ( syringePumpControllerMeasuredDirection != expDir ) ) ) { - if ( ++syringePumpControllerDirectionErrorCtr > SYRINGE_PUMP_DIR_ALARM_PERSISTENCE ) - { - result = TRUE; - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SYRINGE_PUMP_CONTROLLER_DIRECTION_ERROR, (U32)syringePumpControllerMeasuredDirection, (U32)syringePumpState ); - } + result = TRUE; + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SYRINGE_PUMP_CONTROLLER_DIRECTION_ERROR, (U32)syringePumpControllerMeasuredDirection, (U32)syringePumpState ); } - else - { - syringePumpControllerDirectionErrorCtr = 0; - } return result; } @@ -1403,28 +1500,21 @@ BOOL result = stopPump; F32 force = getSyringePumpForceV(); - if ( force >= SYRINGE_FORCE_OCCLUSION_THRESHOLD_V ) + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_OCCLUSION, ( force >= SYRINGE_FORCE_OCCLUSION_THRESHOLD_V ) ) ) { - if ( ++syringePumpOcclusionErrorCtr > SYRINGE_PUMP_OCCLUSION_ALARM_PERSISTENCE ) - { - S32 pos = getSyringePumpPosition(); + 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 ) - } - else - { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SYRINGE_PUMP_OCCLUSION, (F32)pos, force ) - } - result = TRUE; + 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 ) + } + result = TRUE; } - else - { - syringePumpOcclusionErrorCtr = 0; - } return result; } @@ -1506,18 +1596,11 @@ F32 error = ( max > 0.0 ? ( 1.0 - fabs( min / max ) ) : 0.0 ); // Alarm on rate if off by more than 5% or 0.1 mL/hr, whichever is greater - if ( ( error > pctMargin ) && ( delta > SYRINGE_PUMP_MAX_RATE_ERROR_ML_HR ) ) + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_SPEED_ERROR, ( ( error > pctMargin ) && ( delta > SYRINGE_PUMP_MAX_RATE_ERROR_ML_HR ) ) ) ) { - if ( ++syringePumpRateErrorCtr > SYRINGE_PUMP_RATE_ALARM_PERSISTENCE ) - { - result = TRUE; - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SYRINGE_PUMP_SPEED_ERROR, syringePumpSetRate, rate ) - } + result = TRUE; + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SYRINGE_PUMP_SPEED_ERROR, syringePumpSetRate, rate ) } - else - { - syringePumpRateErrorCtr = 0; - } return result; } @@ -1562,11 +1645,12 @@ *************************************************************************/ static void rampSyringePump( void ) { + // Ramp up syringe pump toward target speed syringePumpRampTimerCtr++; if ( syringePumpRampUpToggleTime > syringePumpSetToggleTime ) { syringePumpRampUpToggleTime = (U32)((F32)SYRINGE_PUMP_START_RAMP_SPEED / - (F32)( syringePumpRampTimerCtr * syringePumpRampTimerCtr * syringePumpRampTimerCtr / SYRINGE_PUMP_RAMP_DIVISOR )); + (F32)( ( syringePumpRampTimerCtr * syringePumpRampTimerCtr * syringePumpRampTimerCtr ) / SYRINGE_PUMP_RAMP_DIVISOR ) ); if ( syringePumpRampUpToggleTime > syringePumpSetToggleTime ) { setFPGASyringePumpStepToggleTime( syringePumpRampUpToggleTime ); @@ -1589,18 +1673,22 @@ *************************************************************************/ static void calcStepperToggleTimeForTargetRate( F32 rate ) { - F32 conv = 0.0; + double temp; + F32 conv; // Convert given rate to stepper toggle period - conv = rate * SYRINGE_MICRO_STEPS_PER_ML; // = uSteps/hr - conv /= (F32)( MIN_PER_HOUR * SEC_PER_MIN); // = uSteps/sec - conv /= MICRO_SECONDS_PER_SECOND; // = uSteps/uSec - conv *= SYRINGE_TOGGLES_PER_STEP; // = toggles/uSec + temp = (double)rate * SYRINGE_MICRO_STEPS_PER_ML; // = uSteps/hr + temp /= (double)( MIN_PER_HOUR * SEC_PER_MIN); // = uSteps/sec + temp /= MICRO_SECONDS_PER_SECOND; // = uSteps/uSec + conv = (F32)temp * SYRINGE_TOGGLES_PER_STEP; // = toggles/uSec conv = 1.0 / conv; // = uSec/toggle // Set stepper toggle time to calculated value syringePumpSetToggleTime = FLOAT_TO_INT_WITH_ROUND( conv ); // Set stepper ramp toggle time to initial ramp up speed initially syringePumpRampUpToggleTime = SYRINGE_PUMP_START_RAMP_SPEED; + // Reset ramp stall timer and retry counters + syringePumpStallCtr = 0; + syringePumpStallRetryCount = 0; } /*********************************************************************//** @@ -1663,6 +1751,10 @@ data.heparinDeliveryState = (U32)heparinDeliveryState; data.syringePumpVolumeDelivered = getSyringePumpVolumeDelivered(); data.syringePumpSafetyVolume = syringePumpSafetyVolumeDelivered; + data.syringePumpStatus = ( (U32)getSyringePumpStatus() << SHIFT_24_BITS ) | + ( (U32)getSyringePumpEncoderStatus() << SHIFT_16_BITS_FOR_WORD_SHIFT ) | + ( (U32)getSyringePumpADCandDACStatus() << SHIFT_8_BITS_FOR_BYTE_SHIFT ) | + ( (U32)getSyringePumpADCReadCounter() ); broadcastSyringePumpData( data ); broadcastHeparinData( data.syringePumpVolumeDelivered ); @@ -2048,4 +2140,184 @@ return result; } +/*********************************************************************//** + * @brief + * The testSetSyringePumpStatus function overrides the syringe pump + * status. + * @details Inputs: none + * @details Outputs: syringePumpStatus + * @param status override syringe pump status with this value + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetSyringePumpStatus( U32 status ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + syringePumpStatus.ovData = status; + syringePumpStatus.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetSyringePumpStatus function resets the override of the + * syringe pump status. + * @details Inputs: none + * @details Outputs: syringePumpStatus + * @return TRUE if reset successful, FALSE if not + *************************************************************************/ +BOOL testResetSyringePumpStatus( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + syringePumpStatus.override = OVERRIDE_RESET; + syringePumpStatus.ovData = syringePumpStatus.ovInitData; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testSetSyringePumpEncoderStatus function overrides the syringe + * pump encoder status. + * @details Inputs: none + * @details Outputs: syringePumpEncoderStatus + * @param status override syringe pump encoder status with this value + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetSyringePumpEncoderStatus( U32 status ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + syringePumpEncoderStatus.ovData = status; + syringePumpEncoderStatus.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetSyringePumpEncoderStatus function resets the override + * of the syringe pump encoder status. + * @details Inputs: none + * @details Outputs: syringePumpEncoderStatus + * @return TRUE if reset successful, FALSE if not + *************************************************************************/ +BOOL testResetSyringePumpEncoderStatus( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + syringePumpEncoderStatus.override = OVERRIDE_RESET; + syringePumpEncoderStatus.ovData = syringePumpEncoderStatus.ovInitData; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testSetSyringePumpADCandDACStatus function overrides the syringe + * pump ADC and DAC status. + * @details Inputs: none + * @details Outputs: syringePumpADCandDACStatus + * @param status override syringe pump ADC and DAC status with this value + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetSyringePumpADCandDACStatus( U32 status ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + syringePumpADCandDACStatus.ovData = status; + syringePumpADCandDACStatus.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetSyringePumpADCandDACStatus function resets the override + * of the syringe pump ADC and DAC status. + * @details Inputs: none + * @details Outputs: syringePumpADCandDACStatus + * @return TRUE if reset successful, FALSE if not + *************************************************************************/ +BOOL testResetSyringePumpADCandDACStatus( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + syringePumpADCandDACStatus.override = OVERRIDE_RESET; + syringePumpADCandDACStatus.ovData = syringePumpADCandDACStatus.ovInitData; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testSetSyringePumpADCReadCounter function overrides the syringe + * pump ADC read counter. + * @details Inputs: none + * @details Outputs: syringePumpADCReadCtr + * @param ctr override syringe pump ADC read counter with this value + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetSyringePumpADCReadCounter( U32 ctr ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + syringePumpADCReadCtr.ovData = ctr; + syringePumpADCReadCtr.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetSyringePumpADCReadCounter function resets the override + * of the syringe pump ADC read counter. + * @details Inputs: none + * @details Outputs: syringePumpADCReadCtr + * @return TRUE if reset successful, FALSE if not + *************************************************************************/ +BOOL testResetSyringePumpADCReadCounter( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + syringePumpADCReadCtr.override = OVERRIDE_RESET; + syringePumpADCReadCtr.ovData = syringePumpADCReadCtr.ovInitData; + } + + return result; +} + /**@}*/