Index: firmware/App/Controllers/BloodFlow.c =================================================================== diff -u -reb75e7807c5e85481f1447a3dfebf11db16d8259 -r323f79ab9cd2a2b912b97b804aa2f07b6ea92693 --- firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision eb75e7807c5e85481f1447a3dfebf11db16d8259) +++ firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 323f79ab9cd2a2b912b97b804aa2f07b6ea92693) @@ -16,6 +16,7 @@ ***************************************************************************/ #include // Used for fabs() functions +#include // Used for memset() #include "BloodFlow.h" #include "CpldInterface.h" @@ -86,10 +87,9 @@ #define DATA_PUBLISH_COUNTER_START_COUNT 20 ///< Data publish counter start count. -#define MAX_BP_SPEED_FILTER_SAMPLES 600 ///< Max MA samples (50 ms ticks); 600 = 30 s span at 50 mL/min. -#define BP_SPEED_FILTER_TIME_FLOW_PRODUCT 1500 ///< s*mL/min; filter duration T = PRODUCT / |Q| (e.g. 2.5 s @ 600, 5 s @ 300). -#define BP_SPEED_FILTER_DEFAULT_SAMPLES 20 ///< MA samples when target flow is zero (~1 s @ 50 ms). -#define BP_SPEED_FILTER_MIN_SAMPLES 5 ///< Minimum MA window (samples). +#define BP_SPEED_FILTER_TIME_FLOW_PRODUCT 1500 ///< s*mL/min; filter duration T = PRODUCT / |Qb| (e.g. 2.5 sec @ 600, 3 sec @ 500, 5 sec @ 300). +#define MAX_BP_SPEED_FILTER_SAMPLES ( ( BP_SPEED_FILTER_TIME_FLOW_PRODUCT / 50 ) * (MS_PER_SECOND / TASK_GENERAL_INTERVAL) ) ///< Max MA samples at Qb_min=50 mL/min: Nmax = (1500/50)*20 = 600. +#define BP_SPEED_FILTER_DEFAULT_SAMPLES 20 ///< MA samples when target flow is zero: 20 samples at 1 sec. #define BP_TORQUE_PERIOD_RESOLUTION_US 1.0F ///< Blood pump torque period resolution in microseconds (1 us). #define BP_1KHZ_TO_TORQUE_CONVERSION_MNM 10.0F ///< Blood pump 1kHz to torque conversion in milli-newtonmeter @@ -250,10 +250,7 @@ bpMaxRotorCountForWear.override = OVERRIDE_RESET; // Initialize pump speed filter - for ( i = 0; i < MAX_BP_SPEED_FILTER_SAMPLES; i++ ) - { - rpmReadings[ i ] = 0.0F; - } + memset( rpmReadings, 0, sizeof( rpmReadings ) ); resetBloodPumpRPMMovingAverage(); // Reset pump rotor count @@ -956,53 +953,46 @@ /*********************************************************************//** * @brief * The calcBpSpeedFilterWindowSamples function computes how many general-task - * samples to use for the blood pump motor speed moving average. Let Q be the - * magnitude of target blood flow (mL/min). Averaging duration T (seconds) is - * BP_SPEED_FILTER_TIME_FLOW_PRODUCT / Q. Sample count N is round( T times - * MS_PER_SECOND / TASK_GENERAL_INTERVAL ), clamped to BP_SPEED_FILTER_MIN_SAMPLES - * through MAX_BP_SPEED_FILTER_SAMPLES. If target blood flow is zero, N is - * BP_SPEED_FILTER_DEFAULT_SAMPLES. - * @details \b Inputs: targetBloodFlowRate, MAX_SETTABLE_BLOOD_FLOW_RATE, - * BP_SPEED_FILTER_TIME_FLOW_PRODUCT, MS_PER_SECOND, TASK_GENERAL_INTERVAL, + * samples to use for the blood pump motor speed moving average based on the + * commanded blood flow rate (Qb). + * @details \b Inputs: targetBloodFlowRate (Qb), MAX_SETTABLE_BLOOD_FLOW_RATE, + * BP_SPEED_FILTER_TIME_FLOW_PRODUCT, TASK_GENERAL_INTERVAL, * BP_SPEED_FILTER_MIN_SAMPLES, BP_SPEED_FILTER_DEFAULT_SAMPLES, * MAX_BP_SPEED_FILTER_SAMPLES * @details \b Outputs: none * @return moving-average window size in samples *************************************************************************/ static U32 calcBpSpeedFilterWindowSamples( void ) { - U32 absFlowU32; - F32 tFilterSec; - F32 windowSamplesF; - U32 windowSamples; + U32 absFlowU32 = 0; + F32 tFilterSec = 0.0F; + F32 windowSamplesF = 0.0F; + U32 windowSamples = 0; - if ( 0 == targetBloodFlowRate ) + if ( 0 != targetBloodFlowRate ) { - return BP_SPEED_FILTER_DEFAULT_SAMPLES; - } + absFlowU32 = ( targetBloodFlowRate >= 0 ) ? (U32)targetBloodFlowRate : (U32)( -targetBloodFlowRate ); + if ( 0 != absFlowU32 ) + { + if ( absFlowU32 > (U32)MAX_SETTABLE_BLOOD_FLOW_RATE ) + { + absFlowU32 = (U32)MAX_SETTABLE_BLOOD_FLOW_RATE; + } - absFlowU32 = ( targetBloodFlowRate >= 0 ) ? (U32)targetBloodFlowRate : (U32)( -targetBloodFlowRate ); - if ( 0U == absFlowU32 ) - { - return BP_SPEED_FILTER_DEFAULT_SAMPLES; - } - if ( absFlowU32 > (U32)MAX_SETTABLE_BLOOD_FLOW_RATE ) - { - absFlowU32 = (U32)MAX_SETTABLE_BLOOD_FLOW_RATE; - } + tFilterSec = (F32)BP_SPEED_FILTER_TIME_FLOW_PRODUCT / (F32)absFlowU32; + windowSamplesF = ( tFilterSec * (F32)MS_PER_SECOND / (F32)TASK_GENERAL_INTERVAL ) + 0.5F; + windowSamples = (U32)windowSamplesF; - tFilterSec = (F32)BP_SPEED_FILTER_TIME_FLOW_PRODUCT / (F32)absFlowU32; - windowSamplesF = ( tFilterSec * (F32)MS_PER_SECOND / (F32)TASK_GENERAL_INTERVAL ) + 0.5F; - windowSamples = (U32)windowSamplesF; - - if ( windowSamples < BP_SPEED_FILTER_MIN_SAMPLES ) - { - windowSamples = BP_SPEED_FILTER_MIN_SAMPLES; + if ( windowSamples < BP_SPEED_FILTER_DEFAULT_SAMPLES ) + { + windowSamples = BP_SPEED_FILTER_DEFAULT_SAMPLES; + } + if ( windowSamples > (U32)MAX_BP_SPEED_FILTER_SAMPLES ) + { + windowSamples = (U32)MAX_BP_SPEED_FILTER_SAMPLES; + } + } } - if ( windowSamples > (U32)MAX_BP_SPEED_FILTER_SAMPLES ) - { - windowSamples = (U32)MAX_BP_SPEED_FILTER_SAMPLES; - } return windowSamples; } @@ -1023,10 +1013,7 @@ if ( filterWindowSamples != rpmFilterActiveWindow ) { - rpmReadingsIdx = 0; - rpmReadingsCount = 0; - rpmReadingsTotal = 0.0F; - filteredBloodPumpSpeed = 0.0F; + resetBloodPumpRPMMovingAverage(); rpmFilterActiveWindow = filterWindowSamples; }