Index: firmware/App/Controllers/BloodFlow.c =================================================================== diff -u -r24b2fe72608344e67ef37234085d15ad5e4fcc37 -r54da0840ade5bf0ec6c50232fe952cc98ca314f5 --- firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 24b2fe72608344e67ef37234085d15ad5e4fcc37) +++ firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 54da0840ade5bf0ec6c50232fe952cc98ca314f5) @@ -7,8 +7,8 @@ * * @file BloodFlow.c * -* @author (last) Sean Nash -* @date (last) 15-Nov-2021 +* @author (last) Dara Navaei +* @date (last) 15-Jun-2022 * * @author (original) Sean Nash * @date (original) 07-Nov-2019 @@ -44,18 +44,18 @@ /// Interval (ms/task time) at which the blood flow data is published on the CAN bus. #define BLOOD_FLOW_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) -#define MAX_BLOOD_PUMP_PWM_STEP_UP_CHANGE 0.008 ///< Max duty cycle change when ramping up ~ 100 mL/min/s. -#define MAX_BLOOD_PUMP_PWM_STEP_DN_CHANGE 0.016 ///< Max duty cycle change when ramping down ~ 200 mL/min/s. -#define MAX_BLOOD_PUMP_PWM_DUTY_CYCLE 0.89 ///< Controller will error if PWM duty cycle > 90%, so set max to 89% -#define MIN_BLOOD_PUMP_PWM_DUTY_CYCLE 0.10 ///< Controller will error if PWM duty cycle < 10%, so set min to 10% +#define MAX_BLOOD_PUMP_PWM_STEP_UP_CHANGE 0.008F ///< Max duty cycle change when ramping up ~ 100 mL/min/s. +#define MAX_BLOOD_PUMP_PWM_STEP_DN_CHANGE 0.016F ///< Max duty cycle change when ramping down ~ 200 mL/min/s. +#define MAX_BLOOD_PUMP_PWM_DUTY_CYCLE 0.89F ///< Controller will error if PWM duty cycle > 90%, so set max to 89% +#define MIN_BLOOD_PUMP_PWM_DUTY_CYCLE 0.10F ///< Controller will error if PWM duty cycle < 10%, so set min to 10% #define BP_CONTROL_INTERVAL_SEC 10 ///< Blood pump control interval (in seconds). /// Interval (ms/task time) at which the blood pump is controlled. static const U32 BP_CONTROL_INTERVAL = ( BP_CONTROL_INTERVAL_SEC * MS_PER_SECOND / TASK_GENERAL_INTERVAL ); -#define BP_P_COEFFICIENT 0.0001 ///< P term for blood pump control -#define BP_I_COEFFICIENT 0.00075 ///< I term for blood pump control +#define BP_P_COEFFICIENT 0.0001F ///< P term for blood pump control +#define BP_I_COEFFICIENT 0.00075F ///< I term for blood pump control #define BP_HOME_RATE 100 ///< Target pump speed (in estimate mL/min) for homing. #define BP_HOME_TIMEOUT_MS 10000 ///< Maximum time (in ms) allowed for homing to complete. @@ -67,17 +67,14 @@ /// Number of hall sensor counts kept in buffer to hold last 1 second of count data. #define BP_SPEED_CALC_BUFFER_LEN ( MS_PER_SECOND / BP_SPEED_CALC_INTERVAL / TASK_PRIORITY_INTERVAL ) -#define BP_MAX_ROTOR_SPEED_RPM 100.0 ///< Maximum rotor speed allowed for blood pump. +#define BP_MAX_ROTOR_SPEED_RPM 100.0F ///< Maximum rotor speed allowed for blood pump. -#define BP_MAX_FLOW_RATE 1320.0 ///< Maximum measured BP flow rate allowed. -#define BP_MIN_FLOW_RATE -1320.0 ///< Minimum measured BP flow rate allowed. -#define BP_MAX_MOTOR_SPEED_WHILE_OFF_RPM 100.0 ///< Maximum motor speed (RPM) while motor is commanded off. -#define BP_MAX_ROTOR_VS_MOTOR_DIFF_RPM 5.0 ///< Maximum difference in speed between motor and rotor (in rotor RPM). -#define BP_MAX_MOTOR_SPEED_ERROR_RPM 300.0 ///< Maximum difference in speed between measured and commanded RPM. -#define BP_MAX_FLOW_VS_SPEED_DIFF_RPM 200.0 ///< Maximum difference between measured speed and speed implied by measured flow. +#define BP_MAX_FLOW_RATE 1320.0F ///< Maximum measured BP flow rate allowed. +#define BP_MIN_FLOW_RATE -1320.0F ///< Minimum measured BP flow rate allowed. +#define BP_MAX_MOTOR_SPEED_WHILE_OFF_RPM 100.0F ///< Maximum motor speed (RPM) while motor is commanded off. +#define BP_MAX_ROTOR_VS_MOTOR_DIFF_RPM 5.0F ///< Maximum difference in speed between motor and rotor (in rotor RPM). +#define BP_MAX_MOTOR_SPEED_ERROR_RPM 300.0F ///< Maximum difference in speed between measured and commanded RPM. -/// Persist time (task intervals) for flow vs. motor speed error condition. -static const U32 BP_FLOW_VS_SPEED_PERSIST = ( 5 * MS_PER_SECOND ); /// Persist time (task intervals) for motor off error condition. static const U32 BP_OFF_ERROR_PERSIST = ( 5 * MS_PER_SECOND ); /// Persist time (task intervals) motor speed error condition. @@ -89,41 +86,46 @@ /// Persist time period blood pump rotor speed too fast error condition. static const U32 BP_MAX_ROTOR_SPEED_ERROR_PERSIST = ( 1 * MS_PER_SECOND ); /// Persist time (task intervals) blood flow rate out of range error condition. -static const U32 BP_MAX_FLOW_RATE_OUT_OF_RANGE_PERSIST = ((1 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL); +static const U32 BP_MAX_FLOW_RATE_OUT_OF_RANGE_PERSIST = (1 * MS_PER_SECOND); -#define BP_MAX_CURR_WHEN_STOPPED_MA 150.0 ///< Motor controller current should not exceed this when pump should be stopped. -#define BP_MAX_CURR_WHEN_RUNNING_MA 2000.0 ///< Motor controller current should not exceed this when pump should be running. +#define BP_MAX_CURR_WHEN_STOPPED_MA 150.0F ///< Motor controller current should not exceed this when pump should be stopped. +#define BP_MAX_CURR_WHEN_RUNNING_MA 2000.0F ///< Motor controller current should not exceed this when pump should be running. #define BP_MAX_CURR_ERROR_DURATION_MS 2000 ///< Motor controller current errors persisting beyond this duration will trigger an alarm. -#define BP_SPEED_ADC_TO_RPM_FACTOR 1.751752 ///< Conversion factor from ADC counts to RPM for blood pump motor. -#define BP_MOTOR_RPM_TO_PWM_DC_FACTOR 0.000238 ///< ~42 BP motor RPM = 1% PWM duty cycle. -#define BP_CURRENT_ADC_TO_MA_FACTOR 3.002 ///< Conversion factor from ADC counts to mA for blood pump motor. +#define BLOODPUMP_ADC_FULL_SCALE_V 3.0F ///< BP analog signals are 0-3V (while int. ADC ref may be different). +#define BLOODPUMP_ADC_ZERO 1998 ///< Blood pump ADC channel zero offset. + +/// Macro converts 12 bit ADC value to signed 16-bit value. +#define SIGN_FROM_12_BIT_VALUE(v) ( (S16)(v) - (S16)BLOODPUMP_ADC_ZERO ) + +#define BP_SPEED_ADC_TO_RPM_FACTOR 1.751752F ///< Conversion factor from ADC counts to RPM for blood pump motor (3500 RPM/1998 counts). +#define BP_MOTOR_RPM_TO_PWM_DC_FACTOR 0.000238F ///< ~42 BP motor RPM = 1% PWM duty cycle. +#define BP_CURRENT_ADC_TO_MA_FACTOR 3.002F ///< Conversion factor from ADC counts to mA for blood pump motor. -#define BP_REV_PER_LITER 146.84 ///< Rotor revolutions per liter. -#define BP_ML_PER_ROTOR_REV 6.81 ///< Milliliters per rotor revolusion. +#define BP_REV_PER_LITER 146.84F ///< Rotor revolutions per liter. +#define BP_ML_PER_ROTOR_REV 6.81F ///< Milliliters per rotor revolusion. #define BP_ML_PER_MIN_TO_PUMP_RPM_FACTOR ( BP_REV_PER_LITER / ML_PER_LITER ) ///< Conversion factor from mL/min to motor RPM. -#define BP_GEAR_RATIO 32.0 ///< Blood pump motor to blood pump gear ratio. -#define BP_PWM_ZERO_OFFSET 0.1 ///< 10 pct PWM duty cycle = zero speed. +#define BP_GEAR_RATIO 32.0F ///< Blood pump motor to blood pump gear ratio. +#define BP_PWM_ZERO_OFFSET 0.1F ///< 10 pct PWM duty cycle = zero speed. /// Conversion macro from mL/min to estimated PWM duty cycle %. #define BP_PWM_FROM_ML_PER_MIN(rate) ( (rate) * BP_ML_PER_MIN_TO_PUMP_RPM_FACTOR * BP_GEAR_RATIO * BP_MOTOR_RPM_TO_PWM_DC_FACTOR + BP_PWM_ZERO_OFFSET ) /// Conversion from PWM duty cycle % to commanded pump motor speed. -#define BP_PWM_TO_MOTOR_SPEED_RPM(pwm) ( ((pwm) - BP_PWM_ZERO_OFFSET) * 4000.0 ) +#define BP_PWM_TO_MOTOR_SPEED_RPM(pwm) ( ((pwm) - BP_PWM_ZERO_OFFSET) * 4000.0F ) -#define BLOODPUMP_ADC_FULL_SCALE_V 3.0 ///< BP analog signals are 0-3V (while int. ADC ref may be different). -#define BLOODPUMP_ADC_ZERO 1998 ///< Blood pump ADC channel zero offset. -/// Macro converts 12 bit ADC value to signed 16-bit value. -#define SIGN_FROM_12_BIT_VALUE(v) ( (S16)(v) - (S16)BLOODPUMP_ADC_ZERO ) - /// Measured blood flow is filtered w/ moving average. #define SIZE_OF_ROLLING_AVG ( ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) * 1 ) #define PUMP_DIR_ERROR_COUNT_MASK 0x3F ///< Bit mask for pump direction error counter. +#define BP_MIN_DIR_CHECK_SPEED_RPM 10.0F ///< Minimum motor speed before we check pump direction. +#define BP_COMMUTATION_ERROR_MAX_CNT 3 ///< Maximum number of commutation errors within time window before alarm triggered. +#define BP_COMMUTATION_ERROR_TIME_WIN_MS (15 * MS_PER_SECOND) ///< Time window for BP commutation error. -#define BP_FLOW_ALPHA_Y_INTERCEPT 1.218 ///< Y intercept used for alpha flow coefficient calculation. -#define BP_FLOW_WEAR_A_TERM 0.000000007474 ///< A term used for wear portion of alpha flow coefficient. -#define BP_FLOW_WEAR_B_TERM 0.0006053 ///< B term used for wear portion of alpha flow coefficient. +#define BP_FLOW_ALPHA_Y_INTERCEPT 1.1970F ///< Y intercept used for alpha flow coefficient calculation. +#define BP_FLOW_WEAR_A_TERM 0.000000029F ///< A term used for wear portion of alpha flow coefficient. +#define BP_FLOW_WEAR_B_TERM 0.00055F ///< B term used for wear portion of alpha flow coefficient. #define BP_MAX_ROTOR_COUNT_FOR_WEAR 25000 ///< Maximum rotor count for determining wear of the cartridge (negligible affect beyond this threshold). +#define DATA_PUBLISH_COUNTER_START_COUNT 20 ///< Data publish counter start count. /// Enumeration of blood pump controller states. typedef enum BloodPump_States @@ -156,7 +158,7 @@ // ********** private data ********** static BLOOD_PUMP_STATE_T bloodPumpState = BLOOD_PUMP_OFF_STATE; ///< Current state of blood flow controller state machine -static U32 bloodFlowDataPublicationTimerCounter = 0; ///< Used to schedule blood flow data publication to CAN bus +static U32 bloodFlowDataPublicationTimerCounter; ///< Used to schedule blood flow data publication to CAN bus static BOOL isBloodPumpOn = FALSE; ///< Blood pump is currently running static F32 bloodPumpPWMDutyCyclePct = 0.0; ///< Initial blood pump PWM duty cycle static F32 bloodPumpPWMDutyCyclePctSet = 0.0; ///< Currently set blood pump PWM duty cycle @@ -193,6 +195,7 @@ static U16 bpLastMotorHallSensorCounts[ BP_SPEED_CALC_BUFFER_LEN ]; ///< Last hall sensor readings for the blood pump motor static U32 bpMotorSpeedCalcIdx = 0; ///< Index into 1 second buffer of motor speed hall sensor counts static U32 bpMotorSpeedCalcTimerCtr = 0; ///< Counter determines interval for calculating blood pump motor speed from hall sensor count. +static HD_PUMPS_CAL_RECORD_T bloodPumpCalRecord; ///< Blood pump calibration record. // ********** private function prototypes ********** @@ -220,14 +223,16 @@ * @brief * The initBloodFlow function initializes the BloodFlow module. * @details Inputs: none - * @details Outputs: BloodFlow module initialized. + * @details Outputs: bloodFlowDataPublicationTimerCounter * @return none *************************************************************************/ void initBloodFlow( void ) { U32 i; + + bloodFlowDataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; - stopBloodPump(); + signalBloodPumpHardStop(); setBloodPumpDirection( MOTOR_DIR_FORWARD ); // Zero rolling pump speed average buffer @@ -237,7 +242,7 @@ bpMotorSpeedCalcIdx = 0; for ( i = 0; i < BP_SPEED_CALC_BUFFER_LEN; i++ ) { - bpLastMotorHallSensorCounts[ i ] = 0; + bpLastMotorHallSensorCounts[ i ] = getFPGABloodPumpHallSensorCount(); } resetBloodPumpRotorCount(); @@ -251,9 +256,9 @@ initPersistentAlarm( ALARM_ID_BLOOD_PUMP_MOTOR_SPEED_CHECK, 0, BP_MOTOR_SPEED_ERROR_PERSIST ); initPersistentAlarm( ALARM_ID_BLOOD_PUMP_ROTOR_SPEED_CHECK, 0, BP_ROTOR_SPEED_ERROR_PERSIST ); initPersistentAlarm( ALARM_ID_BLOOD_PUMP_MC_DIRECTION_CHECK, 0, BP_DIRECTION_ERROR_PERSIST ); + initTimeWindowedCount( TIME_WINDOWED_COUNT_BP_COMMUTATION_ERROR, BP_COMMUTATION_ERROR_MAX_CNT, BP_COMMUTATION_ERROR_TIME_WIN_MS ); initPersistentAlarm( ALARM_ID_BLOOD_PUMP_ROTOR_SPEED_TOO_HIGH, 0, BP_MAX_ROTOR_SPEED_ERROR_PERSIST ); initPersistentAlarm( ALARM_ID_BLOOD_PUMP_MC_CURRENT_CHECK, 0, BP_MAX_CURR_ERROR_DURATION_MS ); - initPersistentAlarm( ALARM_ID_BLOOD_PUMP_FLOW_VS_MOTOR_SPEED_CHECK, 0, BP_FLOW_VS_SPEED_PERSIST ); initPersistentAlarm( ALARM_ID_HD_BLOOD_FLOW_OUT_OF_RANGE, 0, BP_MAX_FLOW_RATE_OUT_OF_RANGE_PERSIST ); } @@ -274,58 +279,74 @@ // Direction change while pump is running is not allowed if ( ( FALSE == isBloodPumpOn ) || ( 0 == flowRate ) || ( dir == bloodPumpDirectionSet ) ) - { -#ifndef NO_PUMP_FLOW_LIMITS - // Verify flow rate - if ( flowRate <= MAX_SET_BLOOD_FLOW_RATE ) + { + S32 dirFlowRate = ( dir == MOTOR_DIR_FORWARD ? (S32)flowRate : (S32)flowRate * -1 ); + + // Don't interrupt pump control unless rate or mode is changing + if ( ( dirFlowRate != targetBloodFlowRate ) || ( mode != bloodPumpControlMode ) ) + { + BOOL isFlowInrange = ( flowRate <= MAX_SET_BLOOD_FLOW_RATE ? TRUE : FALSE ); + +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_PUMPS_FLOW_LIMITS ) ) + { + isFlowInrange = TRUE; + } #endif - { - resetBloodPumpRPMMovingAverage(); - targetBloodFlowRate = ( dir == MOTOR_DIR_FORWARD ? (S32)flowRate : (S32)flowRate * -1 ); - bloodPumpDirection = dir; - bloodPumpControlMode = mode; - // Set PWM duty cycle target to an estimated initial target to ramp to based on target flow rate - then we will control to flow when ramp completed - bloodPumpPWMDutyCyclePct = BP_PWM_FROM_ML_PER_MIN((F32)flowRate); // ~ 8% per 100 mL/min with a 10% zero offset added in (e.g. 100 mL/min = 8+10 = 18%) - - switch ( bloodPumpState ) + // Verify flow rate of if the bypass flow limit has been enabled + if ( TRUE == isFlowInrange ) { - case BLOOD_PUMP_RAMPING_UP_STATE: // See if we need to reverse direction of ramp - if ( bloodPumpPWMDutyCyclePct < bloodPumpPWMDutyCyclePctSet ) - { - bloodPumpState = BLOOD_PUMP_RAMPING_DOWN_STATE; - } - break; + resetBloodPumpRPMMovingAverage(); + targetBloodFlowRate = dirFlowRate; + bloodPumpDirection = dir; + bloodPumpControlMode = mode; + // Set PWM duty cycle target to an estimated initial target to ramp to based on target flow rate - then we will control to flow when ramp completed + bloodPumpPWMDutyCyclePct = BP_PWM_FROM_ML_PER_MIN((F32)flowRate); // ~ 8% per 100 mL/min with a 10% zero offset added in (e.g. 100 mL/min = 8+10 = 18%) - case BLOOD_PUMP_RAMPING_DOWN_STATE: // See if we need to reverse direction of ramp - if ( bloodPumpPWMDutyCyclePct > bloodPumpPWMDutyCyclePctSet ) - { - bloodPumpState = BLOOD_PUMP_RAMPING_UP_STATE; - } - break; + switch ( bloodPumpState ) + { + case BLOOD_PUMP_RAMPING_UP_STATE: // See if we need to reverse direction of ramp + if ( bloodPumpPWMDutyCyclePct < bloodPumpPWMDutyCyclePctSet ) + { + bloodPumpState = BLOOD_PUMP_RAMPING_DOWN_STATE; + } + break; - case BLOOD_PUMP_CONTROL_TO_TARGET_STATE: // Start ramp to new target in appropriate direction - if ( bloodPumpPWMDutyCyclePctSet > bloodPumpPWMDutyCyclePct ) - { - bloodPumpState = BLOOD_PUMP_RAMPING_DOWN_STATE; - } - else - { - bloodPumpState = BLOOD_PUMP_RAMPING_UP_STATE; - } - break; + case BLOOD_PUMP_RAMPING_DOWN_STATE: // See if we need to reverse direction of ramp + if ( bloodPumpPWMDutyCyclePct > bloodPumpPWMDutyCyclePctSet ) + { + bloodPumpState = BLOOD_PUMP_RAMPING_UP_STATE; + } + break; - default: - // Ok - not all states need to be handled here - break; + case BLOOD_PUMP_CONTROL_TO_TARGET_STATE: // Start ramp to new target in appropriate direction + if ( bloodPumpPWMDutyCyclePctSet > bloodPumpPWMDutyCyclePct ) + { + bloodPumpState = BLOOD_PUMP_RAMPING_DOWN_STATE; + } + else + { + bloodPumpState = BLOOD_PUMP_RAMPING_UP_STATE; + } + break; + + default: + // Ok - not all states need to be handled here + break; + } + result = TRUE; } - result = TRUE; + + else // Requested flow rate too high + { +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PUMPS_FLOW_LIMITS ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_BLOOD_FLOW_SET_TOO_HIGH, flowRate ) + } + } } -#ifndef NO_PUMP_FLOW_LIMITS - else // Requested flow rate too high - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_BLOOD_FLOW_SET_TOO_HIGH, flowRate ) - } -#endif } return result; @@ -344,12 +365,8 @@ { F32 artPres = getLongFilteredArterialPressure(); F32 rotSpd = filteredBloodPumpSpeed / BP_GEAR_RATIO; -#ifndef WORN_OUT_CARTRIDGE U32 r = getBloodPumpRotorCount(); U32 rotCnt = CAP( r, BP_MAX_ROTOR_COUNT_FOR_WEAR ); -#else - U32 rotCnt = BP_MAX_ROTOR_COUNT_FOR_WEAR; -#endif F32 wear = BP_FLOW_WEAR_A_TERM * (F32)rotCnt + BP_FLOW_WEAR_B_TERM; F32 alpha = wear * artPres + BP_FLOW_ALPHA_Y_INTERCEPT; F32 flow = alpha * BP_ML_PER_ROTOR_REV * rotSpd; @@ -369,7 +386,7 @@ targetBloodFlowRate = 0; stopBloodPump(); bloodPumpState = BLOOD_PUMP_OFF_STATE; - bloodPumpPWMDutyCyclePct = 0.0; + bloodPumpPWMDutyCyclePct = BP_PWM_ZERO_OFFSET; bpControlTimerCounter = 0; resetPIController( PI_CONTROLLER_ID_BLOOD_FLOW, MIN_BLOOD_PUMP_PWM_DUTY_CYCLE ); } @@ -472,6 +489,21 @@ /*********************************************************************//** * @brief + * The isBloodPumpRampComplete function returns whether the blood pump has + * completed its ramp up and entered control state (closed or open loop). + * @details Inputs: bloodPumpState + * @details Outputs: none + * @return TRUE if pump is in control state, FALSE if not + *************************************************************************/ +BOOL isBloodPumpRampComplete( void ) +{ + BOOL result = ( BLOOD_PUMP_CONTROL_TO_TARGET_STATE == bloodPumpState ? TRUE : FALSE ); + + return result; +} + +/*********************************************************************//** + * @brief * The resetBloodPumpRotorCount function resets the blood pump rotor counter * that is a proxy for cartridge wear. Call this function after a new cartridge * has been installed. @@ -481,7 +513,16 @@ *************************************************************************/ void resetBloodPumpRotorCount( void ) { - bloodPumpRotorCounter.data = 0; +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_ENABLE_WORN_OUT_CARTRIDGE ) != SW_CONFIG_ENABLE_VALUE ) + { + bloodPumpRotorCounter.data = 0; + } + else +#endif + { + bloodPumpRotorCounter.data = BP_MAX_ROTOR_COUNT_FOR_WEAR; + } } /*********************************************************************//** @@ -520,6 +561,10 @@ // Check for home position, zero/low speed checkBloodPumpRotor(); } + else + { + lastBloodPumpDirectionCount = getFPGABloodPumpHallSensorStatus() & PUMP_DIR_ERROR_COUNT_MASK; + } // Publish blood flow data on interval publishBloodFlowData(); @@ -642,7 +687,7 @@ // Have we essentially reached zero speed? if ( bloodPumpPWMDutyCyclePctSet < (MAX_BLOOD_PUMP_PWM_STEP_DN_CHANGE + BP_PWM_ZERO_OFFSET) ) { - stopBloodPump(); + signalBloodPumpHardStop(); result = BLOOD_PUMP_OFF_STATE; } // Have we reached end of ramp down? @@ -963,7 +1008,7 @@ U16 last = bpLastMotorHallSensorCounts[ bpMotorSpeedCalcIdx ]; U32 nextIdx = INC_WRAP( bpMotorSpeedCalcIdx, 0, BP_SPEED_CALC_BUFFER_LEN - 1 ); U16 incDelta = u16DiffWithWrap( bpLastMotorHallSensorCounts[ nextIdx ], bpMotorHallSensorCount ); - U16 decDelta = HEX_64_K - incDelta; + U16 decDelta = ( 0 == incDelta ? 0xFFFF : HEX_64_K - incDelta ); U16 spdDelta; S16 delta; @@ -1038,33 +1083,43 @@ { MOTOR_DIR_T bpMCDir, bpDir; BOOL isDirIncorrect; - U08 dirErrorCnt = getFPGABloodPumpHallSensorStatus() & PUMP_DIR_ERROR_COUNT_MASK; + U08 dirErrorCnt = getFPGABloodPumpHallSensorStatus() & PUMP_DIR_ERROR_COUNT_MASK; + F32 measMCSpeed = getMeasuredBloodPumpMCSpeed(); + BOOL minDirSpeed = ( measMCSpeed >= BP_MIN_DIR_CHECK_SPEED_RPM ? TRUE : FALSE ); + BOOL isHallSensorFailed = ( TRUE == minDirSpeed && lastBloodPumpDirectionCount != dirErrorCnt ? TRUE : FALSE ); -#ifndef DISABLE_PUMP_DIRECTION_CHECKS // Check pump direction error count - if ( lastBloodPumpDirectionCount != dirErrorCnt ) + if ( ( TRUE == isHallSensorFailed ) && ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_BP_COMMUTATION_ERROR ) ) ) { - lastBloodPumpDirectionCount = dirErrorCnt; - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_PUMP_DIRECTION_STATUS_ERROR, (U32)HD_PUMP_BLOOD_PUMP ) - } +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PUMP_DIRECTION_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) #endif + { + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_PUMP_DIRECTION_STATUS_ERROR, (U32)HD_PUMP_BLOOD_PUMP ) + } + } + lastBloodPumpDirectionCount = dirErrorCnt; + bpMCDir = ( getMeasuredBloodPumpMCSpeed() >= 0.0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); bpDir = ( getMeasuredBloodPumpSpeed() >= 0.0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); // Check set direction vs. direction from hall sensors vs. direction from sign of motor controller speed - isDirIncorrect = ( bloodPumpDirectionSet != bpDir ) || ( bloodPumpDirectionSet != bpMCDir ); + isDirIncorrect = ( ( ( bloodPumpDirectionSet != bpDir ) || ( bloodPumpDirectionSet != bpMCDir ) ) && ( TRUE == minDirSpeed ) ); if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_BLOOD_PUMP_MC_DIRECTION_CHECK, isDirIncorrect ) ) { -#ifndef DISABLE_PUMP_DIRECTION_CHECKS - if ( bloodPumpDirectionSet != bpDir ) +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PUMP_DIRECTION_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) +#endif { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_BLOOD_PUMP_MC_DIRECTION_CHECK, (U32)bloodPumpDirectionSet, (U32)bpDir ) + if ( bloodPumpDirectionSet != bpDir ) + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_BLOOD_PUMP_MC_DIRECTION_CHECK, (U32)bloodPumpDirectionSet, (U32)bpDir ) + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_BLOOD_PUMP_MC_DIRECTION_CHECK, (U32)bloodPumpDirectionSet, (U32)bpMCDir ) + } } - else - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_BLOOD_PUMP_MC_DIRECTION_CHECK, (U32)bloodPumpDirectionSet, (U32)bpMCDir ) - } -#endif } } else @@ -1091,12 +1146,16 @@ F32 measMCMotorSpeed = fabs( getMeasuredBloodPumpMCSpeed() ); // Check for pump running while commanded off - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_BLOOD_PUMP_OFF_CHECK, ( 0 == targetBloodFlowRate ) && ( measMotorSpeed > BP_MAX_MOTOR_SPEED_WHILE_OFF_RPM ) ) ) + if ( ( TRUE == isPersistentAlarmTriggered( ALARM_ID_BLOOD_PUMP_OFF_CHECK, + ( 0 == targetBloodFlowRate ) && ( measMotorSpeed > BP_MAX_MOTOR_SPEED_WHILE_OFF_RPM ) ) ) ) { -#ifndef DISABLE_PUMP_SPEED_CHECKS - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BLOOD_PUMP_OFF_CHECK, measMotorSpeed ); - activateSafetyShutdown(); -#endif +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PUMP_SPEED_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BLOOD_PUMP_OFF_CHECK, measMotorSpeed ); + activateSafetyShutdown(); + } } // Checks that only occur when pump is running (and beyond ramp). @@ -1110,20 +1169,26 @@ F32 deltaRotorSpeed = fabs( measRotorSpeed - measMotorSpeedInRotorRPM ); // Check measured motor speed vs. commanded motor speed while controlling to target - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_BLOOD_PUMP_MOTOR_SPEED_CHECK, - ( deltaMotorSpeed > BP_MAX_MOTOR_SPEED_ERROR_RPM ) || ( deltaMCMotorSpeed > BP_MAX_MOTOR_SPEED_ERROR_RPM ) ) ) + if ( ( TRUE == isPersistentAlarmTriggered( ALARM_ID_BLOOD_PUMP_MOTOR_SPEED_CHECK, + ( deltaMotorSpeed > BP_MAX_MOTOR_SPEED_ERROR_RPM ) || ( deltaMCMotorSpeed > BP_MAX_MOTOR_SPEED_ERROR_RPM ) ) ) ) { -#ifndef DISABLE_PUMP_SPEED_CHECKS - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_BLOOD_PUMP_MOTOR_SPEED_CHECK, cmdMotorSpeed, measMotorSpeed ); -#endif +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PUMP_SPEED_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_BLOOD_PUMP_MOTOR_SPEED_CHECK, cmdMotorSpeed, measMotorSpeed ); + } } // Check measured rotor speed vs. measured motor speed while controlling to target - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_BLOOD_PUMP_ROTOR_SPEED_CHECK, deltaRotorSpeed > BP_MAX_ROTOR_VS_MOTOR_DIFF_RPM ) ) + if ( ( TRUE == isPersistentAlarmTriggered( ALARM_ID_BLOOD_PUMP_ROTOR_SPEED_CHECK, deltaRotorSpeed > BP_MAX_ROTOR_VS_MOTOR_DIFF_RPM ) ) ) { -#ifndef DISABLE_PUMP_SPEED_CHECKS +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PUMP_SPEED_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { SET_ALARM_WITH_2_F32_DATA( ALARM_ID_BLOOD_PUMP_ROTOR_SPEED_CHECK, measRotorSpeed, measMotorSpeed ); -#endif + } } } else @@ -1143,17 +1208,20 @@ *************************************************************************/ static void checkBloodPumpMCCurrent( void ) { - F32 const bpCurr = fabs( getMeasuredBloodPumpMCCurrent() ); + F32 const bpCurr = fabs( getMeasuredBloodPumpMCCurrent() ); // Check blood pump current during off state - BOOL const isOffMCCurrentBad = ( BLOOD_PUMP_OFF_STATE == bloodPumpState ) && ( bpCurr > BP_MAX_CURR_WHEN_STOPPED_MA ); + BOOL const isOffMCCurrentBad = ( ( BLOOD_PUMP_OFF_STATE == bloodPumpState ) && ( bpCurr > BP_MAX_CURR_WHEN_STOPPED_MA ) ? TRUE : FALSE ); // Check blood pump current during running state - BOOL const isRunningMCCurrentBad = ( BLOOD_PUMP_OFF_STATE != bloodPumpState ) && ( bpCurr > BP_MAX_CURR_WHEN_RUNNING_MA ); + BOOL const isRunningMCCurrentBad = ( ( BLOOD_PUMP_OFF_STATE != bloodPumpState ) && ( bpCurr > BP_MAX_CURR_WHEN_RUNNING_MA ) ? TRUE : FALSE ); - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_BLOOD_PUMP_MC_CURRENT_CHECK, isOffMCCurrentBad || isRunningMCCurrentBad ) ) + if ( ( TRUE == isPersistentAlarmTriggered( ALARM_ID_BLOOD_PUMP_MC_CURRENT_CHECK, isOffMCCurrentBad || isRunningMCCurrentBad ) ) ) { -#ifndef DISABLE_MOTOR_CURRENT_CHECKS - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BLOOD_PUMP_MC_CURRENT_CHECK, bpCurr ); +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_MOTOR_CURRNT_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) #endif + { + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BLOOD_PUMP_MC_CURRENT_CHECK, bpCurr ); + } } } @@ -1167,47 +1235,43 @@ *************************************************************************/ static void checkBloodPumpFlowRate( void ) { -#ifndef DISABLE_PUMP_FLOW_CHECKS - F32 flow = getMeasuredBloodFlowRate(); - - // Range check on measure BP flow rate. - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_BLOOD_FLOW_OUT_OF_RANGE, ( flow > BP_MAX_FLOW_RATE ) || ( flow < BP_MIN_FLOW_RATE ) ) ) +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PUMP_FLOW_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) +#endif { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_BLOOD_FLOW_OUT_OF_RANGE, flow ); - } + F32 flow = getMeasuredBloodFlowRate(); - // Flow vs. speed check only performed while in treatment mode and while we are in control to target state - if ( ( MODE_TREA == getCurrentOperationMode() ) && ( BLOOD_PUMP_CONTROL_TO_TARGET_STATE == bloodPumpState ) ) - { - F32 speed = getMeasuredBloodPumpSpeed(); - F32 impliedSpeed = ( (F32)targetBloodFlowRate / (F32)ML_PER_LITER ) * BP_REV_PER_LITER * BP_GEAR_RATIO; - F32 delta = fabs( speed - impliedSpeed ); - - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_BLOOD_PUMP_FLOW_VS_MOTOR_SPEED_CHECK, delta > BP_MAX_FLOW_VS_SPEED_DIFF_RPM ) ) + // Range check on measure BP flow rate. + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_BLOOD_FLOW_OUT_OF_RANGE, ( flow > BP_MAX_FLOW_RATE ) || ( flow < BP_MIN_FLOW_RATE ) ) ) { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_BLOOD_PUMP_FLOW_VS_MOTOR_SPEED_CHECK, flow, speed ); + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_BLOOD_FLOW_OUT_OF_RANGE, flow ); } } - else - { - resetPersistentAlarmTimer( ALARM_ID_BLOOD_PUMP_FLOW_VS_MOTOR_SPEED_CHECK ); - } -#endif } /*********************************************************************//** * @brief * The execBloodFlowTest function executes the state machine for the * BloodFlow self-test. - * @details Inputs: none + * @details Inputs: bloodPumpCalRecord * @details Outputs: none * @return the current state of the BloodFlow self-test. *************************************************************************/ SELF_TEST_STATUS_T execBloodFlowTest( void ) { SELF_TEST_STATUS_T result = SELF_TEST_STATUS_PASSED; - // TODO - anything to test here? + BOOL calStatus = getNVRecord2Driver( GET_CAL_PUMPS, (U08*)&bloodPumpCalRecord, sizeof( HD_PUMPS_CAL_RECORD_T ), + NUM_OF_CAL_DATA_HD_PUMPS, ALARM_ID_NO_ALARM ); + + if ( TRUE == calStatus ) + { + result = SELF_TEST_STATUS_PASSED; + } + else + { + result = SELF_TEST_STATUS_FAILED; + } return result; } @@ -1293,7 +1357,6 @@ } if ( ctrlMode < NUM_OF_PUMP_CONTROL_MODES ) { - targetBloodFlowRate = value; result = setBloodPumpTargetFlowRate( abs(value), dir, (PUMP_CONTROL_MODE_T)ctrlMode ); } }