Index: firmware/App/Controllers/SyringePump.c =================================================================== diff -u -r29a2c3c7d7618489c0ada9f98e1d30226b455392 -rf6b78d1fe6741043de38707211710ab0e8a08483 --- firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision 29a2c3c7d7618489c0ada9f98e1d30226b455392) +++ firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision f6b78d1fe6741043de38707211710ab0e8a08483) @@ -1,41 +1,41 @@ /************************************************************************** * -* Copyright (c) 2019-2022 Diality Inc. - All Rights Reserved. +* Copyright (c) 2021-2022 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file SyringePump.c * -* @author (last) Dara Navaei -* @date (last) 04-Jan-2022 +* @author (last) Hung Nguyen +* @date (last) 15-Feb-2022 * * @author (original) Sean Nash * @date (original) 04-Mar-2021 * ***************************************************************************/ #include - -#include "AlarmMgmt.h" + +#include "AlarmMgmt.h" #include "FPGA.h" #include "ModeTreatmentParams.h" -#include "NVDataMgmt.h" +#include "NVDataMgmt.h" #include "OperationModes.h" #include "PersistentAlarm.h" #include "SafetyShutdown.h" -#include "SyringePump.h" -#include "SystemCommMessages.h" -#include "TaskPriority.h" -#include "Timers.h" - -/** - * @addtogroup SyringePump - * @{ - */ - -// ********** private definitions ********** - -/// Default publication interval for syringe pump data. +#include "SyringePump.h" +#include "SystemCommMessages.h" +#include "TaskPriority.h" +#include "Timers.h" + +/** + * @addtogroup SyringePump + * @{ + */ + +// ********** private definitions ********** + +/// Default publication interval for syringe pump data. #define SYRINGE_PUMP_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) #define BD_SYRINGE_ID_RADIUS_CM ( 1.4427 / 2.0 ) ///< Radius from inner diameter (in cm) of supported BD syringe. @@ -55,20 +55,18 @@ /// Number of encoder counts per mL. #define SYRINGE_ENCODER_COUNTS_PER_ML ( SYRINGE_ENCODER_COUNTS_PER_MM / SYRINGE_ML_PER_MM ) /// Number of micro steps per mL. -#define SYRINGE_MICRO_STEPS_PER_ML ( ( SYRINGE_MICRO_STEPS_PER_REV / SYRINGE_MM_PER_REV ) / SYRINGE_ML_PER_MM ) +#define SYRINGE_MICRO_STEPS_PER_ML ( ( SYRINGE_MICRO_STEPS_PER_REV / SYRINGE_MM_PER_REV ) / SYRINGE_ML_PER_MM ) #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 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. #define SYRINGE_PUMP_MAX_RATE 11000.0 ///< Maximum rate of the syringe pump (in mL/hr). -#define SYRINGE_PUMP_RATE_ALARM_PERSISTENCE 2000 ///< 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_RATE_ALARM_PERSISTENCE 3000 ///< Alarm persistence period (in ms) for syringe pump speed check alarms. +#define SYRINGE_PUMP_DIR_ALARM_PERSISTENCE 3000 ///< Alarm persistence period (in ms) for syringe pump direction check alarms. #define SYRINGE_PUMP_OFF_ALARM_PERSISTENCE 1000 ///< 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). @@ -81,6 +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_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). @@ -90,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 ) @@ -127,7 +126,7 @@ #define SYRINGE_PUMP_MICROSTEP_TOGGLE_TIME_FOR_STOP 0xFFFFFFFF ///< Syringe pump microstep toggle time setting to indicate zero speed (stopped). #define DATA_PUBLISH_COUNTER_START_COUNT 10 ///< Data publish counter start count. - + /// Control bits to run syringe pump in reverse direction static const U08 SYRINGE_PUMP_CONTROL_RUN_REVERSE = SYRINGE_PUMP_CONTROL_SLEEP_OFF | SYRINGE_PUMP_CONTROL_NOT_RESET | @@ -154,41 +153,44 @@ #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 -{ +/// Defined states for the syringe pump control state machine. +typedef enum SyringePump_States +{ SYRINGE_PUMP_INIT_STATE = 0, ///< Syringe pump initialize state - SYRINGE_PUMP_OFF_STATE, ///< Syringe pump off state + SYRINGE_PUMP_OFF_STATE, ///< Syringe pump off state SYRINGE_PUMP_RETRACT_STATE, ///< Syringe pump retract state SYRINGE_PUMP_SEEK_STATE, ///< Syringe pump seek plunger state SYRINGE_PUMP_PRIME_STATE, ///< Syringe pump prime state SYRINGE_PUMP_HEP_BOLUS_STATE, ///< Syringe pump bolus delivery of Heparin state SYRINGE_PUMP_HEP_CONTINUOUS_STATE, ///< Syringe pump continuous delivery of Heparin state SYRINGE_PUMP_CONFIG_FORCE_SENSOR_STATE, ///< Syringe pump configure DAC gain for force sensor state - NUM_OF_SYRINGE_PUMP_STATES ///< Number of syringe pump control states -} SYRINGE_PUMP_STATE_T; - -// ********** private data ********** - -static SYRINGE_PUMP_STATE_T syringePumpState; ///< Current state of syringe pump control state machine. + NUM_OF_SYRINGE_PUMP_STATES ///< Number of syringe pump control states +} SYRINGE_PUMP_STATE_T; + +// ********** private data ********** + +static SYRINGE_PUMP_STATE_T syringePumpState; ///< Current state of syringe pump control state machine. static U32 syringePumpDataPublicationTimerCounter; ///< Used to schedule syringe pump data publication to CAN bus. static U32 syringePumpRampTimerCtr; ///< Used to track ramp up time. static HEPARIN_STATE_T heparinDeliveryState; ///< Current state of Heparin delivery. - + /// 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_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 heparinBolusTargetRate = { HEPARIN_BOLUS_TARGET_RATE, 0.0, HEPARIN_BOLUS_TARGET_RATE, 0 }; ///< Target rate of the heprin bolus in mL/hour + 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 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). @@ -222,20 +224,22 @@ static U32 syringePumpStallRetryCount; ///< Counts pump ramp up stall retries. static HD_HEPARIN_FORCE_SENSOR_CAL_RECORD_T forceSensorCalRecord; ///< HD heparin force sensor calibration record. -// ********** private function prototypes ********** +// ********** private function prototypes ********** static void resetSyringePumpRequestFlags( void ); -static void execSyringePumpMonitor( void ); +static void execSyringePumpMonitor( void ); static S32 getSyringePumpPosition( void ); static F32 getSyringePumpMeasRate( void ); static F32 getSyringePumpSyringeDetectorV( void ); static F32 getSyringePumpHomeDetectorV( void ); static F32 getSyringePumpForceV( void ); +static F32 getHeprinBolusTargetRate( 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 handleSyringePumpInitState( void ); static SYRINGE_PUMP_STATE_T handleSyringePumpOffState( void ); static SYRINGE_PUMP_STATE_T handleSyringePumpRetractState( void ); static SYRINGE_PUMP_STATE_T handleSyringePumpSeekState( void ); @@ -248,22 +252,22 @@ static void calcMeasRate( void ); static void calcSafetyVolumeDelivered( void ); static BOOL checkDirection( BOOL stopPump, MOTOR_DIR_T expDir ); -static BOOL checkOcclusionOrEmpty( BOOL stopPump ); +static BOOL checkSyringeEmpty( BOOL stopPump ); static BOOL checkSyringeRemoved( BOOL stopPump ); static BOOL checkMaxTravel( BOOL stopPump, S32 maxPos ); static BOOL checkMeasRate( BOOL stopPump, F32 pctMargin ); static BOOL checkVolumeVsSafetyVolume( BOOL stopPump, F32 pctMargin ); static BOOL checkForStall( BOOL stopPump ); static void publishSyringePumpData( void ); - -/*********************************************************************//** - * @brief - * The initSyringePump function initializes the syringe pump module. - * @details Inputs: none - * @details Outputs: syringe pump module initialized. - * @return none - *************************************************************************/ -void initSyringePump( void ) + +/*********************************************************************//** + * @brief + * The initSyringePump function initializes the syringe pump module. + * @details Inputs: none + * @details Outputs: syringe pump module initialized. + * @return none + *************************************************************************/ +void initSyringePump( void ) { U32 i; @@ -312,7 +316,7 @@ 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 + // Reset request flags resetSyringePumpRequestFlags(); } @@ -522,6 +526,7 @@ if ( ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) && ( TRUE == isSyringeDetected() ) && ( heparinDeliveryState != HEPARIN_STATE_OFF ) && ( TRUE == syringePumpPlungerFound ) ) { + forceAtEndOfSeek = getSyringePumpForceV(); // Get the force sensor reading when syringe pump prime has been requested (after seek) syringePumpSetRate = SYRINGE_PUMP_PRIME_RATE; syringePumpPrimeRequested = TRUE; resetHeparinVolumeDelivered(); @@ -554,26 +559,21 @@ *************************************************************************/ BOOL startHeparinBolus( void ) { - F32 tgtRate = 0.0; - - // Get set Heparin bolus volume (mL) and convert to target rate (mL/hr) - tgtRate = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ) / HEPARIN_BOLUS_TIME_HR; - // 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 ) ) { - syringePumpSetRate = tgtRate; + syringePumpSetRate = getHeprinBolusTargetRate(); syringePumpBolusRequested = TRUE; } } else { if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_SYRINGE_PUMP ) != SW_CONFIG_ENABLE_VALUE ) { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, (F32)SW_FAULT_ID_HD_SYRINGE_INVALID_BOLUS_CMD, tgtRate ) + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, (F32)SW_FAULT_ID_HD_SYRINGE_INVALID_BOLUS_CMD, syringePumpSetRate ) } } @@ -647,14 +647,7 @@ *************************************************************************/ F32 getSyringePumpVolumeDelivered( void ) { - F32 result = syringePumpVolumeDelivered.data; - - if ( OVERRIDE_KEY == syringePumpVolumeDelivered.override ) - { - result = syringePumpVolumeDelivered.ovData; - } - - return result; + return getF32OverrideValue( &syringePumpVolumeDelivered ); } /*********************************************************************//** @@ -667,38 +660,11 @@ *************************************************************************/ static F32 getSyringePumpMeasRate( void ) { - F32 result = syringePumpMeasRate.data; - - if ( OVERRIDE_KEY == syringePumpMeasRate.override ) - { - result = syringePumpMeasRate.ovData; - } - - return result; + return getF32OverrideValue( &syringePumpMeasRate ); } /*********************************************************************//** * @brief - * The getSyringePumpPosition function gets the current syringe pump - * position. - * @details Inputs: syringePumpPosition - * @details Outputs: none - * @return the current syringe pump syringe position (in steps). - *************************************************************************/ -static S32 getSyringePumpPosition( void ) -{ - S32 result = syringePumpPosition.data; - - if ( OVERRIDE_KEY == syringePumpPosition.override ) - { - result = syringePumpPosition.ovData; - } - - return result; -} - -/*********************************************************************//** - * @brief * The getSyringePumpSyringeDetectorV function gets the current syringe pump * syringe detect signal. * @details Inputs: syringePumpMeasSyringeDetectionSwitch @@ -707,14 +673,7 @@ *************************************************************************/ static F32 getSyringePumpSyringeDetectorV( void ) { - F32 result = syringePumpMeasSyringeDetectionSwitch.data; - - if ( OVERRIDE_KEY == syringePumpMeasSyringeDetectionSwitch.override ) - { - result = syringePumpMeasSyringeDetectionSwitch.ovData; - } - - return result; + return getF32OverrideValue( &syringePumpMeasSyringeDetectionSwitch ); } /*********************************************************************//** @@ -727,14 +686,7 @@ *************************************************************************/ static F32 getSyringePumpHomeDetectorV( void ) { - F32 result = syringePumpMeasHome.data; - - if ( OVERRIDE_KEY == syringePumpMeasHome.override ) - { - result = syringePumpMeasHome.ovData; - } - - return result; + return getF32OverrideValue( &syringePumpMeasHome ); } /*********************************************************************//** @@ -746,14 +698,33 @@ *************************************************************************/ static F32 getSyringePumpForceV( void ) { - F32 result = syringePumpMeasForce.data; + return getF32OverrideValue( &syringePumpMeasForce ); +} - if ( OVERRIDE_KEY == syringePumpMeasForce.override ) - { - result = syringePumpMeasForce.ovData; - } +/*********************************************************************//** + * @brief + * The getHeprinBolusTargetRate function gets the heprin bolus target + * flow rate. + * @details Inputs: getHeprinBolusTargetRate + * @details Outputs: getHeprinBolusTargetRate + * @return the current target heprin bolus flow rate (in mL/hour). + *************************************************************************/ +static F32 getHeprinBolusTargetRate( void ) +{ + return getF32OverrideValue( &heparinBolusTargetRate ); +} - return result; +/*********************************************************************//** + * @brief + * The getSyringePumpPosition function gets the current syringe pump + * position. + * @details Inputs: syringePumpPosition + * @details Outputs: none + * @return the current syringe pump syringe position (in steps). + *************************************************************************/ +static S32 getSyringePumpPosition( void ) +{ + return getS32OverrideValue( &syringePumpPosition ); } /*********************************************************************//** @@ -765,14 +736,7 @@ *************************************************************************/ 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; + return getU08OverrideValue( &syringePumpStatus ); } /*********************************************************************//** @@ -785,14 +749,7 @@ *************************************************************************/ 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; + return getU08OverrideValue( &syringePumpEncoderStatus ); } /*********************************************************************//** @@ -805,14 +762,7 @@ *************************************************************************/ 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; + return getU08OverrideValue( &syringePumpADCReadCtr ); } /*********************************************************************//** @@ -825,14 +775,7 @@ *************************************************************************/ 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; + return getU08OverrideValue( &syringePumpADCandDACStatus ); } /*********************************************************************//** @@ -1012,8 +955,7 @@ // Check if syringe pump is on while BP is off { - BOOL runWhileOff = ( ( ( SYRINGE_PUMP_HEP_BOLUS_STATE == syringePumpState ) || ( SYRINGE_PUMP_HEP_CONTINUOUS_STATE == syringePumpState ) ) && - ( isBloodPumpRunning() != TRUE ) ); + BOOL runWhileOff = ( ( SYRINGE_PUMP_HEP_CONTINUOUS_STATE == syringePumpState ) && ( isBloodPumpRunning() != TRUE ) ); if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_RUNNING_WHILE_BP_OFF_ERROR, runWhileOff ) ) { @@ -1043,14 +985,14 @@ } } -/*********************************************************************//** - * @brief - * The execSyringePump function executes the syringe pump control state machine. - * @details Inputs: syringePumpState - * @details Outputs: syringePumpState - * @return none - *************************************************************************/ -void execSyringePump( void ) +/*********************************************************************//** + * @brief + * The execSyringePump function executes the syringe pump control state machine. + * @details Inputs: syringePumpState + * @details Outputs: syringePumpState + * @return none + *************************************************************************/ +void execSyringePump( void ) { // Execute syringe pump monitor execSyringePumpMonitor(); @@ -1060,18 +1002,18 @@ { isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_NOT_STOPPED_ERROR, FALSE ); } - - // Execute syringe pump control state machine - switch ( syringePumpState ) - { - case SYRINGE_PUMP_INIT_STATE: - syringePumpState = handleSyringePumpInitState(); - break; - - case SYRINGE_PUMP_OFF_STATE: - syringePumpState = handleSyringePumpOffState(); - break; - + + // Execute syringe pump control state machine + switch ( syringePumpState ) + { + case SYRINGE_PUMP_INIT_STATE: + syringePumpState = handleSyringePumpInitState(); + break; + + case SYRINGE_PUMP_OFF_STATE: + syringePumpState = handleSyringePumpOffState(); + break; + case SYRINGE_PUMP_RETRACT_STATE: syringePumpState = handleSyringePumpRetractState(); break; @@ -1096,15 +1038,15 @@ syringePumpState = handleSyringePumpCalibrateForceSensorState(); break; - default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_SYRINGE_INVALID_STATE, syringePumpState ) - break; - } + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_SYRINGE_INVALID_STATE, syringePumpState ) + break; + } resetSyringePumpRequestFlags(); - - // Publish syringe pump data on interval - publishSyringePumpData(); + + // Publish syringe pump data on interval + publishSyringePumpData(); } /*********************************************************************//** @@ -1133,7 +1075,7 @@ } return result; -} +} /*********************************************************************//** * @brief @@ -1312,7 +1254,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; @@ -1323,14 +1265,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 @@ -1390,16 +1332,13 @@ // 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(); @@ -1437,8 +1376,8 @@ // Check volume vs. safety volume stopPump = checkVolumeVsSafetyVolume( stopPump, SYRINGE_PUMP_VOLUME_CHECK_MARGIN ); - // Check for occlusion - stopPump = checkOcclusionOrEmpty( stopPump ); + // Check for syringe pump empty + stopPump = checkSyringeEmpty( stopPump ); // Check for commanded vs. meas. rate stopPump = checkMeasRate( stopPump, SYRINGE_PUMP_RATE_CHECK_MARGIN ); @@ -1478,8 +1417,8 @@ // Has syringe been removed? stopPump = checkSyringeRemoved( stopPump ); - // Check for occlusion - stopPump = checkOcclusionOrEmpty( stopPump ); + // Check for syringe pump empty + stopPump = checkSyringeEmpty( stopPump ); // Check position > empty + 0.5 mL stopPump = checkMaxTravel( stopPump, SYRINGE_PUMP_EMPTY_POS + SYRINGE_PUMP_EMPTY_POS_MARGIN ); @@ -1568,32 +1507,50 @@ /*********************************************************************//** * @brief - * The checkOcclusionOrEmpty function checks the force sensor for excessive - * pressure. Would indicate occlusion or jam or empty syringe. + * The checkSyringeEmpty function checks the force sensor position + * to determine if the syringe pump is empty. * @details Inputs: syringePumpMeasForce.data, syringePumpPosition.data - * @details Outputs: alarm triggered if max force detected + * @details Outputs: alarm triggered if position is empty. * @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 checkOcclusionOrEmpty( BOOL stopPump ) +static BOOL checkSyringeEmpty( BOOL stopPump ) { BOOL result = stopPump; F32 force = getSyringePumpForceV(); + S32 pos = getSyringePumpPosition(); - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_OCCLUSION, ( force >= SYRINGE_FORCE_OCCLUSION_THRESHOLD_V ) ) ) + // If near empty position, assume syringe is empty + if ( fabs( pos - SYRINGE_PUMP_EMPTY_POS ) < SYRINGE_PUMP_EMPTY_POS_MARGIN ) { - S32 pos = getSyringePumpPosition(); + heparinDeliveryState = HEPARIN_STATE_EMPTY; + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SYRINGE_PUMP_SYRINGE_EMPTY, (F32)pos, force ) + result = TRUE; + } - // If near empty position, assume syringe is empty - 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 ) - } + return result; +} + +/*********************************************************************//** + * @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 + *************************************************************************/ +BOOL checkForPrimeOcclusion( void ) +{ + BOOL result = FALSE; // Return FALSE if no occlusion is detected + 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 or more + BOOL occlusionDetected = ( forceDelta >= SYRINGE_FORCE_OCCLUSION_DIFF_V ? TRUE : FALSE ); + + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_OCCLUSION, occlusionDetected ) ) + { + 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; } @@ -1787,7 +1744,7 @@ } } } - + /*********************************************************************//** * @brief * The calcStepperToggleTimeForTargetRate function calculates the stepper @@ -1858,18 +1815,18 @@ syringePumpSafetyVolumeDelivered += ( syringePumpSetRate / ( MIN_PER_HOUR * SEC_PER_MIN * ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ) ); } -/*********************************************************************//** - * @brief - * The publishSyringePumpData function publishes syringe pump data at the - * set interval. - * @details Inputs: latest syringe pump data, syringePumpDataPublicationTimerCounter - * @details Outputs: Syringe pump data are published to CAN bus. - * @return none - *************************************************************************/ -static void publishSyringePumpData( void ) -{ - // Publish syringe pump data on interval - if ( ++syringePumpDataPublicationTimerCounter >= getU32OverrideValue( &syringePumpDataPublishInterval ) ) +/*********************************************************************//** + * @brief + * The publishSyringePumpData function publishes syringe pump data at the + * set interval. + * @details Inputs: latest syringe pump data, syringePumpDataPublicationTimerCounter + * @details Outputs: Syringe pump data are published to CAN bus. + * @return none + *************************************************************************/ +static void publishSyringePumpData( void ) +{ + // Publish syringe pump data on interval + if ( ++syringePumpDataPublicationTimerCounter >= getU32OverrideValue( &syringePumpDataPublishInterval ) ) { SYRINGE_PUMP_DATA_PAYLOAD_T data; @@ -1887,68 +1844,67 @@ ( (U32)getSyringePumpEncoderStatus() << SHIFT_16_BITS_FOR_WORD_SHIFT ) | ( (U32)getSyringePumpADCandDACStatus() << SHIFT_8_BITS_FOR_BYTE_SHIFT ) | ( (U32)getSyringePumpADCReadCounter() ); - + broadcastData( MSG_ID_HD_SYRINGE_PUMP_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( SYRINGE_PUMP_DATA_PAYLOAD_T ) ); broadcastData( MSG_ID_HD_HEPARIN_DATA_BROADCAST, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data.syringePumpVolumeDelivered, sizeof( F32 ) ); - syringePumpDataPublicationTimerCounter = 0; - } + syringePumpDataPublicationTimerCounter = 0; + } } - /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ - - -/*********************************************************************//** - * @brief - * The testSetSyringePumpDataPublishIntervalOverride function overrides the - * syringe pump data publish interval. - * @details Inputs: none - * @details Outputs: syringePumpDataPublishInterval - * @param value override syringe pump data publish interval with (in ms) - * @return TRUE if override successful, FALSE if not - *************************************************************************/ -BOOL testSetSyringePumpDataPublishIntervalOverride( U32 value ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - U32 intvl = value / TASK_PRIORITY_INTERVAL; - - result = TRUE; - syringePumpDataPublishInterval.ovData = intvl; - syringePumpDataPublishInterval.override = OVERRIDE_KEY; - } - - return result; -} - -/*********************************************************************//** - * @brief - * The testResetSyringePumpDataPublishIntervalOverride function resets the override - * of the syringe pump data publish interval. - * @details Inputs: none - * @details Outputs: syringePumpDataPublishInterval - * @return TRUE if override reset successful, FALSE if not - *************************************************************************/ -BOOL testResetSyringePumpDataPublishIntervalOverride( void ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - syringePumpDataPublishInterval.override = OVERRIDE_RESET; - syringePumpDataPublishInterval.ovData = syringePumpDataPublishInterval.ovInitData; - } - - return result; -} + /*********************************************************************//** * @brief + * The testSetSyringePumpDataPublishIntervalOverride function overrides the + * syringe pump data publish interval. + * @details Inputs: none + * @details Outputs: syringePumpDataPublishInterval + * @param value override syringe pump data publish interval with (in ms) + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetSyringePumpDataPublishIntervalOverride( U32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + U32 intvl = value / TASK_PRIORITY_INTERVAL; + + result = TRUE; + syringePumpDataPublishInterval.ovData = intvl; + syringePumpDataPublishInterval.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetSyringePumpDataPublishIntervalOverride function resets the override + * of the syringe pump data publish interval. + * @details Inputs: none + * @details Outputs: syringePumpDataPublishInterval + * @return TRUE if override reset successful, FALSE if not + *************************************************************************/ +BOOL testResetSyringePumpDataPublishIntervalOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + syringePumpDataPublishInterval.override = OVERRIDE_RESET; + syringePumpDataPublishInterval.ovData = syringePumpDataPublishInterval.ovInitData; + } + + return result; +} + +/*********************************************************************//** + * @brief * The testSyringePumpOperationRequest function requests a given syringe pump * operation. * @details Inputs: none @@ -2271,9 +2227,57 @@ return result; } - + /*********************************************************************//** * @brief + * The testSetHeprinBolusTargetRateOverride function overrides the + * heprine bolus target rate. + * @details Inputs: heprinBolusTargetRate + * @details Outputs: heprinBolusTargetRate + * @param: value : override heprinBolusTargetRate (in mL/hour) + * @param: value : override heprinBolusTargetRate (in mL/hour) + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetHeprinBolusTargetRateOverride( F32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + heparinBolusTargetRate.ovInitData = heparinBolusTargetRate.data; + heparinBolusTargetRate.ovData = value; + heparinBolusTargetRate.override = OVERRIDE_KEY; + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetHeprinBolusTargetRateOverride function resets the override + * of the heprin bolus target rate. + * @details Inputs: heprinBolusTargetRate + * @details Outputs: heprinBolusTargetRate + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testResetHeprinBolusTargetRateOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + heparinBolusTargetRate.override = OVERRIDE_RESET; + heparinBolusTargetRate.ovData = heparinBolusTargetRate.ovInitData; + heparinBolusTargetRate.ovInitData = 0.0; + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief * The testSetSyringePumpStatus function overrides the syringe pump * status. * @details Inputs: none @@ -2452,4 +2456,4 @@ return result; } -/**@}*/ +/**@}*/