Index: firmware/App/Controllers/DialInFlow.c =================================================================== diff -u -r1a685471524555a374854c0c9ec8e208e71fe2df -r933a18d740285e70be9d00696ed0f5a5381bc8e4 --- firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision 1a685471524555a374854c0c9ec8e208e71fe2df) +++ firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision 933a18d740285e70be9d00696ed0f5a5381bc8e4) @@ -28,6 +28,7 @@ #include "OperationModes.h" #include "PersistentAlarm.h" #include "PIControllers.h" +#include "SafetyShutdown.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "TaskPriority.h" @@ -54,7 +55,10 @@ #define DIP_HOME_RATE 100 ///< target pump speed (in estimate mL/min) for homing. #define DIP_HOME_TIMEOUT_MS 10000 ///< maximum time allowed for homing to complete (in ms). -#define DIP_SPEED_CALC_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< interval (ms/task time) at which the dialysate inlet pump speed is calculated. +/// interval (ms/task time) at which the blood pump speed is calculated (every 40 ms). +#define DIP_SPEED_CALC_INTERVAL ( 40 / TASK_PRIORITY_INTERVAL ) +/// number of hall sensor counts kept in buffer to hold last 1 second of count data. +#define DIP_SPEED_CALC_BUFFER__LEN ( 1000 / DIP_SPEED_CALC_INTERVAL / TASK_PRIORITY_INTERVAL ) #define DIP_HALL_EDGE_COUNTS_PER_REV 48 ///< number of hall sensor edge counts per motor revolution. #define DIP_MAX_FLOW_VS_SPEED_DIFF_RPM 200.0 ///< maximum difference between measured motor speed and speed implied by measured flow. @@ -144,8 +148,9 @@ static F32 dialInFlowCalGain = 1.0; ///< dialysate flow calibration gain. static F32 dialInFlowCalOffset = 0.0; ///< dialysate flow calibration offset. -static OVERRIDE_U32_T dialInFlowDataPublishInterval = { DIAL_IN_FLOW_DATA_PUB_INTERVAL, DIAL_IN_FLOW_DATA_PUB_INTERVAL, DIAL_IN_FLOW_DATA_PUB_INTERVAL, 0 }; ///< interval (in ms) at which to publish dialIn flow data to CAN bus -static OVERRIDE_S32_T targetDialInFlowRate = { 0, 0, 0, 0 }; ///< requested dialIn flow rate +/// interval (in ms) at which to publish dialIn flow data to CAN bus +static OVERRIDE_U32_T dialInFlowDataPublishInterval = { DIAL_IN_FLOW_DATA_PUB_INTERVAL, DIAL_IN_FLOW_DATA_PUB_INTERVAL, DIAL_IN_FLOW_DATA_PUB_INTERVAL, 0 }; +static S32 targetDialInFlowRate = 0; ///< requested dialIn flow rate static OVERRIDE_F32_T measuredDialInFlowRate = { 0.0, 0.0, 0.0, 0 }; ///< measured dialysate inlet flow rate static OVERRIDE_F32_T dialInPumpRotorSpeedRPM = { 0.0, 0.0, 0.0, 0 }; ///< measured dialysate inlet pump rotor speed static OVERRIDE_F32_T dialInPumpSpeedRPM = { 0.0, 0.0, 0.0, 0 }; ///< measured dialysate inlet pump motor speed @@ -159,7 +164,8 @@ static BOOL dipStopAtHomePosition = FALSE; ///< stop dialysate inlet pump at next home position static U32 dipHomeStartTime = 0; ///< when did dialysate inlet pump home command begin? (in ms) -static U16 dipLastMotorHallSensorCount = 0; ///< last hall sensor count for the dialysate inlet pump motor +static U16 dipLastMotorHallSensorCounts[ DIP_SPEED_CALC_BUFFER__LEN ]; ///< last hall sensor count for the blood pump motor +static U32 dipMotorSpeedCalcIdx = 0; ///< index into 1 second buffer of motor speed hall sensor counts static U32 dipMotorSpeedCalcTimerCtr = 0; ///< counter determines interval for calculating dialysate inlet pump motor speed from hall sensor count. static U32 errorDialInFlowVsMotorSpeedPersistTimerCtr = 0; ///< persistence timer counter for flow vs. motor speed error condition. @@ -208,15 +214,22 @@ * @return none *************************************************************************/ void initDialInFlow( void ) -{ - dipLastMotorHallSensorCount = getFPGADialInPumpHallSensorCount(); +{ + U32 i; stopDialInPump(); setDialInPumpDirection( MOTOR_DIR_FORWARD ); // zero rolling flow average buffer resetDialInFlowMovingAverage(); + // zero motor hall sensors counts buffer + dipMotorSpeedCalcIdx = 0; + for ( i = 0; i < DIP_SPEED_CALC_BUFFER__LEN; i++ ) + { + dipLastMotorHallSensorCounts[ i ] = 0; + } + // initialize dialysate inlet flow PI controller initializePIController( PI_CONTROLLER_ID_DIALYSATE_FLOW, MIN_DIAL_IN_PUMP_PWM_DUTY_CYCLE, DIP_P_COEFFICIENT, DIP_I_COEFFICIENT, @@ -250,7 +263,7 @@ if ( flowRate <= MAX_DIAL_IN_FLOW_RATE ) { resetDialInFlowMovingAverage(); - targetDialInFlowRate.data = ( dir == MOTOR_DIR_FORWARD ? (S32)flowRate : (S32)flowRate * -1 ); + targetDialInFlowRate = ( dir == MOTOR_DIR_FORWARD ? (S32)flowRate : (S32)flowRate * -1 ); dialInPumpDirection = dir; dialInPumpControlMode = mode; // set PWM duty cycle target to an estimated initial target to ramp to based on target flow rate - then we'll control to flow when ramp completed @@ -304,7 +317,7 @@ *************************************************************************/ void signalDialInPumpHardStop( void ) { - targetDialInFlowRate.data = 0; + targetDialInFlowRate = 0; stopDialInPump(); dialInPumpState = DIAL_IN_PUMP_OFF_STATE; dialInPumpPWMDutyCyclePct = 0.0; @@ -461,7 +474,7 @@ DIAL_IN_PUMP_STATE_T result = DIAL_IN_PUMP_OFF_STATE; // if we've been given a flow rate, setup ramp up and transition to ramp up state - if ( getTargetDialInFlowRate() != 0 ) + if ( targetDialInFlowRate != 0 ) { // set initial PWM duty cycle dialInPumpPWMDutyCyclePctSet = DIP_PWM_ZERO_OFFSET + MAX_DIAL_IN_PUMP_PWM_STEP_UP_CHANGE; @@ -489,7 +502,7 @@ DIAL_IN_PUMP_STATE_T result = DIAL_IN_PUMP_RAMPING_UP_STATE; // have we been asked to stop the dialIn pump? - if ( 0 == getTargetDialInFlowRate() ) + if ( 0 == targetDialInFlowRate ) { // start ramp down to stop dialInPumpPWMDutyCyclePctSet -= MAX_DIAL_IN_PUMP_PWM_STEP_DN_CHANGE; @@ -579,7 +592,7 @@ { if ( dialInPumpControlModeSet == PUMP_CONTROL_MODE_CLOSED_LOOP ) { - F32 tgtFlow = (F32)getTargetDialInFlowRate(); + F32 tgtFlow = (F32)targetDialInFlowRate; F32 actFlow = getMeasuredDialInFlowRate(); F32 newPWM; @@ -693,15 +706,8 @@ *************************************************************************/ S32 getTargetDialInFlowRate( void ) { - S32 result = targetDialInFlowRate.data; - - if ( OVERRIDE_KEY == targetDialInFlowRate.override ) - { - result = targetDialInFlowRate.ovData; - } - - return result; -} + return targetDialInFlowRate; +} /*********************************************************************//** * @brief @@ -839,7 +845,7 @@ { DIALIN_PUMP_STATUS_PAYLOAD_T payload; - payload.setPoint = (S32)getTargetDialInFlowRate(); + payload.setPoint = targetDialInFlowRate; payload.measFlow = getMeasuredDialInFlowRate(); payload.measRotorSpd = getMeasuredDialInPumpRotorSpeed(); payload.measPumpSpd = getMeasuredDialInPumpSpeed(); @@ -906,7 +912,10 @@ if ( ++dipMotorSpeedCalcTimerCtr >= DIP_SPEED_CALC_INTERVAL ) { U16 dipMotorHallSensorCount = getFPGADialInPumpHallSensorCount(); - U16 incDelta = ( dipMotorHallSensorCount >= dipLastMotorHallSensorCount ? dipMotorHallSensorCount - dipLastMotorHallSensorCount : ( HEX_64_K - dipLastMotorHallSensorCount ) + dipMotorHallSensorCount ); + U32 nextIdx = INC_WRAP( dipMotorSpeedCalcIdx, 0, DIP_SPEED_CALC_BUFFER__LEN - 1 ); + U16 incDelta = ( dipMotorHallSensorCount >= dipLastMotorHallSensorCounts[ nextIdx ] ? \ + dipMotorHallSensorCount - dipLastMotorHallSensorCounts[ nextIdx ] : \ + ( HEX_64_K - dipLastMotorHallSensorCounts[ nextIdx ] ) + dipMotorHallSensorCount ); U16 decDelta = HEX_64_K - incDelta; U16 delta; @@ -923,7 +932,8 @@ } // update last count for next time - dipLastMotorHallSensorCount = dipMotorHallSensorCount; + dipLastMotorHallSensorCounts[ nextIdx ] = dipMotorHallSensorCount; + dipMotorSpeedCalcIdx = nextIdx; dipMotorSpeedCalcTimerCtr = 0; } } @@ -1017,7 +1027,7 @@ static void checkDialInPumpSpeeds( void ) { F32 measMotorSpeed = getMeasuredDialInPumpSpeed(); - S32 cmdRate = getTargetDialInFlowRate(); + S32 cmdRate = targetDialInFlowRate; // check for pump running while commanded off if ( 0 == cmdRate ) @@ -1028,6 +1038,7 @@ { #ifndef DISABLE_PUMP_SPEED_CHECKS SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DIAL_IN_PUMP_OFF_CHECK, measMotorSpeed ); + activateSafetyShutdown(); #endif } } @@ -1198,7 +1209,7 @@ F32 sigStrength = getMeasuredDialInFlowSignalStrength(); BOOL outOfRange = ( sigStrength < MIN_FLOW_SIG_STRENGTH ? TRUE : FALSE ); - checkPersistentAlarm( PERSISTENT_ALARM_DIALYSATE_FLOW_SIGNAL_STRENGTH, outOfRange, sigStrength ); + checkPersistentAlarm( PERSISTENT_ALARM_DIALYSATE_FLOW_SIGNAL_STRENGTH, outOfRange, sigStrength, MIN_FLOW_SIG_STRENGTH ); } #endif } @@ -1374,9 +1385,7 @@ } if ( ctrlMode < NUM_OF_PUMP_CONTROL_MODES ) { - targetDialInFlowRate.ovInitData = targetDialInFlowRate.data; // backup current target flow rate - targetDialInFlowRate.ovData = value; - targetDialInFlowRate.override = OVERRIDE_KEY; + targetDialInFlowRate = value; result = setDialInPumpTargetFlowRate( abs(value), dir, (PUMP_CONTROL_MODE_T)ctrlMode ); } } @@ -1386,30 +1395,6 @@ /*********************************************************************//** * @brief - * The testResetTargetDialInFlowRateOverride function resets the override of the - * target dialysate inlet flow rate. - * @details Inputs: none - * @details Outputs: targetDialInFlowRate - * @return TRUE if override reset successful, FALSE if not - *************************************************************************/ -BOOL testResetTargetDialInFlowRateOverride( void ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - targetDialInFlowRate.data = targetDialInFlowRate.ovInitData; // restore pre-override target flow rate - targetDialInFlowRate.override = OVERRIDE_RESET; - targetDialInFlowRate.ovInitData = 0; - targetDialInFlowRate.ovData = 0; - result = setDialInPumpTargetFlowRate( targetDialInFlowRate.data, dialInPumpDirection, dialInPumpControlMode ); - } - - return result; -} - -/*********************************************************************//** - * @brief * The testResetMeasuredDialInFlowRateOverride function overrides the measured * dialIn flow rate. * @details Inputs: none