Index: firmware/App/Controllers/DialOutFlow.c =================================================================== diff -u -ra3a01327c8fe80f65f6658ae6cbef4910a4a8033 -r8e7158d8231435496fcf1d5649e51babf859ccc7 --- firmware/App/Controllers/DialOutFlow.c (.../DialOutFlow.c) (revision a3a01327c8fe80f65f6658ae6cbef4910a4a8033) +++ firmware/App/Controllers/DialOutFlow.c (.../DialOutFlow.c) (revision 8e7158d8231435496fcf1d5649e51babf859ccc7) @@ -1,14 +1,14 @@ /************************************************************************** * -* Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-2021 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file DialOutFlow.c * * @author (last) Sean Nash -* @date (last) 19-Jun-2020 +* @date (last) 01-Dec-2020 * * @author (original) Sean * @date (original) 24-Jan-2020 @@ -25,6 +25,7 @@ #include "InternalADC.h" #include "OperationModes.h" #include "PIControllers.h" +#include "SafetyShutdown.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "TaskPriority.h" @@ -38,7 +39,8 @@ // ********** private definitions ********** -#define DIAL_OUT_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Interval (ms/task time) at which the dialysate outlet pump data is published on the CAN bus. +/// Interval (ms/task time) at which the dialysate outlet pump data is published on the CAN bus. +#define DIAL_OUT_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) #define MAX_DIAL_OUT_FLOW_RATE 650 ///< Maximum dialysate outlet pump flow rate in mL/min. #define MIN_DIAL_OUT_FLOW_RATE 100 ///< Minimum dialysate outlet pump flow rate in mL/min. @@ -55,19 +57,23 @@ #define DOP_HOME_RATE 100 ///< target pump speed (in estimate mL/min) for homing. #define DOP_HOME_TIMEOUT_MS 10000 ///< maximum time allowed for homing to complete (in ms). -#define DOP_SPEED_CALC_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< interval (ms/task time) at which the dialysate outlet pump speed is calculated. +/// interval (ms/task time) at which the blood pump speed is calculated (every 40 ms). +#define DOP_SPEED_CALC_INTERVAL ( 40 / TASK_PRIORITY_INTERVAL ) +/// number of hall sensor counts kept in buffer to hold last 1 second of count data. +#define DOP_SPEED_CALC_BUFFER__LEN ( 1000 / DOP_SPEED_CALC_INTERVAL / TASK_PRIORITY_INTERVAL ) #define DOP_HALL_EDGE_COUNTS_PER_REV 48 ///< number of hall sensor edge counts per motor revolution. #define DOP_MAX_MOTOR_SPEED_WHILE_OFF_RPM 100.0 ///< maximum motor speed (RPM) while motor is commanded off. #define DOP_MAX_ROTOR_VS_MOTOR_DIFF_RPM 5.0 ///< maximum difference in speed between motor and rotor (in rotor RPM). #define DOP_MAX_MOTOR_SPEED_ERROR_RPM 300.0 ///< maximum difference in speed between measured and commanded RPM. -#define DOP_OFF_ERROR_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) for motor off error condition. -#define DOP_MOTOR_SPEED_ERROR_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) motor speed error condition. -#define DOP_ROTOR_SPEED_ERROR_PERSIST ((12 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) rotor speed error condition. +#define DOP_OFF_ERROR_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) for motor off error condition. +#define DOP_MOTOR_SPEED_ERROR_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) motor speed error condition. +#define DOP_ROTOR_SPEED_ERROR_PERSIST ((12 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) rotor speed error condition. +#define DOP_DIRECTION_ERROR_PERSIST (250 / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) pump direction error condition. #define DOP_MAX_CURR_WHEN_STOPPED_MA 150.0 ///< Motor controller current should not exceed this when pump should be stopped. #define DOP_MIN_CURR_WHEN_RUNNING_MA 150.0 ///< Motor controller current should always exceed this when pump should be running. -#define DOP_MAX_CURR_WHEN_RUNNING_MA 1000.0 ///< Motor controller current should not exceed this when pump should be running. +#define DOP_MAX_CURR_WHEN_RUNNING_MA 2000.0 ///< Motor controller current should not exceed this when pump should be running. #define DOP_MAX_CURR_ERROR_DURATION_MS 2000 ///< Motor controller current errors persisting beyond this duration will trigger an alarm. #define DOP_SPEED_ADC_TO_RPM_FACTOR 1.280938 ///< Conversion factor from ADC counts to RPM for dialysate outlet pump motor. @@ -78,12 +84,13 @@ /*** setDialOutFlowRxTotalVolumeAndRxTime ***/ -#define DOP_REV_PER_LITER 150.24 ///< Rotor revolutions per liter. +#define DOP_REV_PER_LITER 150.0 ///< Rotor revolutions per liter. #define DOP_ML_PER_MIN_TO_PUMP_RPM_FACTOR ( DOP_REV_PER_LITER / ML_PER_LITER ) ///< Conversion factor from mL/min to pump motor RPM. #define DOP_GEAR_RATIO 32.0 ///< Pump motor to pump gear ratio. #define DOP_MOTOR_RPM_TO_PWM_DC_FACTOR 0.00028 ///< ~28 DPo motor RPM = 1% PWM duty cycle. #define DOP_PWM_ZERO_OFFSET 0.1 ///< 10% PWM duty cycle = zero speed. -#define DOP_PWM_FROM_ML_PER_MIN(rate) ( (rate) * DOP_ML_PER_MIN_TO_PUMP_RPM_FACTOR * DOP_GEAR_RATIO * DOP_MOTOR_RPM_TO_PWM_DC_FACTOR + DOP_PWM_ZERO_OFFSET ) ///< Macro converts a flow rate to an estimated PWM duty cycle %. +/// Macro converts a flow rate to an estimated PWM duty cycle %. +#define DOP_PWM_FROM_ML_PER_MIN(rate) ( (rate) * DOP_ML_PER_MIN_TO_PUMP_RPM_FACTOR * DOP_GEAR_RATIO * DOP_MOTOR_RPM_TO_PWM_DC_FACTOR + DOP_PWM_ZERO_OFFSET ) /// Enumeration of dialysate outlet pump controller states. typedef enum DialOutPump_States @@ -146,20 +153,18 @@ static BOOL dopStopAtHomePosition = FALSE; ///< stop dialysate outlet pump at next home position static U32 dopHomeStartTime = 0; ///< when did dialysate outlet pump home command begin? (in ms) -static U16 dopLastMotorHallSensorCount = 0; ///< last hall sensor count for the dialysate outlet pump motor -static MOTOR_DIR_T dopMotorDirectionFromHallSensors = MOTOR_DIR_FORWARD; ///< pump direction according to hall sensor count +static U16 dopLastMotorHallSensorCounts[ DOP_SPEED_CALC_BUFFER__LEN ]; ///< last hall sensor count for the dialysate outlet pump motor +static U32 dopMotorSpeedCalcIdx = 0; ///< index into 1 second buffer of motor speed hall sensor counts static U32 dopMotorSpeedCalcTimerCtr = 0; ///< counter determines interval for calculating dialysate outlet pump motor speed from hall sensor count. static U32 errorDialOutMotorOffPersistTimerCtr = 0; ///< persistence timer counter for motor off check error condition. static U32 errorDialOutMotorSpeedPersistTimerCtr = 0; ///< persistence timer counter for motor speed error condition. static U32 errorDialOutRotorSpeedPersistTimerCtr = 0; ///< persistence timer counter for rotor speed error condition. +static U32 errorDialOutPumpDirectionPersistTimerCtr = 0; ///< persistence timer counter for pump direction error condition. static DIAL_OUT_PUMP_SELF_TEST_STATE_T dialOutPumpSelfTestState = DIAL_OUT_PUMP_SELF_TEST_STATE_START; ///< Current state of the dialysate outlet pump self-test state machine. static U32 dialOutPumpSelfTestTimerCount = 0; ///< Timer counter for time reference during self-test. -// Broadcasting record -DIAL_OUT_FLOW_DATA_T dialOutBroadCastVariables; ///< Record containing latest dialysate outlet data for broadcasting. - // ********** private function prototypes ********** static DIAL_OUT_PUMP_STATE_T handleDialOutPumpOffState( void ); @@ -185,35 +190,30 @@ /*********************************************************************//** * @brief * The initDialOutFlow function initializes the DialOutFlow module. - * @details - * Inputs : none - * Outputs : DialOutFlow module initialized. + * @details Inputs: none + * @details Outputs: DialOutFlow module initialized. * @return none *************************************************************************/ void initDialOutFlow( void ) { U32 i; - dopLastMotorHallSensorCount = getFPGADialOutPumpHallSensorCount(); - stopDialOutPump(); setDialOutPumpDirection( MOTOR_DIR_FORWARD ); + // zero motor hall sensors counts buffer + dopMotorSpeedCalcIdx = 0; + for ( i = 0; i < DOP_SPEED_CALC_BUFFER__LEN; i++ ) + { + dopLastMotorHallSensorCounts[ i ] = 0; + } + // initialize load cell weights for ( i = 0; i < NUM_OF_LOAD_CELLS; i++ ) { loadCellWeightInGrams[ i ].data = 0.0; } - // initialize broadcast data - dialOutBroadCastVariables.refUFVolMl = 0.0; - dialOutBroadCastVariables.measUFVolMl = 0.0; - dialOutBroadCastVariables.measRotSpdRPM = 0.0; - dialOutBroadCastVariables.measSpdRPM = 0.0; - dialOutBroadCastVariables.measMCSpdRPM = 0.0; - dialOutBroadCastVariables.measMCCurrmA = 0.0; - dialOutBroadCastVariables.setPWMpct = 0.0; - // initialize dialysate outlet flow PI controller initializePIController( PI_CONTROLLER_ID_ULTRAFILTRATION, MIN_DIAL_OUT_PUMP_PWM_DUTY_CYCLE, DOP_P_COEFFICIENT, DOP_I_COEFFICIENT, @@ -224,9 +224,8 @@ * @brief * The setDialOutPumpTargetRate function sets a new target flow rate, pump * direction, and control mode. - * @details - * Inputs : isDialOutPumpOn, dialOutPumpDirectionSet - * Outputs : targetDialOutFlowRate, dialOutPumpdirection, dialOutPumpPWMDutyCyclePct + * @details Inputs: isDialOutPumpOn, dialOutPumpDirectionSet + * @details Outputs: targetDialOutFlowRate, dialOutPumpdirection, dialOutPumpPWMDutyCyclePct * @param flowRate new target dialysate outlet flow rate * @param dir new dialysate outlet flow direction * @param mode new control mode @@ -297,9 +296,8 @@ * @brief * The setDialOutUFVolumes function sets the ultrafiltration reference and * measured total volumes (in mL). - * @details - * Inputs : none - * Outputs : referenceUFVolumeInMl and totalMeasuredUFVolumeInMl + * @details Inputs: none + * @details Outputs: referenceUFVolumeInMl and totalMeasuredUFVolumeInMl * @param refVol New ultrafiltration reference volume (in mL) * @param totVol New ultrafiltration total volume (in mL) * @return none @@ -314,9 +312,8 @@ * @brief * The signalDialOutPumpHardStop function stops the dialysate outlet pump * immediately. - * @details - * Inputs : none - * Outputs : Dialysate outlet pump stopped, set point reset, state changed to off + * @details Inputs: none + * @details Outputs: Dialysate outlet pump stopped, set point reset, state changed to off * @return none *************************************************************************/ void signalDialOutPumpHardStop( void ) @@ -334,9 +331,8 @@ * The signalDialOutPumpRotorHallSensor function handles the dialysate outlet * pump rotor hall sensor detection. Calculates rotor speed (in RPM). * Stops pump if there is a pending request to home the pump. - * @details - * Inputs : dopRotorRevStartTime, dopStopAtHomePosition - * Outputs : dopRotorRevStartTime, dialOutPumpRotorSpeedRPM + * @details Inputs: dopRotorRevStartTime, dopStopAtHomePosition + * @details Outputs: dopRotorRevStartTime, dialOutPumpRotorSpeedRPM * @return none *************************************************************************/ void signalDialOutPumpRotorHallSensor( void ) @@ -359,9 +355,8 @@ /*********************************************************************//** * @brief * The homeDialOutPump function initiates a dialysate outlet pump home operation. - * @details - * Inputs : dialOutPumpState - * Outputs : dopStopAtHomePosition, dopHomeStartTime, dialysate outlet pump started (slow) + * @details Inputs: dialOutPumpState + * @details Outputs: dopStopAtHomePosition, dopHomeStartTime, dialysate outlet pump started (slow) * @return none *************************************************************************/ BOOL homeDialOutPump( void ) @@ -380,11 +375,23 @@ /*********************************************************************//** * @brief + * The isDialOutPumpRunning function returns whether the dialysate outlet + * pump is currently running or not. + * @details Inputs: isDialOutPumpOn + * @details Outputs: none + * @return isDialOutPumpOn + *************************************************************************/ +BOOL isDialOutPumpRunning( void ) +{ + return isDialOutPumpOn; +} + +/*********************************************************************//** + * @brief * The setDialOutUFVolumes function sets the ultrafiltration reference and * measured total volumes (in mL). - * @details - * Inputs : none - * Outputs : loadCellWeightInGrams[] + * @details Inputs: none + * @details Outputs: loadCellWeightInGrams[] * @param res1Primary New weight from primary load cell of reservoir 1 * @param res1Backup New weight from backup load cell of reservoir 1 * @param res2Primary New weight from primary load cell of reservoir 2 @@ -408,9 +415,8 @@ * The execDialOutFlowMonitor function executes the dialysate outlet pump * and load cell sensor monitor. Checks are performed. Data is published * at appropriate interval. - * @details - * Inputs : latest sensor data - * Outputs : dialOutPumpMCSpeedRPM, dialOutPumpMCCurrentmA + * @details Inputs: latest sensor data + * @details Outputs: dialOutPumpMCSpeedRPM, dialOutPumpMCCurrentmA * @return none *************************************************************************/ void execDialOutFlowMonitor( void ) @@ -444,9 +450,8 @@ * @brief * The execDialOutFlowController function executes the dialysate outlet pump * ultrafiltration controller state machine. - * @details - * Inputs : dialOutPumpState - * Outputs : dialOutPumpState + * @details Inputs: dialOutPumpState + * @details Outputs: dialOutPumpState * @return none *************************************************************************/ void execDialOutFlowController( void ) @@ -479,9 +484,8 @@ * @brief * The handleDialOutPumpOffState function handles the dialOut pump off state * of the dialOut pump controller state machine. - * @details - * Inputs : targetDialOutFlowRate, dialOutPumpDirection - * Outputs : dialOutPumpPWMDutyCyclePctSet, dialOutPumpDirectionSet, isDialOutPumpOn + * @details Inputs: targetDialOutFlowRate, dialOutPumpDirection + * @details Outputs: dialOutPumpPWMDutyCyclePctSet, dialOutPumpDirectionSet, isDialOutPumpOn * @return next state *************************************************************************/ static DIAL_OUT_PUMP_STATE_T handleDialOutPumpOffState( void ) @@ -512,17 +516,16 @@ * @brief * The handleDialOutPumpRampingUpState function handles the ramp up state * of the dialOut pump controller state machine. - * @details - * Inputs : dialOutPumpPWMDutyCyclePctSet - * Outputs : dialOutPumpPWMDutyCyclePctSet + * @details Inputs: dialOutPumpPWMDutyCyclePctSet + * @details Outputs: dialOutPumpPWMDutyCyclePctSet * @return next state *************************************************************************/ static DIAL_OUT_PUMP_STATE_T handleDialOutPumpRampingUpState( void ) { DIAL_OUT_PUMP_STATE_T result = DIAL_OUT_PUMP_RAMPING_UP_STATE; // have we been asked to stop the dialOut pump? - if ( dialOutPumpPWMDutyCyclePct < NEARLY_ZERO ) + if ( dialOutPumpPWMDutyCyclePct < (MAX_DIAL_OUT_PUMP_PWM_STEP_DN_CHANGE + DOP_PWM_ZERO_OFFSET) ) { // start ramp down to stop dialOutPumpPWMDutyCyclePctSet -= MAX_DIAL_OUT_PUMP_PWM_STEP_DN_CHANGE; @@ -556,17 +559,16 @@ * @brief * The handleDialOutPumpRampingDownState function handles the ramp down state * of the dialOut pump controller state machine. - * @details - * Inputs : dialOutPumpPWMDutyCyclePctSet - * Outputs : dialOutPumpPWMDutyCyclePctSet + * @details Inputs: dialOutPumpPWMDutyCyclePctSet + * @details Outputs: dialOutPumpPWMDutyCyclePctSet * @return next state *************************************************************************/ static DIAL_OUT_PUMP_STATE_T handleDialOutPumpRampingDownState( void ) { DIAL_OUT_PUMP_STATE_T result = DIAL_OUT_PUMP_RAMPING_DOWN_STATE; // have we essentially reached zero speed - if ( dialOutPumpPWMDutyCyclePctSet < (MAX_DIAL_OUT_PUMP_PWM_STEP_UP_CHANGE + DOP_PWM_ZERO_OFFSET) ) + if ( dialOutPumpPWMDutyCyclePctSet < (MAX_DIAL_OUT_PUMP_PWM_STEP_DN_CHANGE + DOP_PWM_ZERO_OFFSET) ) { stopDialOutPump(); result = DIAL_OUT_PUMP_OFF_STATE; @@ -598,9 +600,8 @@ * @brief * The handleDialOutPumpControlToTargetState function handles the "control to * target" state of the dialOut pump controller state machine. - * @details - * Inputs : dopControlTimerCounter, dialOutPumpControlModeSet, volumes. - * Outputs : dopControlTimerCounter, pump controlled. + * @details Inputs: dopControlTimerCounter, dialOutPumpControlModeSet, volumes. + * @details Outputs: dopControlTimerCounter, pump controlled. * @return next state *************************************************************************/ static DIAL_OUT_PUMP_STATE_T handleDialOutPumpControlToTargetState( void ) @@ -614,20 +615,22 @@ { F32 refVol = getTotalTargetDialOutUFVolumeInMl(); F32 totVol = getTotalMeasuredUFVolumeInMl(); - F32 newPWM; - F32 deltaPWM; + F32 newPWMDutyCyclePct; + F32 deltaPWMDutyCyclePct; // get new PWM from PI controller - newPWM = runPIController( PI_CONTROLLER_ID_ULTRAFILTRATION, refVol, totVol ); + newPWMDutyCyclePct = runPIController( PI_CONTROLLER_ID_ULTRAFILTRATION, refVol, totVol ); // limit PWM change to max - deltaPWM = newPWM - dialOutPumpPWMDutyCyclePctSet; - if ( fabs( deltaPWM ) > MAX_DIAL_OUT_PUMP_PWM_STEP_UP_CHANGE ) + deltaPWMDutyCyclePct = newPWMDutyCyclePct - dialOutPumpPWMDutyCyclePctSet; + if ( fabs( deltaPWMDutyCyclePct ) > MAX_DIAL_OUT_PUMP_PWM_STEP_UP_CHANGE ) { - newPWM = ( deltaPWM < 0.0 ? dialOutPumpPWMDutyCyclePctSet - MAX_DIAL_OUT_PUMP_PWM_STEP_UP_CHANGE : dialOutPumpPWMDutyCyclePctSet + MAX_DIAL_OUT_PUMP_PWM_STEP_UP_CHANGE ); + newPWMDutyCyclePct = ( deltaPWMDutyCyclePct < 0.0 ? \ + dialOutPumpPWMDutyCyclePctSet - MAX_DIAL_OUT_PUMP_PWM_STEP_UP_CHANGE : \ + dialOutPumpPWMDutyCyclePctSet + MAX_DIAL_OUT_PUMP_PWM_STEP_UP_CHANGE ); } // set new PWM - dialOutPumpPWMDutyCyclePctSet = newPWM; - setDialOutPumpControlSignalPWM( newPWM ); + dialOutPumpPWMDutyCyclePctSet = newPWMDutyCyclePct; + setDialOutPumpControlSignalPWM( newPWMDutyCyclePct ); } dopControlTimerCounter = 0; } @@ -639,9 +642,8 @@ * @brief * The setDialOutPumpControlSignalPWM function set the PWM duty cycle of * the dialysate outlet pump to a given %. - * @details - * Inputs : none - * Outputs : dialysis outlet pump PWM duty cycle is set. + * @details Inputs: none + * @details Outputs: dialysis outlet pump PWM duty cycle is set. * @param newPWM A percentage duty cycle between 0.0 and 1.0 * @return none *************************************************************************/ @@ -654,9 +656,8 @@ * @brief * The stopDialOutPump function sets the dialout flow stop signal and PWM * duty cycle to 0.0. - * @details - * Inputs : none - * Outputs : dialOut pump stop signal activated, PWM duty cycle zeroed + * @details Inputs: none + * @details Outputs: dialOut pump stop signal activated, PWM duty cycle zeroed * @return none *************************************************************************/ static void stopDialOutPump( void ) @@ -670,9 +671,8 @@ /*********************************************************************//** * @brief * The releaseDialOutPumpStop function clears the dialysate outlet pump stop signal. - * @details - * Inputs : none - * Outputs : dialysate outlet pump stop signal is cleared. + * @details Inputs: none + * @details Outputs: dialysate outlet pump stop signal is cleared. * @return none *************************************************************************/ static void releaseDialOutPumpStop( void ) @@ -684,9 +684,8 @@ * @brief * The setDialOutPumpDirection function sets the set dialOut pump direction to * the given direction. - * @details - * Inputs : none - * Outputs : dialOutPumpDirectionSet, pump direction signal set to match given direction. + * @details Inputs: none + * @details Outputs: dialOutPumpDirectionSet, pump direction signal set to match given direction. * @param dir dialysate outlet pump direction to set * @return none *************************************************************************/ @@ -714,16 +713,17 @@ * @brief * The publishDialOutFlowData function publishes dialysate outlet data at * the set interval. - * @details - * Inputs : Dialysate outlet pump data - * Outputs : Dialysate outlet pump data is published to CAN bus. + * @details Inputs: Dialysate outlet pump data + * @details Outputs: Dialysate outlet pump data is published to CAN bus. * @return none *************************************************************************/ static void publishDialOutFlowData( void ) { // publish dialysate outlet pump and UF volume data on interval if ( ++dialOutFlowDataPublicationTimerCounter >= getPublishDialOutDataInterval() ) { + DIAL_OUT_FLOW_DATA_T dialOutBroadCastVariables; + dialOutBroadCastVariables.refUFVolMl = getTotalTargetDialOutUFVolumeInMl(); dialOutBroadCastVariables.measUFVolMl = getTotalMeasuredUFVolumeInMl(); dialOutBroadCastVariables.measRotSpdRPM = getMeasuredDialOutPumpRotorSpeed(); @@ -742,36 +742,37 @@ * The updateDialOutPumpSpeedAndDirectionFromHallSensors function calculates * the dialysate outlet pump motor speed and direction from hall sensor counter on * a 1 second interval. - * @details - * Inputs : dopLastMotorHallSensorCount, dopMotorSpeedCalcTimerCtr, current count from FPGA - * Outputs : dopMotorDirectionFromHallSensors, dialOutPumpSpeedRPM + * @details Inputs: dopLastMotorHallSensorCount, dopMotorSpeedCalcTimerCtr, current count from FPGA + * @details Outputs: dopMotorDirectionFromHallSensors, dialOutPumpSpeedRPM * @return none *************************************************************************/ static void updateDialOutPumpSpeedAndDirectionFromHallSensors( void ) { if ( ++dopMotorSpeedCalcTimerCtr >= DOP_SPEED_CALC_INTERVAL ) { U16 dopMotorHallSensorCount = getFPGADialOutPumpHallSensorCount(); - U16 incDelta = ( dopMotorHallSensorCount >= dopLastMotorHallSensorCount ? dopMotorHallSensorCount - dopLastMotorHallSensorCount : ( HEX_64_K - dopLastMotorHallSensorCount ) + dopMotorHallSensorCount ); + U32 nextIdx = INC_WRAP( dopMotorSpeedCalcIdx, 0, DOP_SPEED_CALC_BUFFER__LEN - 1 ); + U16 incDelta = ( dopMotorHallSensorCount >= dopLastMotorHallSensorCounts[ nextIdx ] ? \ + dopMotorHallSensorCount - dopLastMotorHallSensorCounts[ nextIdx ] : \ + ( HEX_64_K - dopLastMotorHallSensorCounts[ nextIdx ] ) + dopMotorHallSensorCount ); U16 decDelta = HEX_64_K - incDelta; U16 delta; // determine dialysate outlet pump speed/direction from delta hall sensor count since last interval if ( incDelta < decDelta ) { - dopMotorDirectionFromHallSensors = MOTOR_DIR_FORWARD; delta = incDelta; dialOutPumpSpeedRPM.data = ( (F32)delta / (F32)DOP_HALL_EDGE_COUNTS_PER_REV ) * (F32)SEC_PER_MIN; } else { - dopMotorDirectionFromHallSensors = MOTOR_DIR_REVERSE; delta = decDelta; dialOutPumpSpeedRPM.data = ( (F32)delta / (F32)DOP_HALL_EDGE_COUNTS_PER_REV ) * (F32)SEC_PER_MIN * -1.0; } // update last count for next time - dopLastMotorHallSensorCount = dopMotorHallSensorCount; + dopLastMotorHallSensorCounts[ nextIdx ] = dopMotorHallSensorCount; + dopMotorSpeedCalcIdx = nextIdx; dopMotorSpeedCalcTimerCtr = 0; } } @@ -781,9 +782,8 @@ * The checkDialOutPumpRotor function checks the rotor for the dialysate outlet * pump. If homing, this function will stop when hall sensor detected. If pump * is off or running very slowly, rotor speed will be set to zero. - * @details - * Inputs : dopStopAtHomePosition, dopHomeStartTime, dopRotorRevStartTime - * Outputs : pump may be stopped if homing, dialOutPumpRotorSpeedRPM may be set to zero. + * @details Inputs: dopStopAtHomePosition, dopHomeStartTime, dopRotorRevStartTime + * @details Outputs: pump may be stopped if homing, dialOutPumpRotorSpeedRPM may be set to zero. * @return none *************************************************************************/ static void checkDialOutPumpRotor( void ) @@ -807,26 +807,48 @@ * @brief * The checkDialOutPumpDirection function checks the set direction vs. * the direction implied by the sign of the measured MC speed. - * @details - * Inputs : adcDialOutPumpMCSpeedRPM, dialOutPumpDirectionSet, dialOutPumpState - * Outputs : none + * @details Inputs: adcDialOutPumpMCSpeedRPM, dialOutPumpDirectionSet, dialOutPumpState + * @details Outputs: none * @return none *************************************************************************/ static void checkDialOutPumpDirection( void ) { - MOTOR_DIR_T dopMCDir; - if ( DIAL_OUT_PUMP_CONTROL_TO_TARGET_STATE == dialOutPumpState ) { - // check set direction vs. direction from hall sensors or sign of motor controller speed + MOTOR_DIR_T dopMCDir, dopDir; + dopMCDir = ( getMeasuredDialOutPumpMCSpeed() >= 0.0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); - if ( ( dialOutPumpDirectionSet != dopMCDir ) || ( dialOutPumpDirectionSet != dopMotorDirectionFromHallSensors ) ) + dopDir = ( getMeasuredDialOutPumpSpeed() >= 0.0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); + + // check set direction vs. direction from hall sensors + if ( dialOutPumpDirectionSet != dopDir ) { + if ( ++errorDialOutPumpDirectionPersistTimerCtr >= DOP_DIRECTION_ERROR_PERSIST ) + { #ifndef DISABLE_PUMP_DIRECTION_CHECKS - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DIAL_OUT_PUMP_MC_DIRECTION_CHECK, (U32)dialOutPumpDirectionSet, (U32)dopMotorDirectionFromHallSensors ) + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DIAL_OUT_PUMP_MC_DIRECTION_CHECK, (U32)dialOutPumpDirectionSet, (U32)dopDir ) #endif + } } + // check set direction vs. direction from sign of motor controller speed + else if ( dialOutPumpDirectionSet != dopMCDir ) + { + if ( ++errorDialOutPumpDirectionPersistTimerCtr >= DOP_DIRECTION_ERROR_PERSIST ) + { +#ifndef DISABLE_PUMP_DIRECTION_CHECKS + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DIAL_OUT_PUMP_MC_DIRECTION_CHECK, (U32)dialOutPumpDirectionSet, (U32)dopMCDir ) +#endif + } + } + else + { + errorDialOutPumpDirectionPersistTimerCtr = 0; + } } + else + { + errorDialOutPumpDirectionPersistTimerCtr = 0; + } } /*********************************************************************//** @@ -837,9 +859,8 @@ * 2. while pump is controlling, measured motor speed should be within allowed range of measured motor controller speed. * 3. measured motor speed should be within allowed range of measured rotor speed. * All 3 checks have a persistence time that must be met before an alarm is triggered. - * @details - * Inputs : targetDialOutFlowRate, dialOutPumpSpeedRPM, dialOutPumpRotorSpeedRPM - * Outputs : alarm(s) may be triggered + * @details Inputs: targetDialOutFlowRate, dialOutPumpSpeedRPM, dialOutPumpRotorSpeedRPM + * @details Outputs: alarm(s) may be triggered * @return none *************************************************************************/ static void checkDialOutPumpSpeeds( void ) @@ -855,6 +876,7 @@ { #ifndef DISABLE_PUMP_SPEED_CHECKS SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DIAL_OUT_PUMP_OFF_CHECK, measMotorSpeed ); + activateSafetyShutdown(); #endif } } @@ -905,7 +927,6 @@ { errorDialOutRotorSpeedPersistTimerCtr = 0; } - } else { @@ -918,9 +939,8 @@ * @brief * The checkDialOutPumpMCCurrent function checks the measured MC current vs. * the set state of the dialOut pump (stopped or running). - * @details - * Inputs : dialOutPumpState, dopCurrErrorDurationCtr, adcDialOutPumpMCCurrentmA - * Outputs : none + * @details Inputs: dialOutPumpState, dopCurrErrorDurationCtr, adcDialOutPumpMCCurrentmA + * @details Outputs: none * @return none *************************************************************************/ static void checkDialOutPumpMCCurrent( void ) @@ -972,13 +992,13 @@ * GET SUPPORT FUNCTIONS *************************************************************************/ + /*********************************************************************//** * @brief * The getPublishDialOutFlowDataInterval function gets the dialysate out flow * data publication interval. - * @details - * Inputs : dialOutDataPublishInterval - * Outputs : none + * @details Inputs: dialOutDataPublishInterval + * @details Outputs: none * @return the current dialysate out flow data publication interval (in ms). *************************************************************************/ static U32 getPublishDialOutDataInterval( void ) @@ -996,9 +1016,8 @@ /*********************************************************************//** * @brief * The getLoadCellWeightInGrams function gets the load cell weight. - * @details - * Inputs : loadCellWeightInGrams - * Outputs : none + * @details Inputs: loadCellWeightInGrams + * @details Outputs: none * @param loadCellID ID of load cell to get * @return the current load cell weight in grams *************************************************************************/ @@ -1028,9 +1047,8 @@ /*********************************************************************//** * @brief * The getTotalTargetDialOutUFVolumeInMl function gets the target UF volume. - * @details - * Inputs : referenceUFVolumeInMl - * Outputs : none + * @details Inputs: referenceUFVolumeInMl + * @details Outputs: none * @return the current target UF volume in mL. *************************************************************************/ F32 getTotalTargetDialOutUFVolumeInMl( void ) @@ -1048,9 +1066,8 @@ /*********************************************************************//** * @brief * The getTotalMeasuredUFVolumeInMl function gets the measured UF volume. - * @details - * Inputs : totalMeasuredUFVolumeInMl - * Outputs : none + * @details Inputs: totalMeasuredUFVolumeInMl + * @details Outputs: none * @return the current UF volume (in mL). *************************************************************************/ F32 getTotalMeasuredUFVolumeInMl( void ) @@ -1069,9 +1086,8 @@ * @brief * The getMeasuredDialOutPumpRotorSpeed function gets the measured dialysate * outlet pump rotor speed. - * @details - * Inputs : dialOutPumpRotorSpeedRPM - * Outputs : none + * @details Inputs: dialOutPumpRotorSpeedRPM + * @details Outputs: none * @return the current dialysate outlet pump rotor speed (in RPM). *************************************************************************/ F32 getMeasuredDialOutPumpRotorSpeed( void ) @@ -1090,9 +1106,8 @@ * @brief * The getMeasuredDialOutPumpSpeed function gets the measured dialysate outlet * pump motor speed. - * @details - * Inputs : dialOutPumpSpeedRPM - * Outputs : none + * @details Inputs: dialOutPumpSpeedRPM + * @details Outputs: none * @return the current dialysate outlet pump motor speed (in RPM). *************************************************************************/ F32 getMeasuredDialOutPumpSpeed( void ) @@ -1111,9 +1126,8 @@ * @brief * The getMeasuredDialOutPumpMCSpeed function gets the measured dialOut pump * speed. - * @details - * Inputs : dialOutPumpMCSpeedRPM - * Outputs : none + * @details Inputs: dialOutPumpMCSpeedRPM + * @details Outputs: none * @return the current dialOut pump speed (in RPM). *************************************************************************/ F32 getMeasuredDialOutPumpMCSpeed( void ) @@ -1132,9 +1146,8 @@ * @brief * The getMeasuredDialOutPumpMCCurrent function gets the measured dialOut pump * current. - * @details - * Inputs : dialOutPumpMCCurrentmA - * Outputs : none + * @details Inputs: dialOutPumpMCCurrentmA + * @details Outputs: none * @return the current dialOut pump current (in mA). *************************************************************************/ F32 getMeasuredDialOutPumpMCCurrent( void ) @@ -1159,9 +1172,8 @@ * @brief * The testSetDialOutPumpAndLoadCellDataPublishIntervalOverride function overrides the * dialout data publish interval. - * @details - * Inputs : none - * Outputs : dialOutDataPublishInterval + * @details Inputs: none + * @details Outputs: dialOutDataPublishInterval * @param value override dialout data publish interval with (in ms) * @return TRUE if override successful, FALSE if not *************************************************************************/ @@ -1185,9 +1197,8 @@ * @brief * The testResetDialOutPumpAndLoadCellDataPublishIntervalOverride function resets the override * of the dialout data publish interval. - * @details - * Inputs : none - * Outputs : dialOutDataPublishInterval + * @details Inputs: none + * @details Outputs: dialOutDataPublishInterval * @return TRUE if reset override successful, FALSE if not *************************************************************************/ BOOL testResetDialOutPumpAndLoadCellDataPublishIntervalOverride( void ) @@ -1208,9 +1219,8 @@ * @brief * The testSetTargetDialOutFlowRateOverride function overrides the target * dialysate outlet flow rate. - * @details - * Inputs : none - * Outputs : pump started w/ set target rate and control mode + * @details Inputs: none + * @details Outputs: pump started w/ set target rate and control mode * @param value override target dialysate outlet flow rate (in mL/min) * @param ctrlMode override pump control mode to this mode (0 = closed loop, 1 = open loop) * @return TRUE if override successful, FALSE if not @@ -1242,32 +1252,10 @@ /*********************************************************************//** * @brief - * The testResetTargetDialOutFlowRateOverride function resets the override of the - * target dialysate outlet flow rate. - * @details - * Inputs : none - * Outputs : pump stopped - * @return TRUE if override reset successful, FALSE if not - *************************************************************************/ -BOOL testResetTargetDialOutFlowRateOverride( void ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = setDialOutPumpTargetRate( 0, dialOutPumpDirection, dialOutPumpControlMode ); - } - - return result; -} - -/*********************************************************************//** - * @brief * The testSetDialOutUFRefVolumeOverride function overrides the target * dialout vol rate. - * @details - * Inputs : referenceUFVolumeInMl - * Outputs : referenceUFVolumeInMl + * @details Inputs: referenceUFVolumeInMl + * @details Outputs: referenceUFVolumeInMl * @param value override target dialout vol rate (in mL/min) * @return TRUE if override successful, FALSE if not *************************************************************************/ @@ -1289,9 +1277,8 @@ * @brief * The testResetDialOutUFRefVolumeOverride function resets the override of the * target dialout vol rate. - * @details - * Inputs : referenceUFVolumeInMl - * Outputs : referenceUFVolumeInMl + * @details Inputs: referenceUFVolumeInMl + * @details Outputs: referenceUFVolumeInMl * @return TRUE if reset override successful, FALSE if not *************************************************************************/ BOOL testResetDialOutUFRefVolumeOverride( void ) @@ -1312,9 +1299,8 @@ * @brief * The testSetDialOutUFTotVolumeOverride function overrides the measured * dialout vol rate. - * @details - * Inputs : totalMeasuredUFVolumeInMl - * Outputs : totalMeasuredUFVolumeInMl + * @details Inputs: totalMeasuredUFVolumeInMl + * @details Outputs: totalMeasuredUFVolumeInMl * @param value override measured dialout vol rate (in mL/min) * @return TRUE if override successful, FALSE if not *************************************************************************/ @@ -1336,9 +1322,8 @@ * @brief * The testResetDialOutUFTotVolumeOverride function resets the override of the * measured dialout vol rate. - * @details - * Inputs : totalMeasuredUFVolumeInMl - * Outputs : totalMeasuredUFVolumeInMl + * @details Inputs: totalMeasuredUFVolumeInMl + * @details Outputs: totalMeasuredUFVolumeInMl * @return TRUE if reset override successful, FALSE if not *************************************************************************/ BOOL testResetDialOutUFTotVolumeOverride( void ) @@ -1359,9 +1344,8 @@ * @brief * The testSetMeasuredDialOutPumpRotorSpeedOverride function overrides the measured * dialOut pump rotor speed. - * @details - * Inputs : DialOutPumpRotorSpeedRPM - * Outputs : DialOutPumpRotorSpeedRPM + * @details Inputs: DialOutPumpRotorSpeedRPM + * @details Outputs: DialOutPumpRotorSpeedRPM * @param value override measured dialOut pump rotor speed (in RPM) * @return TRUE if override successful, FALSE if not *************************************************************************/ @@ -1383,9 +1367,8 @@ * @brief * The testResetMeasuredDialOutPumpRotorSpeedOverride function resets the override of the * measured dialOut pump rotor speed. - * @details - * Inputs : DialOutPumpRotorSpeedRPM - * Outputs : DialOutPumpRotorSpeedRPM + * @details Inputs: DialOutPumpRotorSpeedRPM + * @details Outputs: DialOutPumpRotorSpeedRPM * @return TRUE if reset override successful, FALSE if not *************************************************************************/ BOOL testResetMeasuredDialOutPumpRotorSpeedOverride( void ) @@ -1406,9 +1389,8 @@ * @brief * The testSetMeasuredDialOutPumpSpeedOverride function overrides the measured * dialOut pump motor speed. - * @details - * Inputs : dialOutPumpSpeedRPM - * Outputs : dialOutPumpSpeedRPM + * @details Inputs: dialOutPumpSpeedRPM + * @details Outputs: dialOutPumpSpeedRPM * @param value override measured dialOut pump motor speed (in RPM) * @return TRUE if override successful, FALSE if not *************************************************************************/ @@ -1430,9 +1412,8 @@ * @brief * The testResetMeasuredDialOutPumpSpeedOverride function resets the override of the * measured dialOut pump motor speed. - * @details - * Inputs : dialOutPumpSpeedRPM - * Outputs : dialOutPumpSpeedRPM + * @details Inputs: dialOutPumpSpeedRPM + * @details Outputs: dialOutPumpSpeedRPM * @return TRUE if reset override successful, FALSE if not *************************************************************************/ BOOL testResetMeasuredDialOutPumpSpeedOverride( void ) @@ -1453,9 +1434,8 @@ * @brief * The testSetMeasuredDialOutPumpMCSpeedOverride function overrides the measured * dialOut pump motor speed. - * @details - * Inputs : dialOutPumpMCSpeedRPM - * Outputs : dialOutPumpMCSpeedRPM + * @details Inputs: dialOutPumpMCSpeedRPM + * @details Outputs: dialOutPumpMCSpeedRPM * @param value override measured dialOut pump speed (in RPM) * @return TRUE if override successful, FALSE if not *************************************************************************/ @@ -1477,9 +1457,8 @@ * @brief * The testResetMeasuredDialOutPumpMCSpeedOverride function resets the override of the * measured dialOut pump motor speed. - * @details - * Inputs : dialOutPumpMCSpeedRPM - * Outputs : dialOutPumpMCSpeedRPM + * @details Inputs: dialOutPumpMCSpeedRPM + * @details Outputs: dialOutPumpMCSpeedRPM * @return TRUE if reset override successful, FALSE if not *************************************************************************/ BOOL testResetMeasuredDialOutPumpMCSpeedOverride( void ) @@ -1500,9 +1479,8 @@ * @brief * The testSetMeasuredDialOutPumpMCCurrentOverride function overrides the measured * dialOut pump motor current. - * @details - * Inputs : dialOutPumpMCCurrentmA - * Outputs : dialOutPumpMCCurrentmA + * @details Inputs: dialOutPumpMCCurrentmA + * @details Outputs: dialOutPumpMCCurrentmA * @param value override measured dialOut pump current (in mA) * @return TRUE if override successful, FALSE if not *************************************************************************/ @@ -1524,9 +1502,8 @@ * @brief * The testResetMeasuredDialOutPumpMCCurrentOverride function resets the override of the * measured dialOut pump motor current. - * @details - * Inputs : dialOutPumpMCCurrentmA - * Outputs : dialOutPumpMCCurrentmA + * @details Inputs: dialOutPumpMCCurrentmA + * @details Outputs: dialOutPumpMCCurrentmA * @return TRUE if reset override successful, FALSE if not *************************************************************************/ BOOL testResetMeasuredDialOutPumpMCCurrentOverride( void ) @@ -1547,9 +1524,8 @@ * @brief * The testSetDialOutLoadCellWeightOverride function overrides the value of the * load cell sensor with a given weight (in grams). - * @details - * Inputs : loadCellWeightInGrams[] - * Outputs : loadCellWeightInGrams[] + * @details Inputs: loadCellWeightInGrams[] + * @details Outputs: loadCellWeightInGrams[] * @param sensor ID of load cell sensor to override weight for * @param value override weight (in grams) for the given sensor * @return TRUE if override successful, FALSE if not @@ -1575,9 +1551,8 @@ * @brief * The testResetDialOutLoadCellWeightOverride function resets the override of the * load cell sensor. - * @details - * Inputs : loadCellWeightInGrams[] - * Outputs : loadCellWeightInGrams[] + * @details Inputs: loadCellWeightInGrams[] + * @details Outputs: loadCellWeightInGrams[] * @param sensor ID of load cell sensor to override weight for * @return TRUE if reset successful, FALSE if not *************************************************************************/