Index: firmware/App/Controllers/SyringePump.c =================================================================== diff -u -rcbaa57803fa8359407a799fca0cde6ae2c486bd7 -rd6709b7cdfe6d32b48520065ae5f3bccbeec2a74 --- firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision cbaa57803fa8359407a799fca0cde6ae2c486bd7) +++ firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision d6709b7cdfe6d32b48520065ae5f3bccbeec2a74) @@ -8,7 +8,7 @@ * @file SyringePump.c * * @author (last) Dara Navaei -* @date (last) 13-Jul-2022 +* @date (last) 22-Sep-2022 * * @author (original) Sean Nash * @date (original) 04-Mar-2021 @@ -88,6 +88,7 @@ #define TEN_PCT_OVER_ALLOWANCE 1.1F ///< Allow 10 percent over target before alarming on over travel. #define FIVE_PCT_OVER_ALLOWANCE 1.05F ///< Allow 5 percent over target before alarming on over travel. #define SYRINGE_PUMP_DAC_VOLTAGE_MAX_ERROR 0.05F ///< Force sensor POST check for DAC voltage - max delta. +#define MIN_SYRINGE_PUMP_RATE_FOR_DIR_ALARM 0.5F ///< Minimum measured rate (in mL/hr) required before enforcing direction alarm. /// Expected position of empty in relation to home position. #define SYRINGE_PUMP_EMPTY_POS ( SYRINGE_ENCODER_COUNTS_PER_ML * 10.84F ) @@ -153,6 +154,11 @@ #define SYRINGE_PUMP_RAMP_STALL_RETRIES 3 ///< Syringe pump ramp stall retries allowed. #define SYRINGE_PUMP_STALL_SPEED_THRESHOLD 0.05F ///< Minimum syringe pump speed to be considered not stalled. +#define SYRINGE_PUMP_ADC_FPGA_ERROR_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Syringe pump ADC FPGA error timeout in milliseconds. + +#define SYRINGE_PUMP_DAC_RETRIES 5 ///< Syringe pump DAC retries to write +#define SYRINGE_PUMP_DAC_TIMER ( 200 / TASK_PRIORITY_INTERVAL ) ///< Syringe pump DAC timer between retries + /// Defined states for the syringe pump control state machine. typedef enum SyringePump_States { @@ -227,6 +233,9 @@ static U32 syringePumpStallRetryCount; ///< Counts pump ramp up stall retries. static HD_HEPARIN_FORCE_SENSOR_CAL_RECORD_T forceSensorCalRecord; ///< HD heparin force sensor calibration record. +static U32 syringePumpDACRetryCount; +static U32 syringePumpDACRetryTimer; + // ********** private function prototypes ********** static void resetSyringePumpRequestFlags( void ); @@ -277,9 +286,7 @@ syringePumpState = SYRINGE_PUMP_INIT_STATE; heparinDeliveryState = HEPARIN_STATE_OFF; - requireSyringeDetection = FALSE; - syringePumpSetRate = 0.0; syringePumpSetToggleTime = 0; syringePumpSafetyVolumeDelivered = 0.0; @@ -317,6 +324,8 @@ syringePumpStallCtr = 0; syringePumpStallRetryCount = 0; + syringePumpDACRetryCount = 0; + syringePumpDACRetryTimer = 0; // Initialize persistent alarms initPersistentAlarm( ALARM_ID_HD_SYRINGE_PUMP_ADC_ERROR, 0, SYRINGE_PUMP_ADC_READ_PERSISTENCE ); @@ -490,24 +499,12 @@ *************************************************************************/ BOOL retractSyringePump( void ) { -#ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_ENABLE_SYRINGE_PUMP_CMDS ) == SW_CONFIG_ENABLE_VALUE ) + if ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) { - heparinDeliveryState = HEPARIN_STATE_STOPPED; + heparinDeliveryState = HEPARIN_STATE_STOPPED; + syringePumpSetRate = SYRINGE_PUMP_RETRACT_RATE; + syringePumpRetractRequested = TRUE; } -#endif - if ( MODE_SERV == getCurrentOperationMode() ) // Allow syringe pump operations in Service Mode. - { - heparinDeliveryState = HEPARIN_STATE_STOPPED; - } - if ( ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) && ( heparinDeliveryState != HEPARIN_STATE_OFF ) ) - { - { - heparinDeliveryState = HEPARIN_STATE_STOPPED; - syringePumpSetRate = SYRINGE_PUMP_RETRACT_RATE; - syringePumpRetractRequested = TRUE; - } - } return syringePumpRetractRequested; } @@ -660,8 +657,8 @@ F32 vRef = forceSensorCalRecord.hdHeparinForceSensorDACVoltage; if ( ( vRef >= 0.0 ) && ( vRef <= SYRINGE_PUMP_ADC_REF_V ) ) - { - if ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) + { // Cannot set DAC value if pump is busy or calibration values have not been provided yet + if ( ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) && ( forceSensorCalRecord.calibrationTime != 0 ) ) { syringePumpDACVref = vRef; syringePumpDACVrefSetRequested = TRUE; @@ -691,6 +688,28 @@ /*********************************************************************//** * @brief + * The syringePumpVerifyForceSensorDACCalibration function verifies that the + * syringe pump force sensor DAC has been calibrated and is reporting no force + * as would be expected when fully retracted (caller should not call this function + * until the syringe pump is homed first). + * @details Inputs: none + * @details Outputs: + * @return none + *************************************************************************/ +void syringePumpVerifyForceSensorDACCalibration( void ) +{ + F32 DACDeltaV = fabs( forceSensorCalRecord.hdHeparinForceSensorDACVoltage - getSyringePumpForceV() ); + + if ( DACDeltaV > SYRINGE_PUMP_DAC_VOLTAGE_MAX_ERROR ) + { + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_SYRINGE_PUMP_SELF_TEST_FAILURE, DACDeltaV ) + // In case DAC not set yet, try to set DAC + setSyringePumpDACVref(); + } +} + +/*********************************************************************//** + * @brief * The getSyringePumpVolumeDelivered function gets the current syringe pump * volume delivered. * @details Inputs: syringePumpVolumeDelivered @@ -1102,6 +1121,11 @@ isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_NOT_STOPPED_ERROR, FALSE ); } + if ( syringePumpDACRetryCount > 0 ) + { + syringePumpDACRetryTimer++; + } + // Execute syringe pump control state machine switch ( syringePumpState ) { @@ -1153,29 +1177,29 @@ * The execSyringePumpSelfTest function executes the state machine for the * syringe pump self-test. * @details Inputs: none - * @details Outputs: none - * @return the current state of the BloodFlow self-test. + * @details Outputs: forceSensorCalRecord + * @return TRUE if the self test passed otherwise, FALSE *************************************************************************/ SELF_TEST_STATUS_T execSyringePumpSelfTest( void ) { - SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; - F32 DACDeltaV; + SELF_TEST_STATUS_T result = SELF_TEST_STATUS_PASSED; // Read/check force sensor calibration BOOL calStatus = getNVRecord2Driver( GET_CAL_HEPARIN_FORCE_SENSOR, (U08*)&forceSensorCalRecord, sizeof( HD_HEPARIN_FORCE_SENSOR_CAL_RECORD_T ), 0, ALARM_ID_HD_HEPARIN_FORCE_SENSOR_INVALID_CAL_RECORD ); - // Verify calibration - DACDeltaV = fabs( forceSensorCalRecord.hdHeparinForceSensorDACVoltage - getSyringePumpForceV() ); - - if ( ( TRUE == calStatus ) && ( DACDeltaV > SYRINGE_PUMP_DAC_VOLTAGE_MAX_ERROR ) ) +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_SYRINGE_PUMP_ALARMS ) != SW_CONFIG_ENABLE_VALUE ) +#endif { - result = SELF_TEST_STATUS_PASSED; + if ( TRUE == calStatus ) + { + result = SELF_TEST_STATUS_PASSED; + } + else + { + result = SELF_TEST_STATUS_FAILED; + } } - else - { - result = SELF_TEST_STATUS_FAILED; - activateAlarmNoData( ALARM_ID_HD_SYRINGE_PUMP_SELF_TEST_FAILURE ); - } return result; } @@ -1260,14 +1284,17 @@ sendTreatmentLogEventData( HEPARIN_START_RESUME_EVENT, 0.0, syringePumpSetRate ); result = SYRINGE_PUMP_HEP_CONTINUOUS_STATE; } - else if ( TRUE == syringePumpDACVrefSetRequested ) + else if ( TRUE == syringePumpDACVrefSetRequested || + ( syringePumpDACRetryCount > 0 && syringePumpDACRetryTimer > SYRINGE_PUMP_DAC_TIMER ) ) { U16 vRef = (U16)( ( syringePumpDACVref / SYRINGE_PUMP_ADC_REF_V ) * SYRINGE_PUMP_DAC_FULL_SCALE_BITS ); 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 @@ -1576,21 +1603,56 @@ SYRINGE_PUMP_STATE_T result = SYRINGE_PUMP_CONFIG_FORCE_SENSOR_STATE; U08 adcDACStatus = getSyringePumpADCandDACStatus(); + // Check DAC write error + if ( ( adcDACStatus & SYRINGE_PUMP_DAC_WRITE_ERROR_BIT ) != 0 ) + { + + syringePumpDACRetryCount++; + + + if ( syringePumpDACRetryCount > SYRINGE_PUMP_DAC_RETRIES ) + { + syringePumpDACRetryCount = 0; + activateAlarmNoData( ALARM_ID_HD_SYRINGE_PUMP_DAC_WRITE_ERROR ); + } + + 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; + } + // Wait for DAC setting write to EEPROM to complete - if ( ( adcDACStatus & SYRINGE_PUMP_ADC_DAC_ERROR_COUNT_DAC_WR_DONE ) != 0 ) + else if ( ( adcDACStatus & SYRINGE_PUMP_ADC_DAC_ERROR_COUNT_DAC_WR_DONE ) != 0 ) { + // We're done and no error bit found. + // Clear retry attempts. + syringePumpDACRetryCount = 0; + syringePumpDACRetryTimer = 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; } - // Check DAC write error - else if ( ( adcDACStatus & SYRINGE_PUMP_DAC_WRITE_ERROR_BIT ) != 0 ) +/* + * + * #define SYRINGE_LENGTH 20 +static BOOL syringeTick; +static U32 syringepumpDACstatus[SYRINGE_LENGTH]; +static U32 syringeReadingIDX = 0; + syringepumpDACstatus[syringeReadingIDX] = getSyringePumpADCandDACStatus(); + syringeReadingIDX++; + syringepumpDACstatus[i] = 0xFFFF; + if (syringeReadingIDX == SYRINGE_LENGTH) { - activateAlarmNoData( ALARM_ID_HD_SYRINGE_PUMP_DAC_WRITE_ERROR ); + syringePumpDACVrefWriteInProgress = FALSE; + setFPGASyringePumpADCandDACControlFlags( SYRINGE_PUMP_ADC_DAC_CONTROL_RD_DAC_ON_ADC | SYRINGE_PUMP_ADC_DAC_CONTROL_ENABLE_ADC ); + syringeReadingIDX = 0; + result = SYRINGE_PUMP_OFF_STATE; } - + */ return result; } @@ -1612,15 +1674,24 @@ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_SYRINGE_PUMP_ALARMS ) != SW_CONFIG_ENABLE_VALUE ) #endif { - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_ENCODER_DIRECTION_ERROR, ( syringePumpEncoderMeasuredDirection != expDir ) ) ) + // Check direction if rate >= minimum for alarm + if ( getSyringePumpMeasRate() >= MIN_SYRINGE_PUMP_RATE_FOR_DIR_ALARM ) { - result = TRUE; - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SYRINGE_PUMP_ENCODER_DIRECTION_ERROR, (U32)syringePumpEncoderMeasuredDirection, (U32)syringePumpState ); + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_ENCODER_DIRECTION_ERROR, ( syringePumpEncoderMeasuredDirection != expDir ) ) ) + { + result = TRUE; + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SYRINGE_PUMP_ENCODER_DIRECTION_ERROR, (U32)syringePumpEncoderMeasuredDirection, (U32)syringePumpState ); + } + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_CONTROLLER_DIRECTION_ERROR, ( syringePumpControllerMeasuredDirection != expDir ) ) ) + { + result = TRUE; + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SYRINGE_PUMP_CONTROLLER_DIRECTION_ERROR, (U32)syringePumpControllerMeasuredDirection, (U32)syringePumpState ); + } } - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_CONTROLLER_DIRECTION_ERROR, ( syringePumpControllerMeasuredDirection != expDir ) ) ) + else { - result = TRUE; - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SYRINGE_PUMP_CONTROLLER_DIRECTION_ERROR, (U32)syringePumpControllerMeasuredDirection, (U32)syringePumpState ); + isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_ENCODER_DIRECTION_ERROR, FALSE ); + isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_CONTROLLER_DIRECTION_ERROR, FALSE ); } } @@ -1978,12 +2049,12 @@ } } - -/************************************************************************* - * TEST SUPPORT FUNCTIONS - *************************************************************************/ +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + /*********************************************************************//** * @brief * The testSetSyringePumpDataPublishIntervalOverride function overrides the