Index: firmware/App/Controllers/PresOccl.c =================================================================== diff -u -r88fd90befbce61886ae47ad7d20ec863319cfa34 -racb165deff7036d41bbe12678f35cd9539012838 --- firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 88fd90befbce61886ae47ad7d20ec863319cfa34) +++ firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision acb165deff7036d41bbe12678f35cd9539012838) @@ -217,7 +217,7 @@ /*********************************************************************//** * @brief - * The handlePresOcclInitState function handles the pres/occl initialize state + * The handlePresOcclInitState function handles the initialize state * of the pressure/occlusion monitor state machine. * @details Inputs: TBD * @details Outputs: TBD Index: firmware/App/Controllers/SyringePump.c =================================================================== diff -u -r1afd5c87ef15399998a743c2ebcafe2cc03bd363 -racb165deff7036d41bbe12678f35cd9539012838 --- firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision 1afd5c87ef15399998a743c2ebcafe2cc03bd363) +++ firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision acb165deff7036d41bbe12678f35cd9539012838) @@ -33,9 +33,27 @@ // ********** private definitions ********** /// Default publication interval for syringe pump data. -#define SYRINGE_PUMP_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) +#define SYRINGE_PUMP_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) +/// Speed check interval. +#define SYRINGE_PUMP_SPEED_CHECK_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) -#define BD_SYRINGE_ID_MM 14.02 ///< Inner diameter (in mm) of supported BD syringe. +#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. +#define SYRINGE_ML_PER_MM ( ( BD_SYRINGE_ID_RADIUS_CM * BD_SYRINGE_ID_RADIUS_CM ) * PI * 0.1 ) +#define SYRINGE_MM_PER_REV 0.635 ///< Travel (in mm) per revolution. +#define SYRINGE_ENCODER_COUNTS_PER_REV 4000.0 ///< Number of encoder counts per revolution. +#define SYRINGE_STEPS_PER_REV 200.0 ///< Number of steps per revolution. +#define MICRO_SECONDS_PER_SECOND 1000000.0 ///< Microseconds per second conversion. +#define SYRINGE_TOGGLES_PER_STEP 2.0 ///< Stepper motor driver toggles per step or microstep. +#define SYRINGE_MICRO_STEPS_PER_STEP 32.0 ///< Micro-steps per step. +/// Number of micro steps per revolution. +#define SYRINGE_MICRO_STEPS_PER_REV ( SYRINGE_STEPS_PER_REV * SYRINGE_MICRO_STEPS_PER_STEP ) +/// Number of encoder counts per mm. +#define SYRINGE_ENCODER_COUNTS_PER_MM ( SYRINGE_ENCODER_COUNTS_PER_REV / SYRINGE_MM_PER_REV ) +/// 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 MIN_HEPARIN_CONTINUOUS_RATE 0.1 ///< Minimum continuous Heparin flow rate (in mL/hr). #define MAX_HEPARIN_CONTINUOUS_RATE 1.0 ///< Maximum continuous Heparin flow rate (in mL/hr). @@ -44,24 +62,26 @@ #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_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. #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. #define SYRINGE_PUMP_ADC_REF_V 3.3 ///< Syringe pump ADC reference voltage. #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_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_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 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_HOME_DETECT_THRESHOLD_V 0.25 ///< Syringe pump home detected threshold (in V). #define SYRINGE_PUMP_PRIME_VOLUME_ML 0.353 ///< Target syringe prime volume (in mL). +#define SYRINGE_PUMP_START_RAMP_SPEED 300000 ///< Starting speed for all syringe pump operations to ramp up from. +#define SYRINGE_PUMP_RAMP_NUMERATOR 15 ///< Numerator of ramp period reduction fraction. +#define SYRINGE_PUMP_RAMP_DENOMINATOR 16 ///< Denominator of ramp period reduction fraction. + // 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). @@ -124,7 +144,8 @@ // ********** 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 syringePumpDataPublicationTimerCounter; ///< Used to schedule syringe pump data publication to CAN bus. +static U32 syringePumpSpeedCalcTimerCounter; ///< Used to calculate measured rate from change in position over time. /// 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 }; @@ -136,30 +157,41 @@ static OVERRIDE_F32_T syringePumpVolumeDelivered = {0.0, 0.0, 0.0, 0 }; ///< Measured volume delivered (in mL). static F32 syringePumpSetRate; ///< Set rate for syringe pump (in mL/hr). -static F32 syringePumpSetSpeed; ///< Set speed for syringe pump (in steps/sec). -static F32 syringePumpMeasSpeed; ///< Measured speed for syringe pump (in steps/sec). +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). static S32 syringePumpHomePositionOffset; ///< FPGA reported position when at home postion. +static S32 syringePumpPosition1SecAgo; ///< Position recorded at last 1 Hz speed check. 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. +static BOOL syringePumpDACVrefSetRequested; ///< Flag indicates request to set DAC Vref for force sensor. +static BOOL syringePumpDACVrefWriteInProgress; ///< Flag indicates DAC Vref write is in progress. +static F32 syringePumpDACVref; ///< DAC Vref setting for force sensor. + static U08 lastSyringePumpADCReadCtr; ///< Remember last ADC read counter to check new reads are fresh. static SYRINGE_PUMP_SELF_TEST_STATE_T syringePumpSelfTestState; ///< Current syringe pump self-test state. static U32 syringePumpSelfTestTimerCount; ///< Timer counter for syringe pump self-test. // TODO - test code -static U32 xTimerCtr; +static U32 xTimerCtr; // ********** private function prototypes ********** static void resetSyringePumpRequestFlags( void ); static void execSyringePumpMonitor( void ); +static U32 getPublishSyringePumpDataInterval( void ); +static S32 getSyringePumpPosition( void ); +static F32 getSyringePumpMeasRate( void ); +static F32 getSyringePumpSyringeDetectorV( void ); +static F32 getSyringePumpHomeDetectorV( void ); +static F32 getSyringePumpForceV( void ); static SYRINGE_PUMP_STATE_T handleSyringePumpInitState( void ); static SYRINGE_PUMP_STATE_T handleSyringePumpOffState( void ); static SYRINGE_PUMP_STATE_T handleSyringePumpRetractState( void ); @@ -168,14 +200,15 @@ static SYRINGE_PUMP_STATE_T handleSyringePumpBolusState( void ); static SYRINGE_PUMP_STATE_T handleSyringePumpContinuousState( void ); static SYRINGE_PUMP_STATE_T handleSyringePumpCalibrateForceSensorState( void ); +static void calcStepperToggleTimeForTargetRate( F32 rate ); +static void calcMeasRate( void ); +static void calcSafetyVolumeDelivered( void ); +static BOOL checkOcclusionOrEmpty( BOOL stopPump ); +static BOOL checkSyringeRemoved( BOOL stopPump ); +static BOOL checkMaxTravel( BOOL stopPump, S32 maxPos ); +static BOOL checkMaxMeasRate( BOOL stopPump, F32 maxRate ); +static BOOL checkVolumeVsSafetyVolume( BOOL stopPump, F32 pctMargin ); static void publishSyringePumpData( void ); -static U32 getPublishSyringePumpDataInterval( void ); -static S32 getSyringePumpPosition( void ); -static F32 getSyringePumpVolumeDelivered( void ); -static F32 getSyringePumpMeasRate( void ); -static F32 getSyringePumpSyringeDetectorV( void ); -static F32 getSyringePumpHomeDetectorV( void ); -static F32 getSyringePumpForceV( void ); /*********************************************************************//** * @brief @@ -190,15 +223,16 @@ syringePumpSelfTestState = SYRINGE_PUMP_SELF_TEST_STATE_START; syringePumpSetRate = 0.0; - syringePumpSetSpeed = 0.0; - syringePumpMeasSpeed = 0.0; + syringePumpSetToggleTime = 0; syringePumpSafetyVolumeDelivered = 0.0; syringePumpHomePositionOffset = 0; + syringePumpPosition1SecAgo = 0; syringePumpHasBeenHomed = FALSE; syringePumpDataPublicationTimerCounter = 0; syringePumpSelfTestTimerCount = 0; + syringePumpSpeedCalcTimerCounter = 0; lastSyringePumpADCReadCtr = 0; @@ -220,6 +254,7 @@ syringePumpSeekToPrimeRequested = FALSE; syringePumpBolusRequested = FALSE; syringePumpContinuousRequested = FALSE; + syringePumpDACVrefSetRequested = FALSE; } /*********************************************************************//** @@ -247,7 +282,7 @@ { if ( ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) && ( FALSE == isSyringeDetected() ) ) { - syringePumpSetRate = 0.1; // SYRINGE_PUMP_RETRACT_RATE; + syringePumpSetRate = SYRINGE_PUMP_RETRACT_RATE; syringePumpRetractRequested = TRUE; } @@ -266,7 +301,7 @@ if ( ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) && ( TRUE == isSyringeDetected() ) && ( TRUE == isSyringePumpHome() ) ) { - syringePumpSetRate = 0.1; //SYRINGE_PUMP_SEEK_RATE; + syringePumpSetRate = SYRINGE_PUMP_SEEK_RATE; syringePumpPrimeRequested = TRUE; } @@ -329,6 +364,32 @@ /*********************************************************************//** * @brief + * The setSyringePumpDACVref function requests to set the DAC Vref setting. + * @details Inputs: none + * @details Outputs: syringePumpDACVrefSetRequested, syringePumpDACVref + * @param vRef voltage to set DAC Vref to (in V) + * @return TRUE if request accepted, FALSE if not + *************************************************************************/ +BOOL setSyringePumpDACVref( F32 vRef ) +{ + if ( ( vRef >= 0.0 ) && ( vRef <= 3.3 ) ) + { + if ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) + { + syringePumpDACVref = vRef; + syringePumpDACVrefSetRequested = TRUE; + } + } + else + { + // TODO - s/w fault + } + + return syringePumpDACVrefSetRequested; +} + +/*********************************************************************//** + * @brief * The getPublishSyringePumpDataInterval function gets the syringe pump data * publication interval. * @details Inputs: syringePumpDataPublishInterval @@ -355,7 +416,7 @@ * @details Outputs: none * @return the current syringe pump volume delivered (in mL). *************************************************************************/ -static F32 getSyringePumpVolumeDelivered( void ) +F32 getSyringePumpVolumeDelivered( void ) { F32 result = syringePumpVolumeDelivered.data; @@ -498,7 +559,7 @@ { BOOL result = FALSE; - if ( getSyringePumpHomeDetectorV() >= SYRINGE_PUMP_HOME_DETECT_THRESHOLD_V ) + if ( getSyringePumpHomeDetectorV() <= SYRINGE_PUMP_HOME_DETECT_THRESHOLD_V ) { result = TRUE; } @@ -508,6 +569,26 @@ /*********************************************************************//** * @brief + * The isSyringePumpStopped function determines whether the syringe pump + * is currently stopped. + * @details Inputs: syringePumpState + * @details Outputs: none + * @return TRUE if syringe pump is currently stopped, FALSE if running. + *************************************************************************/ +BOOL isSyringePumpStopped( void ) +{ + BOOL result = FALSE; + + if ( ( syringePumpState > SYRINGE_PUMP_OFF_STATE ) || ( syringePumpState < SYRINGE_PUMP_CONFIG_FORCE_SENSOR_STATE ) ) + { + 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 @@ -521,19 +602,27 @@ U08 adcReadCtr = getFPGASyringePumpADCReadCounter(); U08 adcDACStatus= getFPGASyringePumpADCandDACStatus(); - // get latest ADC data and convert to V + // 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; - // apply home offset to encoder position + // Apply home offset to encoder position syringePumpPosition.data = encPosition - syringePumpHomePositionOffset; + // Calculate volume delivered from position + syringePumpVolumeDelivered.data = (F32)(syringePumpPosition.data) / SYRINGE_ENCODER_COUNTS_PER_ML; + calcSafetyVolumeDelivered(); + // Calculate measured rate (mL/hr) + calcMeasRate(); - // check ADC read is fresh - if ( lastSyringePumpADCReadCtr == adcReadCtr ) + if ( syringePumpDACVrefWriteInProgress != TRUE ) { - // TODO - fault + // Check ADC read is fresh + if ( lastSyringePumpADCReadCtr == adcReadCtr ) + { + // TODO - fault + } + lastSyringePumpADCReadCtr = adcReadCtr; } - lastSyringePumpADCReadCtr = adcReadCtr; } /*********************************************************************//** @@ -587,14 +676,16 @@ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, 0, syringePumpState ) // TODO - replace 0 with appropriate enum break; } + + resetSyringePumpRequestFlags(); // Publish syringe pump data on interval publishSyringePumpData(); } /*********************************************************************//** * @brief - * The handleSyringePumpInitState function handles the pres/occl initialize state + * The handleSyringePumpInitState function handles the initialize state * of the syringe pump control state machine. * @details Inputs: TBD * @details Outputs: TBD @@ -616,7 +707,7 @@ /*********************************************************************//** * @brief - * The handleSyringePumpOffState function handles the pres/occl initialize state + * The handleSyringePumpOffState function handles the off state * of the syringe pump control state machine. * @details Inputs: TBD * @details Outputs: TBD @@ -650,8 +741,18 @@ { result = SYRINGE_PUMP_HEP_CONTINUOUS_STATE; } + else if ( TRUE == syringePumpDACVrefSetRequested ) + { + U16 vRef = (U16)( ( syringePumpDACVref / SYRINGE_PUMP_ADC_REF_V ) * SYRINGE_PUMP_DAC_FULL_SCALE_BITS ); - if ( result != SYRINGE_PUMP_OFF_STATE ) + setFPGASyringePumpDACOutputLevel( vRef ); + setFPGASyringePumpADCandDACControlFlags( SYRINGE_PUMP_ADC_DAC_CONTROL_ENABLE_DAC ); + syringePumpDACVrefWriteInProgress = TRUE; + result = SYRINGE_PUMP_CONFIG_FORCE_SENSOR_STATE; + } + + // If we are starting an active pump state, set direction and calculate target toggle time to achieve desired rate + if ( ( result != SYRINGE_PUMP_OFF_STATE ) && ( result != SYRINGE_PUMP_CONFIG_FORCE_SENSOR_STATE ) ) { if ( SYRINGE_PUMP_RETRACT_STATE == result ) { @@ -663,8 +764,9 @@ // Set fpga direction to forward setFPGASyringePumpControlFlags( SYRINGE_PUMP_CONTROL_RUN_FORWARD ); } - // Set fpga rate to set rate converted to microstep interval in uSec/2 - setFPGASyringePumpStepToggleTime( syringePumpSetRate ); // TODO - convert set rate (mL/hr) to miscrostep toggle time + // Calculate target FPGA rate from set rate in mL/hr converted to microstep toggle interval in uSec + calcStepperToggleTimeForTargetRate( syringePumpSetRate ); + setFPGASyringePumpStepToggleTime( syringePumpRampUpToggleTime ); } // TODO - test code @@ -675,7 +777,7 @@ /*********************************************************************//** * @brief - * The handleSyringePumpRetractState function handles the pres/occl initialize state + * The handleSyringePumpRetractState function handles the retract state * of the syringe pump control state machine. * @details Inputs: TBD * @details Outputs: TBD @@ -685,34 +787,40 @@ { 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 ) || ( getSyringePumpHomeDetectorV() > 3.0 ) || ( getSyringePumpSyringeDetectorV() < 1.0 ) ) - { // Retract reached home - setFPGASyringePumpStepToggleTime( SYRINGE_PUMP_MICROSTEP_TOGGLE_TIME_FOR_STOP ); - if ( TRUE == isSyringePumpHome() ) - { - syringePumpHomePositionOffset = getFPGASyringePumpEncoderPosition(); - syringePumpPosition.data = 0; - syringePumpVolumeDelivered.data = 0.0; - syringePumpHasBeenHomed = TRUE; - } - else - { - // TODO - alarm - } + // Handle ramp up + if ( syringePumpRampUpToggleTime > syringePumpSetToggleTime ) + { + syringePumpRampUpToggleTime *= SYRINGE_PUMP_RAMP_NUMERATOR; + syringePumpRampUpToggleTime /= SYRINGE_PUMP_RAMP_DENOMINATOR; + setFPGASyringePumpStepToggleTime( syringePumpRampUpToggleTime ); + } + else + { + setFPGASyringePumpStepToggleTime( syringePumpSetToggleTime ); + } + + if ( TRUE == isSyringePumpHome() ) + { + stopSyringePump(); + syringePumpHomePositionOffset = getFPGASyringePumpEncoderPosition(); + syringePumpPosition.data = 0; + syringePumpVolumeDelivered.data = 0.0; + syringePumpHasBeenHomed = TRUE; result = SYRINGE_PUMP_OFF_STATE; } else if ( TRUE == isSyringeDetected() ) { stopSyringePump(); + result = SYRINGE_PUMP_OFF_STATE; + // TODO - alarm } return result; } /*********************************************************************//** * @brief - * The handleSyringePumpSeekState function handles the pres/occl initialize state + * The handleSyringePumpSeekState function handles the seek plunger state * of the syringe pump control state machine. * @details Inputs: TBD * @details Outputs: TBD @@ -721,12 +829,39 @@ static SYRINGE_PUMP_STATE_T handleSyringePumpSeekState( void ) { SYRINGE_PUMP_STATE_T result = SYRINGE_PUMP_SEEK_STATE; + BOOL stopPump = FALSE; - if ( getSyringePumpForceV() <= SYRINGE_PUMP_PLUNGER_DETECT_THRESHOLD_V ) + // Handle ramp up + if ( syringePumpRampUpToggleTime > syringePumpSetToggleTime ) { - stopSyringePump(); + syringePumpRampUpToggleTime *= SYRINGE_PUMP_RAMP_NUMERATOR; + syringePumpRampUpToggleTime /= SYRINGE_PUMP_RAMP_DENOMINATOR; + setFPGASyringePumpStepToggleTime( syringePumpRampUpToggleTime ); + } + else + { + setFPGASyringePumpStepToggleTime( syringePumpSetToggleTime ); + } + + // Is plunger contact detected? + if ( ( ++xTimerCtr > 500 ) ) //|| ( getSyringePumpForceV() >= SYRINGE_FORCE_PLUNGER_THRESHOLD_V ) ) + { + stopPump = TRUE; syringePumpVolumeDelivered.data = 0.0; - syringePumpSeekToPrimeRequested = TRUE; +// syringePumpSeekToPrimeRequested = TRUE; + xTimerCtr = 0; + } + + // Has syringe been removed? + stopPump = checkSyringeRemoved( stopPump ); + + // Check for occlusion + stopPump = checkOcclusionOrEmpty( stopPump ); + + // If anything found that would require stopping the pump, stop pump and go to off state + if ( TRUE == stopPump ) + { + stopSyringePump(); result = SYRINGE_PUMP_OFF_STATE; } @@ -735,7 +870,7 @@ /*********************************************************************//** * @brief - * The handleSyringePumpPrimeState function handles the pres/occl initialize state + * The handleSyringePumpPrimeState function handles the prime state * of the syringe pump control state machine. * @details Inputs: TBD * @details Outputs: TBD @@ -744,11 +879,25 @@ static SYRINGE_PUMP_STATE_T handleSyringePumpPrimeState( void ) { SYRINGE_PUMP_STATE_T result = SYRINGE_PUMP_PRIME_STATE; + BOOL stopPump = FALSE; + // Has prime volume been delivered? if ( getSyringePumpVolumeDelivered() >= SYRINGE_PUMP_PRIME_VOLUME_ML ) { - stopSyringePump(); + stopPump = TRUE; syringePumpVolumeDelivered.data = 0.0; + } + + // Has syringe been removed? + stopPump = checkSyringeRemoved( stopPump ); + + // Check for occlusion + stopPump = checkOcclusionOrEmpty( stopPump ); + + // If anything found that would require stopping the pump, stop pump and go to off state + if ( TRUE == stopPump ) + { + stopSyringePump(); result = SYRINGE_PUMP_OFF_STATE; } @@ -757,7 +906,7 @@ /*********************************************************************//** * @brief - * The handleSyringePumpBolusState function handles the pres/occl initialize state + * The handleSyringePumpBolusState function handles the bolus delivery state * of the syringe pump control state machine. * @details Inputs: TBD * @details Outputs: TBD @@ -766,48 +915,33 @@ static SYRINGE_PUMP_STATE_T handleSyringePumpBolusState( void ) { SYRINGE_PUMP_STATE_T result = SYRINGE_PUMP_HEP_BOLUS_STATE; + BOOL stopPump = FALSE; + // Is bolus completed? + if ( getSyringePumpVolumeDelivered() >= 2.0 ) // TODO - get bolus volume from treatment params + { + stopPump = TRUE; + } + + // Has syringe been removed? + stopPump = checkSyringeRemoved( stopPump ); + + // TODO - check volume vs. safety volume (fault) + + // Check for occlusion + stopPump = checkOcclusionOrEmpty( stopPump ); + + // TODO - check for meas. speed > 1.05 mL/hr for TBD sec (fault) + + // If anything found that would require stopping the pump, stop pump and go to off state + if ( TRUE == stopPump ) + { + stopSyringePump(); + result = SYRINGE_PUMP_OFF_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 ); -//void setFPGASyringePumpStepToggleTime( U32 microSeconds ); -//U08 getFPGASyringePumpStatus( void ); -//U08 getFPGASyringePumpADCReadCounter( void ); -//U08 getFPGASyringePumpADCandDACStatus( void ); -//U08 getFPGASyringePumpEncoderStatus( void ); -//U32 getFPGASyringePumpEncoderPosition( void ); -//U16 getFPGASyringePumpADCChannel0( void ); -//U16 getFPGASyringePumpADCChannel1( void ); -//U16 getFPGASyringePumpADCChannel2( void ); -//U16 getFPGASyringePumpADCChannel3( void ); -//// 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). -//#define SYRINGE_PUMP_CONTROL_ENABLE 0x00 ///< Syringe pump control register bit mask for enable. -//#define SYRINGE_PUMP_CONTROL_DISABLE 0x10 ///< Syringe pump control register bit for enable (active low). -//#define SYRINGE_PUMP_CONTROL_REVERSE_DIR 0x08 ///< Syringe pump control register bit for direction (0=fwd, 1=rev). -//#define SYRINGE_PUMP_CONTROL_FORWARD_DIR 0x00 ///< Syringe pump control register bit mask for forward direction. -//#define SYRINGE_PUMP_CONTROL_32TH_STEP 0x03 ///< Syringe pump control register bits for 1/32 micro-stepping mode. -//// Bit definitions for syringe pump ADC/DAC control register -//#define SYRINGE_PUMP_ADC_DAC_CONTROL_WR_ADC_SETUP 0x04 ///< Syringe pump ADC/DAC control bit for re-write ADC setup registers to ADC. -//#define SYRINGE_PUMP_ADC_DAC_CONTROL_RD_DAC_ON_ADC 0x02 ///< Syringe pump ADC/DAC control bit for reading (once) DAC setting from device. -//#define SYRINGE_PUMP_ADC_DAC_CONTROL_ENABLE_DAC 0x01 ///< Syringe pump ADC/DAC control bit for write DAC setting to device (ADC reads are off). -//#define SYRINGE_PUMP_ADC_DAC_CONTROL_ENABLE_ADC 0x00 ///< Syringe pump ADC/DAC control bit mask for enable ADC reads. -//// Bit definitions for syringe pump ADC/DAC status register -//#define SYRINGE_PUMP_ADC_DAC_ERROR_COUNT_DAC_WR_DONE 0x80 ///< Syringe pump ADC/DAC error status bit for DAC write done. -//#define SYRINGE_PUMP_ADC_DAC_ERROR_COUNT_DAC_WR_ERROR 0x40 ///< Syringe pump ADC/DAC error status bit for DAC write error. -//#define SYRINGE_PUMP_ADC_DAC_ERROR_COUNT_MASK 0x3F ///< Syringe pump ADC/DAC error status count bit-mask. -//// Bit definitions for syringe pump encoder status register -//#define SYRINGE_PUMP_ENCODER_STATUS_DIRECTION 0x80 ///< Syringe pump encoder status direction bit (0-Fwd, 1=Rev). -//#define SYRINGE_PUMP_ENCODER_STATUS_ERROR_COUNT_MASK 0x3F ///< Syringe pump encoder status error count bit-mask. /*********************************************************************//** * @brief @@ -820,26 +954,221 @@ static SYRINGE_PUMP_STATE_T handleSyringePumpContinuousState( void ) { SYRINGE_PUMP_STATE_T result = SYRINGE_PUMP_HEP_CONTINUOUS_STATE; + BOOL stopPump = FALSE; + // Has syringe been removed? + stopPump = checkSyringeRemoved( stopPump ); + + // TODO - check volume vs. safety volume (fault) + + // Check for occlusion + stopPump = checkOcclusionOrEmpty( stopPump ); + + // TODO - check for meas. speed > 1.05 mL/hr for TBD sec (fault) + + // TODO - check position > max travel (alarm for empty syringe) + + // If anything found that would require stopping the pump, stop pump and go to off state + if ( TRUE == stopPump ) + { + stopSyringePump(); + result = SYRINGE_PUMP_OFF_STATE; + } + return result; } /*********************************************************************//** * @brief + * The checkOcclusionOrEmpty function checks the force sensor for excessive + * pressure. Would indicate occlusion or jam or empty syringe. + * @details Inputs: TBD + * @details Outputs: TBD + * @param stopPump flag passed in by caller indicating whether pump should be stopped + * @return TRUE if occlusion/empty condition detected, FALSE if not + *************************************************************************/ +static BOOL checkOcclusionOrEmpty( BOOL stopPump ) +{ + BOOL result = FALSE; + + if ( getSyringePumpForceV() >= SYRINGE_FORCE_OCCLUSION_THRESHOLD_V ) + { + result = TRUE; + // TODO - alarm (alarm for occlusion or empty syringe depending on position) + } + + 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. + * @details Inputs: TBD + * @details Outputs: TBD + * @param stopPump flag passed in by caller indicating whether pump should be stopped + * @return TRUE if syringe removed, FALSE if not + *************************************************************************/ +static BOOL checkSyringeRemoved( BOOL stopPump ) +{ + BOOL result = FALSE; + + if ( FALSE == isSyringeDetected() ) + { + result = TRUE; + // TODO - alarm + } + + return result; +} + +/*********************************************************************//** + * @brief + * The checkMaxTravel function checks whether a maximum travel (position) + * has been exceeded. This threshold is state dependent so the calling function + * must provide the maximum position to apply. + * @details Inputs: TBD + * @details Outputs: TBD + * @param stopPump flag passed in by caller indicating whether pump should be stopped + * @param maxPos maximum position allowed in current state + * @return TRUE if max travel exceeded, FALSE if not + *************************************************************************/ +static BOOL checkMaxTravel( BOOL stopPump, S32 maxPos ) +{ + BOOL result = FALSE; + + + + return result; +} + +/*********************************************************************//** + * @brief + * The checkMaxMeasRate function checks whether the measured rate is exceeding + * a maximum rate (in mL/hr). This threshold is state dependent so the calling + * function must provide the maximum rate to apply. + * @details Inputs: TBD + * @details Outputs: TBD + * @param stopPump flag passed in by caller indicating whether pump should be stopped + * @param maxRate maximum measured rate allowed in current state + * @return TRUE if max rate exceeded, FALSE if not +*************************************************************************/ +static BOOL checkMaxMeasRate( BOOL stopPump, F32 maxRate ) +{ + BOOL result = FALSE; + + + + return result; +} + +/*********************************************************************//** + * @brief + * The checkVolumeVsSafetyVolume function checks whether the volume delivered + * and the safety volume delivered have diverged too much. The threshold + * is state dependent so the calling function must provide the tolerance (in +/- %) + * to apply. + * @details Inputs: TBD + * @details Outputs: TBD + * @param stopPump flag passed in by caller indicating whether pump should be stopped + * @param pctMargin percent tolerance allowed between volume and safety volume + * @return TRUE if volume check fails, FALSE if not +*************************************************************************/ +static BOOL checkVolumeVsSafetyVolume( BOOL stopPump, F32 pctMargin ) +{ + BOOL result = FALSE; + + + + return result; +} + +/*********************************************************************//** + * @brief * The handleSyringePumpCalibrateForceSensorState function handles the * calibrate force sensor state of the syringe pump control state machine. * of the pressure/occlusion monitor state machine. - * @details Inputs: TBD - * @details Outputs: TBD + * @details Inputs: DAC status + * @details Outputs: syringePumpDACVrefWriteInProgress, ADC read mode restored * @return next state *************************************************************************/ static SYRINGE_PUMP_STATE_T handleSyringePumpCalibrateForceSensorState( void ) { SYRINGE_PUMP_STATE_T result = SYRINGE_PUMP_CONFIG_FORCE_SENSOR_STATE; + // Wait for DAC setting write to EEPROM to complete + if ( ( getFPGASyringePumpADCandDACStatus() & SYRINGE_PUMP_ADC_DAC_ERROR_COUNT_DAC_WR_DONE ) != 0 ) + { + syringePumpDACVrefWriteInProgress = FALSE; + // Switch back from DAC to ADC control + setFPGASyringePumpADCandDACControlFlags( SYRINGE_PUMP_ADC_DAC_CONTROL_RD_DAC_ON_ADC | SYRINGE_PUMP_ADC_DAC_CONTROL_ENABLE_ADC ); + // Back to off state + result = SYRINGE_PUMP_OFF_STATE; + } + return result; } +/*********************************************************************//** + * @brief + * The calcStepperToggleTimeForTargetRate function calculates the stepper + * toggle period for a given rate. + * @details Inputs: none + * @details Outputs: syringePumpSetToggleTime, syringePumpRampUpToggleTime + * @param rate the rate (in mL/hr) to calculate stepper toggle period for + * @return none + *************************************************************************/ +static void calcStepperToggleTimeForTargetRate( F32 rate ) +{ + F32 conv = 0.0; + + // 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 + 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; +} + +/*********************************************************************//** + * @brief + * The calcMeasRate function calculates the measured rate from a given delta + * position in last 10 ms. + * @details Inputs: syringePumpPosition1SecAgo, syringePumpSpeedCalcTimerCounter + * @details Outputs: syringePumpMeasRate, syringePumpSpeedCalcTimerCounter + * @return none + *************************************************************************/ +static void calcMeasRate( void ) +{ + if ( ++syringePumpSpeedCalcTimerCounter > SYRINGE_PUMP_SPEED_CHECK_INTERVAL ) + { + S32 countsPerSec = syringePumpMeasRate.data - syringePumpPosition1SecAgo; + S32 countsPerHr = countsPerSec * ( MIN_PER_HOUR * SEC_PER_MIN); + F32 mLPerHr = (F32)countsPerHr / SYRINGE_ENCODER_COUNTS_PER_ML; + + syringePumpMeasRate.data = mLPerHr; + syringePumpSpeedCalcTimerCounter = 0; + } +} + +/*********************************************************************//** + * @brief + * The calcSafetyVolumeDelivered function calculates the safety volume from + * commanded rate over time (last 10 ms). + * @details Inputs: syringePumpSetRate + * @details Outputs: syringePumpSafetyVolumeDelivered + * @return none + *************************************************************************/ +static void calcSafetyVolumeDelivered( void ) +{ + syringePumpSafetyVolumeDelivered += ( syringePumpSetRate / ( MIN_PER_HOUR * SEC_PER_MIN * ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ) ); +} + /*********************************************************************//** * @brief * The publishSyringePumpData function publishes syringe pump data at the Index: firmware/App/Controllers/SyringePump.h =================================================================== diff -u -r88fd90befbce61886ae47ad7d20ec863319cfa34 -racb165deff7036d41bbe12678f35cd9539012838 --- firmware/App/Controllers/SyringePump.h (.../SyringePump.h) (revision 88fd90befbce61886ae47ad7d20ec863319cfa34) +++ firmware/App/Controllers/SyringePump.h (.../SyringePump.h) (revision acb165deff7036d41bbe12678f35cd9539012838) @@ -54,9 +54,12 @@ BOOL primeSyringePump( void ); BOOL startHeparinBolus( F32 flowRate ); BOOL startHeparinContinuous( F32 flowRate ); +BOOL setSyringePumpDACVref( F32 vRef ); BOOL isSyringeDetected( void ); BOOL isSyringePumpHome( void ); +BOOL isSyringePumpStopped( void ); +F32 getSyringePumpVolumeDelivered( void ); SELF_TEST_STATUS_T execSyringePumpTest( void ); Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -r1afd5c87ef15399998a743c2ebcafe2cc03bd363 -racb165deff7036d41bbe12678f35cd9539012838 --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 1afd5c87ef15399998a743c2ebcafe2cc03bd363) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision acb165deff7036d41bbe12678f35cd9539012838) @@ -2232,7 +2232,7 @@ // Create a message record blankMessage( &msg ); msg.hdr.msgID = MSG_ID_USER_SALINE_BOLUS_RESPONSE; - msg.hdr.payloadLen = sizeof( BOOL ) + sizeof( U32 ) + sizeof( U32 ); + msg.hdr.payloadLen = sizeof( BOOL ) + sizeof( U32 ) + sizeof( U32 ) + sizeof( U32 ); memcpy( payloadPtr, &accepted, sizeof( BOOL ) ); payloadPtr += sizeof( BOOL ); @@ -3374,7 +3374,7 @@ memcpy( &payload, message->payload, sizeof(TEST_OVERRIDE_PAYLOAD_T) ); if ( FALSE == payload.reset ) { - result = testSetBloodPumpOcclusionOverride( payload.state.f32 ); + result = testSetBloodPumpOcclusionOverride( payload.state.u32 ); } else { @@ -3406,7 +3406,7 @@ memcpy( &payload, message->payload, sizeof(TEST_OVERRIDE_PAYLOAD_T) ); if ( FALSE == payload.reset ) { - result = testSetDialInPumpOcclusionOverride( payload.state.f32 ); + result = testSetDialInPumpOcclusionOverride( payload.state.u32 ); } else { @@ -3438,7 +3438,7 @@ memcpy( &payload, message->payload, sizeof(TEST_OVERRIDE_PAYLOAD_T) ); if ( FALSE == payload.reset ) { - result = testSetDialOutPumpOcclusionOverride( payload.state.f32 ); + result = testSetDialOutPumpOcclusionOverride( payload.state.u32 ); } else {