Index: firmware/App/Controllers/BloodFlow.c =================================================================== diff -u -r5aaca3e9292c6c7404872440fe2ebe8ac6641fb8 -r1ebbe403d260d9f65695c13d6dbafbe1a93cfdde --- firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 5aaca3e9292c6c7404872440fe2ebe8ac6641fb8) +++ firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 1ebbe403d260d9f65695c13d6dbafbe1a93cfdde) @@ -15,7 +15,7 @@ * ***************************************************************************/ -#include +#include // Used for fabs() and pow() functions #include "can.h" #include "etpwm.h" @@ -93,7 +93,7 @@ #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 BP_REV_PER_LITER 150.0 ///< Rotor revolutions per liter +#define BP_REV_PER_LITER 144.7 ///< 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_PWM_ZERO_OFFSET 0.1 ///< 10% PWM duty cycle = zero speed @@ -124,6 +124,20 @@ #define BFM_SENSOR_PARAM_CORRUPT_STATUS 0x07 ///< Blood flow meter NVM parameter status. #define PUMP_DIR_ERROR_COUNT_MASK 0x3F ///< Bit mask for pump direction error counter. + +#ifdef ENABLE_ALTERNATE_FLOW +#define BLOOD_PC2 -0.0000090267 ///< Pressure compensation coefficient (2nd order) for blood pump. +#define BLOOD_PC1 -0.00071147 ///< Pressure compensation coefficient (1st order) for blood pump. +#define BLOOD_NSV 3.4555 ///< Nominal stroke (1/2 rotor revolution) volume (in mL) for blood pump. +#define BLOOD_SC2 -0.0000000718 ///< Speed compensation coefficient (2nd order) for blood pump. +#define BLOOD_SC1 0.0000851 ///< Speed compensation coefficient (1st order) for blood pump. +#define BLOOD_SC0 -0.027 ///< Speed compensation coefficient (offset) for blood pump. +#define BLOOD_PSC2 -0.00000382 ///< Additional pressure compensation coefficient (2nd order) for blood pump. +#define BLOOD_PSC1 0.000197 ///< Additional pressure compensation coefficient (1st order) for blood pump. +#define BLOOD_PSC0 0.17 ///< Additional pressure compensation coefficient (offset) for blood pump. +#define BLOOD_TS0 1000.0 ///< Lower boundary of weighted speed transition (in RPM). +#define BLOOD_TS1 1500.0 ///< Upper boundary of weighted speed transition (in RPM). +#endif /// Enumeration of blood pump controller states. typedef enum BloodPump_States @@ -167,13 +181,23 @@ /// 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 S32 targetBloodFlowRate = 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 -static OVERRIDE_F32_T bloodFlowSignalStrength = { 0.0, 0.0, 0.0, 0 }; ///< Measured blood flow signal strength (%) +static S32 targetBloodFlowRate = 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. +static OVERRIDE_F32_T bloodFlowSignalStrength = { 0.0, 0.0, 0.0, 0 }; ///< Measured blood flow signal strength (%). +#ifdef ENABLE_ALTERNATE_FLOW + static F32 calcBloodFlowRate = 0.0; ///< Calculated blood flow rate from pump speed and upstream pressure. + + static F32 bloodPCSV; ///< Calculated pressure corrected blood pump stroke volume. + static F32 bloodSCSV; ///< Calculated speed corrected blood pump stroke volume. + static F32 bloodPSCSV; ///< Calculated additional pressure corrected blood pump stroke volume. + static F32 bloodHSWF; ///< High speed weighting factor for blood pump stroke volume calculation. + static F32 bloodLSWF; ///< Low speed weighting factor for blood pump stroke volume calculation. + static F32 bloodPSCSVT; ///< Pressure corrected, speed corrected blood pump stroke volume with weighted transition. +#endif static U32 bpControlTimerCounter = 0; ///< Determines when to perform control on blood flow @@ -195,7 +219,9 @@ static U08 lastBloodFlowFastPacketReadCtr = 0; ///< Previous read counter for the blood flow fast packets. static U08 lastBloodFlowSlowPacketReadCtr = 0; ///< Previous read counter for the blood flow slow packets. static U08 lastBloodPumpDirectionCount = 0; ///< Previous pump direction error count reported by FPGA. +#ifndef DISABLE_PUMP_FLOW_CHECKS static U08 lastBloodFlowCommErrorCount = 0; ///< Previous BP flow sensor comm error count. +#endif static HD_FLOW_SENSORS_CAL_RECORD_T bloodFlowCalRecord; ///< Blood flow sensor calibration record. // ********** private function prototypes ********** @@ -219,6 +245,38 @@ static void checkBloodPumpMCCurrent( void ); static void checkBloodFlowSensorSignalStrength( void ); static BOOL processCalibrationData( void ); +#ifdef ENABLE_ALTERNATE_FLOW +static void calcBloodFlow( void ); + +/*********************************************************************//** + * @brief + * The calcBloodFlow function calculates an estimated blood flow rate from + * blood pump speed and arterial pressure. + * @details Inputs: BP set speed, arterial pressure + * @details Outputs: calcBloodFlowRate + * @return none + *************************************************************************/ +static void calcBloodFlow( void ) +{ + F32 artPres = getLongFilteredArterialPressure(); + F32 artPres_2 = pow( artPres, 2.0 ); + F32 motSpd = BP_PWM_TO_MOTOR_SPEED_RPM( bloodPumpPWMDutyCyclePctSet ); // TODO - should we use measured speed? getMeasuredBloodPumpSpeed() + F32 motSpd_2 = pow( motSpd, 2.0 ); + F32 rotSpd = motSpd / BP_GEAR_RATIO; + F32 strokeSpd = rotSpd * 2.0; // 1 rotor revolution = 2 strokes + + // Calculate compensated stroke volume (in mL). + bloodPCSV = BLOOD_PC2 * artPres_2 + BLOOD_PC1 * artPres + BLOOD_NSV; + bloodSCSV = bloodPCSV * ( 1.0 + BLOOD_SC2 * motSpd_2 + BLOOD_SC1 * motSpd + BLOOD_SC0 ); + bloodPSCSV = bloodSCSV * ( 1.0 + BLOOD_PSC2 * artPres_2 + BLOOD_PSC1 * artPres + BLOOD_PSC0 ); + bloodHSWF = ( ( motSpd - BLOOD_TS0 > 0.0 ? motSpd - BLOOD_TS0 : 0.0 ) - ( motSpd - BLOOD_TS1 > 0.0 ? motSpd - BLOOD_TS1 : 0.0 ) ) / ( BLOOD_TS1 - BLOOD_TS0 ); + bloodLSWF = 1.0 - bloodHSWF; + bloodPSCSVT = bloodLSWF * bloodPCSV + bloodHSWF * bloodPSCSV; + + // Blood flow = stroke speed (strokes/min) x stroke volume (mL/stroke) = mL/min + calcBloodFlowRate = strokeSpd * bloodPSCSVT; +} +#endif /*********************************************************************//** * @brief @@ -526,6 +584,10 @@ checkBloodFlowSensorSignalStrength(); } +#ifdef ENABLE_ALTERNATE_FLOW + calcBloodFlow(); +#endif + // Publish blood flow data on interval publishBloodFlowData(); } @@ -913,7 +975,11 @@ payload.measRotorSpd = getMeasuredBloodPumpRotorSpeed(); payload.measPumpSpd = getMeasuredBloodPumpSpeed(); payload.measMCSpd = getMeasuredBloodPumpMCSpeed(); +#ifdef ENABLE_ALTERNATE_FLOW + payload.measMCCurr = calcBloodFlowRate; +#else payload.measMCCurr = getMeasuredBloodPumpMCCurrent(); +#endif payload.pwmDC = bloodPumpPWMDutyCyclePctSet * FRACTION_TO_PERCENT_FACTOR; payload.flowSigStrength = getMeasuredBloodFlowSignalStrength() * FRACTION_TO_PERCENT_FACTOR; broadcastBloodFlowData( &payload );