Index: firmware/App/Controllers/SyringePump.c =================================================================== diff -u -r88fd90befbce61886ae47ad7d20ec863319cfa34 -r1afd5c87ef15399998a743c2ebcafe2cc03bd363 --- firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision 88fd90befbce61886ae47ad7d20ec863319cfa34) +++ firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision 1afd5c87ef15399998a743c2ebcafe2cc03bd363) @@ -41,9 +41,12 @@ #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 SYRINGE_PUMP_RETRACT_RATE 10800.0 ///< Retract rate is 15 mL/ 5 s = 3 mL/s = 10,800 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 MAX_SYRINGE_PUMP_RAMP_RATE 10000.0 ///< Maximum ramp rate (micro steps per second) for syringe pump. TODO - get from Systems -#define SYRINGE_OCCLUSION_THRESHOLD_MV 3000.0 ///< Force sensor threshold (in mV) above which an occlusion is detected. TODO - get from Systems +#define SYRINGE_OCCLUSION_THRESHOLD_V 2.5 ///< Force sensor threshold (in V) above which an occlusion is detected. TODO - get from Systems #define SYRINGE_PUMP_RATE_ALARM_PERSISTENCE ( 1 * MS_PER_SECOND ) ///< Alarm persistence period for syringe pump speed check alarms. @@ -54,6 +57,11 @@ #define SYRINGE_PUMP_ADC_FULL_SCALE_BITS 1024.0 ///< Syringe pump ADC has 1024 full scale counts (10-bit) per channel. #define SYRINGE_PUMP_DAC_FULL_SCALE_BITS 4096 ///< Syringe pump DAC has has 4096 full scale counts (12-bit). +#define SYRINGE_PUMP_SYRINGE_DETECT_THRESHOLD_V 2.0 ///< Syringe pump syringe detected threshold (in V). +#define SYRINGE_PUMP_HOME_DETECT_THRESHOLD_V 2.5 ///< Syringe pump home detected threshold (in V). +#define SYRINGE_PUMP_PLUNGER_DETECT_THRESHOLD_V 2.0 ///< Syringe pump plunger detection force threshold (in V). +#define SYRINGE_PUMP_PRIME_VOLUME_ML 0.353 ///< Target syringe prime volume (in mL). + // Bit definitions for syringe pump control register #define SYRINGE_PUMP_CONTROL_SLEEP_OFF 0x40 ///< Syringe pump control register bit for sleep mode (active low). #define SYRINGE_PUMP_CONTROL_NOT_RESET 0x20 ///< Syringe pump control register bit for resetting stepper motor (active low). @@ -121,9 +129,9 @@ /// 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 mV). -static OVERRIDE_F32_T syringePumpMeasSyringeDetectionSwitch = {0, 0, 0, 0 }; ///< Measured syringe detect switch (in mV). -static OVERRIDE_F32_T syringePumpMeasHome = {0.0, 0.0, 0.0, 0 }; ///< Measured optical home (in mV). +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). @@ -136,6 +144,7 @@ static BOOL syringePumpHasBeenHomed; ///< Flag indicates whether syringe pump has been homed at least once (indicates position is known). static BOOL syringePumpRetractRequested; ///< Flag indicates a retract operation is requested. static BOOL syringePumpPrimeRequested; ///< Flag indicates plunger seek and Heparin prime operations are requested. +static BOOL syringePumpSeekToPrimeRequested; ///< Flag indicates plunger seek finished, pump stopped, now requesting prime operation. static BOOL syringePumpBolusRequested; ///< Flag indicates start or resume of a Heparin bolus operation is requested. static BOOL syringePumpContinuousRequested; ///< Flag indicates start or resume of a Heparin continuous delivery operation is requested. @@ -164,9 +173,9 @@ static S32 getSyringePumpPosition( void ); static F32 getSyringePumpVolumeDelivered( void ); static F32 getSyringePumpMeasRate( void ); -static F32 getSyringePumpSyringeDetectorMv( void ); -static F32 getSyringePumpHomeDetectorMv( void ); -static F32 getSyringePumpForceMv( void ); +static F32 getSyringePumpSyringeDetectorV( void ); +static F32 getSyringePumpHomeDetectorV( void ); +static F32 getSyringePumpForceV( void ); /*********************************************************************//** * @brief @@ -187,53 +196,95 @@ syringePumpHomePositionOffset = 0; syringePumpHasBeenHomed = FALSE; - resetSyringePumpRequestFlags(); syringePumpDataPublicationTimerCounter = 0; syringePumpSelfTestTimerCount = 0; - lastSyringePumpADCReadCtr = 0; + lastSyringePumpADCReadCtr = 0; + + // Reset request flags + resetSyringePumpRequestFlags(); } +/*********************************************************************//** + * @brief + * The resetSyringePumpRequestFlags function resets request flags. + * @details Inputs: none + * @details Outputs: syringePumpSetRate, syringePumpRetractRequested + * @return TRUE if request accepted, FALSE if not + *************************************************************************/ static void resetSyringePumpRequestFlags( void ) { syringePumpRetractRequested = FALSE; syringePumpPrimeRequested = FALSE; + syringePumpSeekToPrimeRequested = FALSE; syringePumpBolusRequested = FALSE; syringePumpContinuousRequested = FALSE; } +/*********************************************************************//** + * @brief + * The stopSyringePump function requests syringe pump be stopped. + * @details Inputs: none + * @details Outputs: syringePumpSetRate, syringePumpRetractRequested, syringePumpState + * @return TRUE if request accepted, FALSE if not + *************************************************************************/ void stopSyringePump( void ) { syringePumpSetRate = 0.0; setFPGASyringePumpStepToggleTime( SYRINGE_PUMP_MICROSTEP_TOGGLE_TIME_FOR_STOP ); + syringePumpState = SYRINGE_PUMP_OFF_STATE; } +/*********************************************************************//** + * @brief + * The retractSyringePump function requests retract operation. + * @details Inputs: syringePumpState + * @details Outputs: syringePumpSetRate, syringePumpRetractRequested + * @return TRUE if request accepted, FALSE if not + *************************************************************************/ BOOL retractSyringePump( void ) { - if ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) + if ( ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) && ( FALSE == isSyringeDetected() ) ) { - syringePumpSetRate = 0.0; // TODO - what is retract rate in mL/hr? + syringePumpSetRate = 0.1; // SYRINGE_PUMP_RETRACT_RATE; syringePumpRetractRequested = TRUE; } return syringePumpRetractRequested; } +/*********************************************************************//** + * @brief + * The primeSyringePump function requests plunger seek and prime operations. + * @details Inputs: syringePumpState + * @details Outputs: syringePumpSetRate, syringePumpBolusRequested + * @return TRUE if request accepted, FALSE if not + *************************************************************************/ BOOL primeSyringePump( void ) { - if ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) + if ( ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) && ( TRUE == isSyringeDetected() ) && + ( TRUE == isSyringePumpHome() ) ) { - syringePumpSetRate = 0.0; // TODO - what is seek rate in mL/hr? + syringePumpSetRate = 0.1; //SYRINGE_PUMP_SEEK_RATE; syringePumpPrimeRequested = TRUE; } return syringePumpPrimeRequested; } +/*********************************************************************//** + * @brief + * The startHeparinBolus function requests Heparin bolus delivery. + * @details Inputs: syringePumpState + * @details Outputs: syringePumpSetRate, syringePumpBolusRequested + * @param flowRate desired bolus flow rate (in mL/hr) + * @return TRUE if request accepted, FALSE if not + *************************************************************************/ BOOL startHeparinBolus( F32 flowRate ) { - if ( ( flowRate >= MIN_HEPARIN_BOLUS_RATE ) && ( flowRate <= MAX_HEPARIN_BOLUS_RATE ) ) + if ( ( flowRate >= MIN_HEPARIN_BOLUS_RATE ) && ( flowRate <= MAX_HEPARIN_BOLUS_RATE ) && + ( TRUE == isSyringeDetected() ) && ( FALSE == isSyringePumpHome() ) ) { if ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) { @@ -249,9 +300,18 @@ return syringePumpBolusRequested; } +/*********************************************************************//** + * @brief + * The startHeparinContinuous function requests Heparin continuous delivery. + * @details Inputs: syringePumpState + * @details Outputs: syringePumpSetRate, syringePumpContinuousRequested + * @param flowRate desired flow rate (in mL/hr) + * @return TRUE if request accepted, FALSE if not + *************************************************************************/ BOOL startHeparinContinuous( F32 flowRate ) { - if ( ( flowRate >= MIN_HEPARIN_CONTINUOUS_RATE ) && ( flowRate <= MAX_HEPARIN_CONTINUOUS_RATE ) ) + if ( ( flowRate >= MIN_HEPARIN_CONTINUOUS_RATE ) && ( flowRate <= MAX_HEPARIN_CONTINUOUS_RATE ) && + ( TRUE == isSyringeDetected() ) && ( FALSE == isSyringePumpHome() ) ) { if ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) { @@ -287,7 +347,15 @@ return result; } -static F32 getSyringePumpVolumeDelivered( void ) +/*********************************************************************//** + * @brief + * The getSyringePumpVolumeDelivered function gets the current syringe pump + * volume delivered. + * @details Inputs: syringePumpVolumeDelivered + * @details Outputs: none + * @return the current syringe pump volume delivered (in mL). + *************************************************************************/ +static F32 getSyringePumpVolumeDelivered( void ) { F32 result = syringePumpVolumeDelivered.data; @@ -299,7 +367,15 @@ return result; } -static F32 getSyringePumpMeasRate( void ) +/*********************************************************************//** + * @brief + * The getSyringePumpMeasRate function gets the current syringe pump measured + * rate. + * @details Inputs: syringePumpMeasRate + * @details Outputs: none + * @return the current syringe pump measured rate (in mL/hr). + *************************************************************************/ +static F32 getSyringePumpMeasRate( void ) { F32 result = syringePumpMeasRate.data; @@ -311,6 +387,14 @@ 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 ) { S32 result = syringePumpPosition.data; @@ -323,7 +407,15 @@ return result; } -static F32 getSyringePumpSyringeDetectorMv( void ) +/*********************************************************************//** + * @brief + * The getSyringePumpSyringeDetectorV function gets the current syringe pump + * syringe detect signal. + * @details Inputs: syringePumpMeasSyringeDetectionSwitch + * @details Outputs: none + * @return the current syringe pump syringe detect signal (in V). + *************************************************************************/ +static F32 getSyringePumpSyringeDetectorV( void ) { F32 result = syringePumpMeasSyringeDetectionSwitch.data; @@ -335,7 +427,15 @@ return result; } -static F32 getSyringePumpHomeDetectorMv( void ) +/*********************************************************************//** + * @brief + * The getSyringePumpHomeDetectorV function gets the current syringe pump + * home detect signal. + * @details Inputs: syringePumpMeasHome + * @details Outputs: none + * @return the current syringe pump home detect signal (in V). + *************************************************************************/ +static F32 getSyringePumpHomeDetectorV( void ) { F32 result = syringePumpMeasHome.data; @@ -349,12 +449,12 @@ /*********************************************************************//** * @brief - * The getSyringePumpForceMv function gets the current syringe pump force. + * The getSyringePumpForceV function gets the current syringe pump force. * @details Inputs: syringePumpMeasForce * @details Outputs: none - * @return the current syringe pump force (in mV). + * @return the current syringe pump force (in V). *************************************************************************/ -static F32 getSyringePumpForceMv( void ) +static F32 getSyringePumpForceV( void ) { F32 result = syringePumpMeasForce.data; @@ -366,6 +466,53 @@ return result; } +/*********************************************************************//** + * @brief + * The isSyringeDetected function determines whether a syringe is currently + * detected. + * @details Inputs: syringePumpMeasSyringeDetectionSwitch + * @details Outputs: none + * @return TRUE if syringe detected, FALSE if not + *************************************************************************/ +BOOL isSyringeDetected( void ) +{ + BOOL result = FALSE; + + if ( getSyringePumpSyringeDetectorV() >= SYRINGE_PUMP_SYRINGE_DETECT_THRESHOLD_V ) + { + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The isSyringePumpHome function determines whether the syringe drive position + * is at the home position. + * @details Inputs: syringePumpMeasHome + * @details Outputs: none + * @return TRUE if home detected, FALSE if not + *************************************************************************/ +BOOL isSyringePumpHome( void ) +{ + BOOL result = FALSE; + + if ( getSyringePumpHomeDetectorV() >= SYRINGE_PUMP_HOME_DETECT_THRESHOLD_V ) + { + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The execSyringePumpMonitor function executes the syringe pump monitor. + * @details Inputs: FPGA syringe pump readings + * @details Outputs: Alarm(s) may be triggered + * @return none + *************************************************************************/ static void execSyringePumpMonitor( void ) { S32 encPosition = getFPGASyringePumpEncoderPosition(); @@ -374,7 +521,7 @@ U08 adcReadCtr = getFPGASyringePumpADCReadCounter(); U08 adcDACStatus= getFPGASyringePumpADCandDACStatus(); - // get latest ADC data and convert to mV + // 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; syringePumpMeasForce.data = ( (F32)getFPGASyringePumpADCChannel0() * SYRINGE_PUMP_ADC_REF_V ) / SYRINGE_PUMP_ADC_FULL_SCALE_BITS; @@ -490,6 +637,11 @@ { result = SYRINGE_PUMP_SEEK_STATE; } + else if ( TRUE == syringePumpSeekToPrimeRequested ) + { + result = SYRINGE_PUMP_PRIME_STATE; + syringePumpSetRate = SYRINGE_PUMP_PRIME_RATE; + } else if ( TRUE == syringePumpBolusRequested ) { result = SYRINGE_PUMP_HEP_BOLUS_STATE; @@ -534,20 +686,26 @@ SYRINGE_PUMP_STATE_T result = SYRINGE_PUMP_RETRACT_STATE; // TODO - timer is test code, 3.0 is placeholder for home threshold, 1.0 is placeholder for syringe detected threshold - if ( ( ++xTimerCtr > 100 ) || ( getSyringePumpHomeDetectorMv() > 3.0 ) || ( getSyringePumpSyringeDetectorMv() < 1.0 ) ) + if ( ( ++xTimerCtr > 100 ) || ( getSyringePumpHomeDetectorV() > 3.0 ) || ( getSyringePumpSyringeDetectorV() < 1.0 ) ) { // Retract reached home setFPGASyringePumpStepToggleTime( SYRINGE_PUMP_MICROSTEP_TOGGLE_TIME_FOR_STOP ); - if ( getSyringePumpHomeDetectorMv() > 3.0 ) + if ( TRUE == isSyringePumpHome() ) { syringePumpHomePositionOffset = getFPGASyringePumpEncoderPosition(); syringePumpPosition.data = 0; + syringePumpVolumeDelivered.data = 0.0; + syringePumpHasBeenHomed = TRUE; } else { // TODO - alarm } result = SYRINGE_PUMP_OFF_STATE; } + else if ( TRUE == isSyringeDetected() ) + { + stopSyringePump(); + } return result; } @@ -564,8 +722,59 @@ { SYRINGE_PUMP_STATE_T result = SYRINGE_PUMP_SEEK_STATE; + if ( getSyringePumpForceV() <= SYRINGE_PUMP_PLUNGER_DETECT_THRESHOLD_V ) + { + stopSyringePump(); + syringePumpVolumeDelivered.data = 0.0; + syringePumpSeekToPrimeRequested = TRUE; + result = SYRINGE_PUMP_OFF_STATE; + } + return result; } + +/*********************************************************************//** + * @brief + * The handleSyringePumpPrimeState function handles the pres/occl initialize state + * of the syringe pump control state machine. + * @details Inputs: TBD + * @details Outputs: TBD + * @return next state + *************************************************************************/ +static SYRINGE_PUMP_STATE_T handleSyringePumpPrimeState( void ) +{ + SYRINGE_PUMP_STATE_T result = SYRINGE_PUMP_PRIME_STATE; + + if ( getSyringePumpVolumeDelivered() >= SYRINGE_PUMP_PRIME_VOLUME_ML ) + { + stopSyringePump(); + syringePumpVolumeDelivered.data = 0.0; + result = SYRINGE_PUMP_OFF_STATE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The handleSyringePumpBolusState function handles the pres/occl initialize state + * of the syringe pump control state machine. + * @details Inputs: TBD + * @details Outputs: TBD + * @return next state + *************************************************************************/ +static SYRINGE_PUMP_STATE_T handleSyringePumpBolusState( void ) +{ + SYRINGE_PUMP_STATE_T result = SYRINGE_PUMP_HEP_BOLUS_STATE; + + return result; +} +//static S32 getSyringePumpPosition( void ); +//static F32 getSyringePumpVolumeDelivered( void ); +//static F32 getSyringePumpMeasRate( void ); +//static F32 getSyringePumpSyringeDetectorV( void ); +//static F32 getSyringePumpHomeDetectorV( void ); +//static F32 getSyringePumpForceV( void ); //void setFPGASyringePumpControlFlags( U08 bitFlags ); //void setFPGASyringePumpADCandDACControlFlags( U08 bitFlags ); //void setFPGASyringePumpDACOutputLevel( U16 counts ); @@ -602,36 +811,6 @@ /*********************************************************************//** * @brief - * The handleSyringePumpPrimeState function handles the pres/occl initialize state - * of the syringe pump control state machine. - * @details Inputs: TBD - * @details Outputs: TBD - * @return next state - *************************************************************************/ -static SYRINGE_PUMP_STATE_T handleSyringePumpPrimeState( void ) -{ - SYRINGE_PUMP_STATE_T result = SYRINGE_PUMP_PRIME_STATE; - - return result; -} - -/*********************************************************************//** - * @brief - * The handleSyringePumpBolusState function handles the pres/occl initialize state - * of the syringe pump control state machine. - * @details Inputs: TBD - * @details Outputs: TBD - * @return next state - *************************************************************************/ -static SYRINGE_PUMP_STATE_T handleSyringePumpBolusState( void ) -{ - SYRINGE_PUMP_STATE_T result = SYRINGE_PUMP_HEP_BOLUS_STATE; - - return result; -} - -/*********************************************************************//** - * @brief * The handleSyringePumpContinuousState function handles the continuous state * of the syringe pump control state machine. * @details Inputs: TBD @@ -676,10 +855,10 @@ { SYRINGE_PUMP_DATA_PAYLOAD_T data; - data.syringePumpMeasForce = getSyringePumpForceMv(); - data.syringePumpMeasHome = getSyringePumpHomeDetectorMv(); + data.syringePumpMeasForce = getSyringePumpForceV(); + data.syringePumpMeasHome = getSyringePumpHomeDetectorV(); data.syringePumpMeasRate = getSyringePumpMeasRate(); - data.syringePumpMeasSwitch = getSyringePumpSyringeDetectorMv(); + data.syringePumpMeasSwitch = getSyringePumpSyringeDetectorV(); data.syringePumpPosition = getSyringePumpPosition(); data.syringePumpSetRate = syringePumpSetRate; data.syringePumpState = (U32)syringePumpState;