Index: firmware/App/Controllers/BloodFlow.c =================================================================== diff -u -rc67def50892f9a7c2f1f22985b5351465a8f6773 -r1a685471524555a374854c0c9ec8e208e71fe2df --- firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision c67def50892f9a7c2f1f22985b5351465a8f6773) +++ firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 1a685471524555a374854c0c9ec8e208e71fe2df) @@ -24,32 +24,36 @@ #include "DialInFlow.h" #include "PresOccl.h" +#include "BloodFlow.h" #include "FPGA.h" #include "InternalADC.h" #include "NVDataMgmt.h" #include "OperationModes.h" -#include "PIControllers.h" +#include "PersistentAlarm.h" +#include "PIControllers.h" +#include "SafetyShutdown.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "TaskPriority.h" #include "Timers.h" -#include "BloodFlow.h" /** * @addtogroup BloodFlow * @{ */ // ********** private definitions ********** + +/// 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 BLOOD_FLOW_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< interval (ms/task time) at which the blood flow data is published on the CAN bus - #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.88 ///< controller will error if PWM duty cycle > 90%, so set max to 88% #define MIN_BLOOD_PUMP_PWM_DUTY_CYCLE 0.12 ///< controller will error if PWM duty cycle < 10%, so set min to 12% - -#define BP_CONTROL_INTERVAL ( 10000 / TASK_GENERAL_INTERVAL ) ///< interval (ms/task time) at which the blood pump is controlled + +/// interval (ms/task time) at which the blood pump is controlled. +#define BP_CONTROL_INTERVAL ( 10000 / TASK_GENERAL_INTERVAL ) #define BP_P_COEFFICIENT 0.00035 ///< P term for blood pump control #define BP_I_COEFFICIENT 0.00035 ///< I term for blood pump control @@ -59,14 +63,16 @@ #define BP_HALL_EDGE_COUNTS_PER_REV 48 ///< number of hall sensor edge counts per motor revolution. #define BP_MAX_ROTOR_SPEED_RPM 100.0 ///< maximum rotor speed allowed for blood pump. -#define BP_MAX_FLOW_VS_SPEED_DIFF_ML_MIN 50.0 ///< maximum difference between measured flow and flow implied by measured motor speed. +#define BP_MAX_FLOW_VS_SPEED_DIFF_RPM 200.0 ///< maximum difference between measured speed and speed implied by measured flow. #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_FLOW_VS_SPEED_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) for flow vs. motor speed error condition. -#define BP_OFF_ERROR_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) for motor off error condition. -#define BP_MOTOR_SPEED_ERROR_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) motor speed error condition. -#define BP_ROTOR_SPEED_ERROR_PERSIST ((12 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) rotor speed error condition. +#define BP_FLOW_VS_SPEED_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) for flow vs. motor speed error condition. +#define BP_OFF_ERROR_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) for motor off error condition. +#define BP_MOTOR_SPEED_ERROR_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) motor speed error condition. +#define BP_ROTOR_SPEED_ERROR_PERSIST ((12 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) rotor speed error condition. +#define BP_DIRECTION_ERROR_PERSIST (250 / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) pump direction error condition. +#define BP_MAX_ROTOR_SPEED_ERROR_PERSIST ((1 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) blood pump rotor speed too fast error condition. #define BP_MAX_CURR_WHEN_STOPPED_MA 150.0 ///< motor controller current should not exceed this when pump should be stopped #define BP_MIN_CURR_WHEN_RUNNING_MA 150.0 ///< motor controller current should always exceed this when pump should be running @@ -76,19 +82,25 @@ #define BP_SPEED_ADC_TO_RPM_FACTOR 1.280938 ///< conversion factor from ADC counts to RPM for blood pump motor #define BP_CURRENT_ADC_TO_MA_FACTOR 3.002 ///< conversion factor from ADC counts to mA for blood pump motor -#define BP_REV_PER_LITER 150.24 ///< rotor revolutions per liter +#define BP_REV_PER_LITER 150.0 ///< rotor revolutions per liter #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_MOTOR_RPM_TO_PWM_DC_FACTOR 0.00028 ///< ~28 BP motor RPM = 1% PWM duty cycle #define BP_PWM_ZERO_OFFSET 0.1 ///< 10% PWM duty cycle = zero speed -#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 factor from mL/min to estimated PWM duty cycle %. +/// conversion factor 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 ) #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. -#define SIGN_FROM_12_BIT_VALUE(v) ( (S16)(v) - (S16)BLOODPUMP_ADC_ZERO ) ///< macro converts 12 bit ADC value to signed 16-bit value. +/// 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 ) * 10 ) + +/// blood flow sensor signal strength low alarm persistence. +#define FLOW_SIG_STRGTH_ALARM_PERSIST ( ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) * 5 ) +#define MIN_FLOW_SIG_STRENGTH 0.9 ///< Minimum flow sensor signal strength (90%). -#define SIZE_OF_ROLLING_AVG ( ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) * 10 ) ///< measured blood flow is filtered w/ moving average - /// Enumeration of blood pump controller states. typedef enum BloodPump_States { @@ -136,28 +148,33 @@ static F32 bloodFlowCalGain = 1.0; ///< blood flow calibration gain. static F32 bloodFlowCalOffset = 0.0; ///< blood flow calibration offset. -static OVERRIDE_U32_T bloodFlowDataPublishInterval = { BLOOD_FLOW_DATA_PUB_INTERVAL, BLOOD_FLOW_DATA_PUB_INTERVAL, BLOOD_FLOW_DATA_PUB_INTERVAL, 0 }; ///< Interval (in ms) at which to publish blood flow data to CAN bus -static OVERRIDE_S32_T targetBloodFlowRate = { 0, 0, 0, 0 }; ///< requested blood flow rate -static OVERRIDE_F32_T measuredBloodFlowRate = { 0.0, 0.0, 0.0, 0 }; ///< measured blood flow rate -static OVERRIDE_F32_T bloodPumpRotorSpeedRPM = { 0.0, 0.0, 0.0, 0 }; ///< measured blood pump rotor speed -static OVERRIDE_F32_T bloodPumpSpeedRPM = { 0.0, 0.0, 0.0, 0 }; ///< measured blood pump motor speed -static OVERRIDE_F32_T adcBloodPumpMCSpeedRPM = { 0.0, 0.0, 0.0, 0 }; ///< measured blood pump motor controller speed -static OVERRIDE_F32_T adcBloodPumpMCCurrentmA = { 0.0, 0.0, 0.0, 0 }; ///< measured blood pump motor controller current +/// Interval (in task intervals) at which to publish blood flow data to CAN bus. +static OVERRIDE_U32_T bloodFlowDataPublishInterval = { BLOOD_FLOW_DATA_PUB_INTERVAL, BLOOD_FLOW_DATA_PUB_INTERVAL, BLOOD_FLOW_DATA_PUB_INTERVAL, 0 }; +static OVERRIDE_S32_T targetBloodFlowRate = { 0, 0, 0, 0 }; ///< requested blood flow rate (mL/min) +static OVERRIDE_F32_T measuredBloodFlowRate = { 0.0, 0.0, 0.0, 0 }; ///< measured blood flow rate (mL/min) +static OVERRIDE_F32_T bloodPumpRotorSpeedRPM = { 0.0, 0.0, 0.0, 0 }; ///< measured blood pump rotor speed (RPM) +static OVERRIDE_F32_T bloodPumpSpeedRPM = { 0.0, 0.0, 0.0, 0 }; ///< measured blood pump motor speed (RPM) +static OVERRIDE_F32_T adcBloodPumpMCSpeedRPM = { 0.0, 0.0, 0.0, 0 }; ///< measured blood pump motor controller speed (RPM) +static OVERRIDE_F32_T adcBloodPumpMCCurrentmA = { 0.0, 0.0, 0.0, 0 }; ///< measured blood pump motor controller current (mA) +static OVERRIDE_F32_T bloodFlowSignalStrength = { 0.0, 0.0, 0.0, 0 }; ///< measured blood flow signal strength (%) static U32 bpControlTimerCounter = 0; ///< determines when to perform control on blood flow -static U32 bpRotorRevStartTime = 0; ///< blood pump rotor rotation start time (in ms) +static U32 bpRotorRevStartTime = 0; ///< blood pump rotor rotation start time (in ms) +static U32 bloodPumpRotorCounter = 0; ///< running counter for blood pump rotor revolutions static BOOL bpStopAtHomePosition = FALSE; ///< stop blood pump at next home position static U32 bpHomeStartTime = 0; ///< when did blood pump home command begin? (in ms) -static U16 bpLastMotorHallSensorCount = 0; ///< last hall sensor count for the blood pump motor -static MOTOR_DIR_T bpMotorDirectionFromHallSensors = MOTOR_DIR_FORWARD; ///< pump direction according to hall sensor count +static U16 bpLastMotorHallSensorCount = 0; ///< last hall sensor count for the blood pump motor +static U32 bloodPumpMotorEdgeCount = 0; ///< running counter for blood pump motor revolutions static U32 bpMotorSpeedCalcTimerCtr = 0; ///< counter determines interval for calculating blood pump motor speed from hall sensor count. static U32 errorBloodFlowVsMotorSpeedPersistTimerCtr = 0; ///< persistence timer counter for flow vs. motor speed error condition. static U32 errorBloodMotorOffPersistTimerCtr = 0; ///< persistence timer counter for motor off check error condition. static U32 errorBloodMotorSpeedPersistTimerCtr = 0; ///< persistence timer counter for motor speed error condition. -static U32 errorBloodRotorSpeedPersistTimerCtr = 0; ///< persistence timer counter for rotor speed error condition. +static U32 errorBloodRotorSpeedPersistTimerCtr = 0; ///< persistence timer counter for rotor speed error condition. +static U32 errorBloodPumpDirectionPersistTimerCtr = 0; ///< persistence timer counter for pump direction error condition. +static U32 errorBloodPumpRotorTooFastPersistTimerCtr = 0; ///< persistence timer counter for pump rotor too fast error condition. static F32 flowReadings[ SIZE_OF_ROLLING_AVG ]; ///< holds flow samples for a rolling average static U32 flowReadingsIdx = 0; ///< index for next sample in rolling average array @@ -187,7 +204,8 @@ static void checkBloodPumpDirection( void ); static void checkBloodPumpSpeeds( void ); static void checkBloodPumpFlowAgainstSpeed( void ); -static void checkBloodPumpMCCurrent( void ); +static void checkBloodPumpMCCurrent( void ); +static void checkBloodFlowSensorSignalStrength( void ); static DATA_GET_PROTOTYPE( U32, getPublishBloodFlowDataInterval ); /*********************************************************************//** @@ -210,7 +228,12 @@ // initialize blood flow PI controller initializePIController( PI_CONTROLLER_ID_BLOOD_FLOW, MIN_BLOOD_PUMP_PWM_DUTY_CYCLE, BP_P_COEFFICIENT, BP_I_COEFFICIENT, - MIN_BLOOD_PUMP_PWM_DUTY_CYCLE, MAX_BLOOD_PUMP_PWM_DUTY_CYCLE ); + MIN_BLOOD_PUMP_PWM_DUTY_CYCLE, MAX_BLOOD_PUMP_PWM_DUTY_CYCLE ); + + // initialize persistent alarm for flow sensor signal strength too low + initPersistentAlarm( PERSISTENT_ALARM_BLOOD_FLOW_SIGNAL_STRENGTH, + ALARM_ID_BLOOD_FLOW_SIGNAL_STRENGTH_TOO_LOW, + FALSE, FLOW_SIG_STRGTH_ALARM_PERSIST, FLOW_SIG_STRGTH_ALARM_PERSIST ); } /*********************************************************************//** @@ -309,7 +332,10 @@ void signalBloodPumpRotorHallSensor( void ) { U32 rotTime = getMSTimerCount(); - U32 deltaTime = calcTimeBetween( bpRotorRevStartTime, rotTime ); + U32 deltaTime = calcTimeBetween( bpRotorRevStartTime, rotTime ); + + // increment rotor counter + bloodPumpRotorCounter++; // calculate rotor speed (in RPM) bloodPumpRotorSpeedRPM.data = ( 1.0 / (F32)deltaTime ) * (F32)MS_PER_SECOND * (F32)SEC_PER_MIN; @@ -342,6 +368,45 @@ } return result; +} + +/*********************************************************************//** + * @brief + * The getBloodPumpMotorCount function returns the current count for the + * blood pump motor revolution counter. + * @details Inputs: bloodPumpMotorCount + * @details Outputs: none + * @return bloodPumpMotorCount + *************************************************************************/ +U32 getBloodPumpMotorCount( void ) +{ + return bloodPumpMotorEdgeCount / BP_HALL_EDGE_COUNTS_PER_REV; +} + +/*********************************************************************//** + * @brief + * The getBloodPumpRotorCount function returns the current count for the + * blood pump rotor revolution counter. + * @details Inputs: bloodPumpRotorCounter + * @details Outputs: none + * @return bloodPumpRotorCounter + *************************************************************************/ +U32 getBloodPumpRotorCount( void ) +{ + return bloodPumpRotorCounter; +} + +/*********************************************************************//** + * @brief + * The isBloodPumpRunning function returns whether the blood pump is currently + * running or not. + * @details Inputs: isBloodPumpOn + * @details Outputs: none + * @return isBloodPumpOn + *************************************************************************/ +BOOL isBloodPumpRunning( void ) +{ + return isBloodPumpOn; } /*********************************************************************//** @@ -352,21 +417,23 @@ * @return none *************************************************************************/ void execBloodFlowMonitor( void ) -{ +{ + HD_OP_MODE_T opMode = getCurrentOperationMode(); U16 bpRPM = getIntADCReading( INT_ADC_BLOOD_PUMP_SPEED ); U16 bpmA = getIntADCReading( INT_ADC_BLOOD_PUMP_MOTOR_CURRENT ); F32 bpFlow = ( ( getFPGABloodFlow() * -1.0 ) * bloodFlowCalGain ) + bloodFlowCalOffset; // blood flow sensor installed backwards on HD adcBloodPumpMCSpeedRPM.data = (F32)(SIGN_FROM_12_BIT_VALUE(bpRPM)) * BP_SPEED_ADC_TO_RPM_FACTOR; - adcBloodPumpMCCurrentmA.data = (F32)(SIGN_FROM_12_BIT_VALUE(bpmA)) * BP_CURRENT_ADC_TO_MA_FACTOR; + adcBloodPumpMCCurrentmA.data = (F32)(SIGN_FROM_12_BIT_VALUE(bpmA)) * BP_CURRENT_ADC_TO_MA_FACTOR; + bloodFlowSignalStrength.data = getFPGABloodFlowSignalStrength(); filterBloodFlowReadings( bpFlow ); // calculate blood pump motor speed/direction from hall sensor count updateBloodPumpSpeedAndDirectionFromHallSensors(); // don't start enforcing checks until out of init/POST mode - if ( getCurrentOperationMode() != MODE_INIT ) + if ( opMode != MODE_INIT ) { // check pump direction checkBloodPumpDirection(); @@ -376,8 +443,10 @@ checkBloodPumpSpeeds(); checkBloodPumpFlowAgainstSpeed(); // check for home position, zero/low speed - checkBloodPumpRotor(); - } + checkBloodPumpRotor(); + // check flow sensor signal strength + checkBloodFlowSensorSignalStrength(); + } // publish blood flow data on interval publishBloodFlowData(); @@ -501,7 +570,7 @@ BLOOD_PUMP_STATE_T result = BLOOD_PUMP_RAMPING_DOWN_STATE; // have we essentially reached zero speed - if ( bloodPumpPWMDutyCyclePctSet < (MAX_BLOOD_PUMP_PWM_STEP_UP_CHANGE + BP_PWM_ZERO_OFFSET) ) + if ( bloodPumpPWMDutyCyclePctSet < (MAX_BLOOD_PUMP_PWM_STEP_DN_CHANGE + BP_PWM_ZERO_OFFSET) ) { stopBloodPump(); result = BLOOD_PUMP_OFF_STATE; @@ -691,6 +760,26 @@ return result; } +/*********************************************************************//** + * @brief + * The getMeasuredBloodFlowSignalStrength function gets the measured blood flow + * signal strength. + * @details Inputs: bloodFlowSignalStrength + * @details Outputs: none + * @return the current blood flow signal strength (in %). + *************************************************************************/ +F32 getMeasuredBloodFlowSignalStrength( void ) +{ + F32 result = bloodFlowSignalStrength.data; + + if ( OVERRIDE_KEY == bloodFlowSignalStrength.override ) + { + result = bloodFlowSignalStrength.ovData; + } + + return result; +} + /*********************************************************************//** * @brief * The getMeasuredBloodPumpRotorSpeed function gets the measured blood flow @@ -783,33 +872,19 @@ static void publishBloodFlowData( void ) { // publish blood flow data on interval -#ifndef FLOW_DEBUG if ( ++bloodFlowDataPublicationTimerCounter >= getPublishBloodFlowDataInterval() ) -#endif - { - S32 flowStPt = (S32)getTargetBloodFlowRate(); - F32 measFlow = getMeasuredBloodFlowRate(); - F32 measRotSpd = getMeasuredBloodPumpRotorSpeed(); - F32 measSpd = getMeasuredBloodPumpSpeed(); - F32 measMCSpd = getMeasuredBloodPumpMCSpeed(); - F32 measMCCurr = getMeasuredBloodPumpMCCurrent(); - F32 pumpPWMPctDutyCycle = bloodPumpPWMDutyCyclePctSet * FRACTION_TO_PERCENT_FACTOR; -#ifdef FLOW_DEBUG - // TODO - temporary debug code - remove later - char debugFlowStr[ 256 ]; - - F32 measFlowSig = getFPGABloodFlowSignalStrength() * 100.0; - F32 dialFlow = getMeasuredDialInFlowRate(); - F32 dialFlowSig = getFPGADialysateFlowSignalStrength() * 100.0; - F32 bldOccl = getMeasuredBloodPumpOcclusion(); - F32 dpiOccl = getMeasuredDialInPumpOcclusion(); - F32 dpoOccl = getMeasuredDialOutPumpOcclusion(); - - sprintf( debugFlowStr, "Blood: %5.1f, %6.1f, %6.1f Dial-I: %5.1f, %6.1f, %6.1f Dial-O: %6.1f\n", measFlowSig, measFlow, bldOccl, dialFlowSig, dialFlow, dpiOccl, dpoOccl ); - sendDebugData( (U08*)debugFlowStr, strlen(debugFlowStr) ); -#else - broadcastBloodFlowData( flowStPt, measFlow, measRotSpd, measSpd, measMCSpd, measMCCurr, pumpPWMPctDutyCycle ); -#endif + { + BLOOD_PUMP_STATUS_PAYLOAD_T payload; + + payload.setPoint = (S32)getTargetBloodFlowRate(); + payload.measFlow = getMeasuredBloodFlowRate(); + payload.measRotorSpd = getMeasuredBloodPumpRotorSpeed(); + payload.measPumpSpd = getMeasuredBloodPumpSpeed(); + payload.measMCSpd = getMeasuredBloodPumpMCSpeed(); + payload.measMCCurr = getMeasuredBloodPumpMCCurrent(); + payload.pwmDC = bloodPumpPWMDutyCyclePctSet * FRACTION_TO_PERCENT_FACTOR; + payload.flowSigStrength = getMeasuredBloodFlowSignalStrength() * FRACTION_TO_PERCENT_FACTOR; + broadcastBloodFlowData( &payload ); bloodFlowDataPublicationTimerCounter = 0; } } @@ -876,16 +951,15 @@ // determine blood pump speed/direction from delta hall sensor count since last interval if ( incDelta < decDelta ) { - bpMotorDirectionFromHallSensors = MOTOR_DIR_FORWARD; delta = incDelta; bloodPumpSpeedRPM.data = ( (F32)delta / (F32)BP_HALL_EDGE_COUNTS_PER_REV ) * (F32)SEC_PER_MIN; } else { - bpMotorDirectionFromHallSensors = MOTOR_DIR_REVERSE; delta = decDelta; bloodPumpSpeedRPM.data = ( (F32)delta / (F32)BP_HALL_EDGE_COUNTS_PER_REV ) * (F32)SEC_PER_MIN * -1.0; - } + } + bloodPumpMotorEdgeCount += delta; // update last count for next time bpLastMotorHallSensorCount = bpMotorHallSensorCount; @@ -917,7 +991,14 @@ // ensure rotor speed below maximum if ( rotorSpeed > BP_MAX_ROTOR_SPEED_RPM ) { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BLOOD_PUMP_ROTOR_SPEED_TOO_HIGH, rotorSpeed ) + if ( ++errorBloodPumpRotorTooFastPersistTimerCtr >= BP_MAX_ROTOR_SPEED_ERROR_PERSIST ) + { + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BLOOD_PUMP_ROTOR_SPEED_TOO_HIGH, rotorSpeed ) + } + } + else + { + errorBloodPumpRotorTooFastPersistTimerCtr = 0; } // if pump is stopped or running very slowly, set rotor speed to zero @@ -937,18 +1018,41 @@ *************************************************************************/ static void checkBloodPumpDirection( void ) { - MOTOR_DIR_T bpMCDir; - if ( BLOOD_PUMP_CONTROL_TO_TARGET_STATE == bloodPumpState ) { - // check set direction vs. direction from hall sensors or sign of motor controller speed - bpMCDir = ( getMeasuredBloodPumpMCSpeed() >= 0.0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); - if ( ( bloodPumpDirectionSet != bpMCDir ) || ( bloodPumpDirectionSet != bpMotorDirectionFromHallSensors ) ) + MOTOR_DIR_T bpMCDir, bpDir; + + 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 + if ( bloodPumpDirectionSet != bpDir ) { + if ( ++errorBloodPumpDirectionPersistTimerCtr >= BP_DIRECTION_ERROR_PERSIST ) + { #ifndef DISABLE_PUMP_DIRECTION_CHECKS - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_BLOOD_PUMP_MC_DIRECTION_CHECK, (U32)bloodPumpDirectionSet, (U32)bpMotorDirectionFromHallSensors ) -#endif - } + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_BLOOD_PUMP_MC_DIRECTION_CHECK, (U32)bloodPumpDirectionSet, (U32)bpDir ) +#endif + } + } + // check set direction vs. direction from sign of motor controller speed + else if ( bloodPumpDirectionSet != bpMCDir ) + { + if ( ++errorBloodPumpDirectionPersistTimerCtr >= BP_DIRECTION_ERROR_PERSIST ) + { +#ifndef DISABLE_PUMP_DIRECTION_CHECKS + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_BLOOD_PUMP_MC_DIRECTION_CHECK, (U32)bloodPumpDirectionSet, (U32)bpMCDir ) +#endif + } + } + else + { + errorBloodPumpDirectionPersistTimerCtr = 0; + } + } + else + { + errorBloodPumpDirectionPersistTimerCtr = 0; } } @@ -966,7 +1070,7 @@ *************************************************************************/ static void checkBloodPumpSpeeds( void ) { - F32 measMotorSpeed = getMeasuredBloodPumpSpeed(); + F32 measMotorSpeed = fabs( getMeasuredBloodPumpSpeed() ); S32 cmdRate = getTargetBloodFlowRate(); // check for pump running while commanded off @@ -977,7 +1081,8 @@ if ( ++errorBloodMotorOffPersistTimerCtr >= BP_OFF_ERROR_PERSIST ) { #ifndef DISABLE_PUMP_SPEED_CHECKS - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BLOOD_PUMP_OFF_CHECK, measMotorSpeed ); + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BLOOD_PUMP_OFF_CHECK, measMotorSpeed ); + activateSafetyShutdown(); #endif } } @@ -1028,7 +1133,6 @@ { errorBloodRotorSpeedPersistTimerCtr = 0; } - } else { @@ -1053,16 +1157,16 @@ if ( ( MODE_TREA == getCurrentOperationMode() ) && ( BLOOD_PUMP_CONTROL_TO_TARGET_STATE == bloodPumpState ) ) { F32 flow = getMeasuredBloodFlowRate(); - F32 speed = getMeasuredBloodPumpSpeed(); - F32 impliedFlow = ( ( speed / BP_GEAR_RATIO ) / BP_REV_PER_LITER ) * (F32)ML_PER_LITER; - F32 delta = fabs( flow - impliedFlow ); + F32 speed = getMeasuredBloodPumpSpeed(); + F32 impliedSpeed = ( flow / (F32)ML_PER_LITER ) * BP_REV_PER_LITER * BP_GEAR_RATIO; + F32 delta = fabs( speed - impliedSpeed ); - if ( delta > BP_MAX_FLOW_VS_SPEED_DIFF_ML_MIN ) + if ( delta > BP_MAX_FLOW_VS_SPEED_DIFF_RPM ) { if ( ++errorBloodFlowVsMotorSpeedPersistTimerCtr >= BP_FLOW_VS_SPEED_PERSIST ) { #ifndef DISABLE_PUMP_FLOW_CHECKS - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_BLOOD_PUMP_FLOW_VS_MOTOR_SPEED_CHECK, flow, impliedFlow ); + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_BLOOD_PUMP_FLOW_VS_MOTOR_SPEED_CHECK, flow, speed ); #endif } } @@ -1127,6 +1231,30 @@ bpCurrErrorDurationCtr = 0; } } +} + +/*********************************************************************//** + * @brief + * The checkBloodFlowSensorSignalStrength function checks the measured blood + * flow sensor signal strength is sufficient for accurate flow sensing. + * @details Inputs: + * @details Outputs: + * @return none + *************************************************************************/ +static void checkBloodFlowSensorSignalStrength( void ) +{ +#ifndef DISABLE_PUMP_FLOW_CHECKS + HD_OP_MODE_T opMode = getCurrentOperationMode(); + + // check flow sensor signal strength when appropriate TODO - in pre-treatment, must be far enough along for fluid to be in tubing + if ( MODE_TREA == opMode || ( MODE_PRET == opMode && FALSE ) ) + { + F32 sigStrength = getMeasuredBloodFlowSignalStrength(); + BOOL outOfRange = ( sigStrength < MIN_FLOW_SIG_STRENGTH ? TRUE : FALSE ); + + checkPersistentAlarm( PERSISTENT_ALARM_BLOOD_FLOW_SIGNAL_STRENGTH, outOfRange, sigStrength ); + } +#endif } /*********************************************************************//** @@ -1558,5 +1686,50 @@ return result; } + +/*********************************************************************//** + * @brief + * The testSetMeasuredBloodFlowSignalStrengthOverride function overrides the measured + * blood flow signal strength. + * @details Inputs: none + * @details Outputs: bloodFlowSignalStrength + * @param value override measured blood flow signal strength (in %) + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetMeasuredBloodFlowSignalStrengthOverride( F32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + bloodFlowSignalStrength.ovData = value / 100.0; + bloodFlowSignalStrength.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetMeasuredBloodFlowSignalStrengthOverride function resets the override + * of the measured blood flow signal strength. + * @details Inputs: none + * @details Outputs: bloodFlowSignalStrength + * @return TRUE if reset successful, FALSE if not + *************************************************************************/ +BOOL testResetMeasuredBloodFlowSignalStrengthOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + bloodFlowSignalStrength.override = OVERRIDE_RESET; + bloodFlowSignalStrength.ovData = bloodFlowSignalStrength.ovInitData; + } + + return result; +} /**@}*/