Index: firmware/App/Controllers/DialInFlow.c =================================================================== diff -u -r6463655c18b173e335b6d475ac7289336f1bf092 -rd3596da054513ebf85d4114221eddbe875d1f1a1 --- firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision 6463655c18b173e335b6d475ac7289336f1bf092) +++ firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision d3596da054513ebf85d4114221eddbe875d1f1a1) @@ -32,105 +32,138 @@ #include "Timers.h" #include "DialInFlow.h" +/** + * @addtogroup DialysateInletFlow + * @{ + */ + // ********** private definitions ********** -#define DIAL_IN_FLOW_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) // interval (ms/task time) at which the dialIn flow data is published on the CAN bus +#define DIAL_IN_FLOW_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< interval (ms/task time) at which the dialIn flow data is published on the CAN bus -#define MAX_DIAL_IN_PUMP_PWM_STEP_CHANGE 0.01 // duty cycle TODO - fixed or parameterized or set in motor controller? -#define MAX_DIAL_IN_PUMP_PWM_DUTY_CYCLE 0.88 // controller will error if PWM duty cycle > 90%, so set max to 88% -#define MIN_DIAL_IN_PUMP_PWM_DUTY_CYCLE 0.12 // controller will error if PWM duty cycle < 10%, so set min to 12% +#define MAX_DIAL_IN_PUMP_PWM_STEP_UP_CHANGE 0.0133 ///< max duty cycle change when ramping up ~ 200 mL/min/s. +#define MAX_DIAL_IN_PUMP_PWM_STEP_DN_CHANGE 0.02 ///< max duty cycle change when ramping down ~ 300 mL/min/s. +#define MAX_DIAL_IN_PUMP_PWM_DUTY_CYCLE 0.88 ///< controller will error if PWM duty cycle > 90%, so set max to 88% +#define MIN_DIAL_IN_PUMP_PWM_DUTY_CYCLE 0.12 ///< controller will error if PWM duty cycle < 10%, so set min to 12% -#define DIP_CONTROL_INTERVAL ( 1000 / TASK_GENERAL_INTERVAL ) // interval (ms/task time) at which the dialIn pump is controlled -#define DIP_P_COEFFICIENT 0.00005 // P term for dialIn pump control -#define DIP_I_COEFFICIENT 0.00015 // I term for dialIn pump control +#define DIP_CONTROL_INTERVAL ( 10000 / TASK_GENERAL_INTERVAL ) ///< interval (ms/task time) at which the dialIn pump is controlled +#define DIP_P_COEFFICIENT 0.00005 ///< P term for dialIn pump control +#define DIP_I_COEFFICIENT 0.00015 ///< I term for dialIn pump control -#define DIP_MAX_CURR_WHEN_STOPPED_MA 150.0 // motor controller current should not exceed this when pump should be stopped -#define DIP_MIN_CURR_WHEN_RUNNING_MA 150.0 // motor controller current should always exceed this when pump should be running -#define DIP_MAX_CURR_WHEN_RUNNING_MA 1000.0 // motor controller current should not exceed this when pump should be running -#define DIP_MAX_CURR_ERROR_DURATION_MS 2000 // motor controller current errors persisting beyond this duration will trigger an alarm +#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. +#define DIP_HALL_EDGE_COUNTS_PER_REV 48 ///< number of hall sensor edge counts per motor revolution. -#define DIP_SPEED_ADC_TO_RPM_FACTOR 1.280938 // conversion factor from ADC counts to RPM for dialIn pump motor -#define DIP_CURRENT_ADC_TO_MA_FACTOR 3.002 // conversion factor from ADC counts to mA for dialIn pump motor +#define DIP_MAX_FLOW_VS_SPEED_DIFF_ML_MIN 50.0 ///< maximum difference between measured flow and flow implied by measured motor speed. +#define DIP_MAX_MOTOR_SPEED_WHILE_OFF_RPM 100.0 ///< maximum motor speed (RPM) while motor is commanded off. +#define DIP_MAX_ROTOR_VS_MOTOR_DIFF_RPM 5.0 ///< maximum difference in speed between motor and rotor (in rotor RPM). +#define DIP_MAX_MOTOR_SPEED_ERROR_RPM 300.0 ///< maximum difference in speed between measured and commanded RPM. +#define DIP_FLOW_VS_SPEED_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) for flow vs. motor speed error condition. +#define DIP_OFF_ERROR_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) for motor off error condition. +#define DIP_MOTOR_SPEED_ERROR_PERSIST ((5 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) motor speed error condition. +#define DIP_ROTOR_SPEED_ERROR_PERSIST ((12 * MS_PER_SECOND) / TASK_PRIORITY_INTERVAL) ///< persist time (task intervals) rotor speed error condition. -#define DIP_REV_PER_LITER 150.24 // rotor revolutions per liter -#define DIP_ML_PER_MIN_TO_PUMP_RPM_FACTOR ( DIP_REV_PER_LITER / ML_PER_LITER ) -#define DIP_GEAR_RATIO 32.0 // dialIn pump motor to dialIn pump gear ratio -#define DIP_MOTOR_RPM_TO_PWM_DC_FACTOR 0.00035 // ~28 BP motor RPM = 1% PWM duty cycle -#define DIP_PWM_ZERO_OFFSET 0.1 // 10% PWM duty cycle = zero speed -#define DIP_PWM_FROM_ML_PER_MIN(rate) ( (rate) * DIP_ML_PER_MIN_TO_PUMP_RPM_FACTOR * DIP_GEAR_RATIO * DIP_MOTOR_RPM_TO_PWM_DC_FACTOR + DIP_PWM_ZERO_OFFSET ) -#define DIAL_IN_PUMP_ADC_FULL_SCALE_V 3.0 // BP analog signals are 0-3V (while int. ADC ref V may be different) -#define DIAL_IN_PUMP_ADC_ZERO ( (F32)( INT_ADC_ZERO ) * ( DIAL_IN_PUMP_ADC_FULL_SCALE_V / INT_ADC_REF_V ) ) -#define SIGN_FROM_12_BIT_VALUE(v) ( (S16)(v) - (S16)DIAL_IN_PUMP_ADC_ZERO ) +#define DIP_MAX_CURR_WHEN_STOPPED_MA 150.0 ///< motor controller current should not exceed this when pump should be stopped +#define DIP_MIN_CURR_WHEN_RUNNING_MA 150.0 ///< motor controller current should always exceed this when pump should be running +#define DIP_MAX_CURR_WHEN_RUNNING_MA 1000.0 ///< motor controller current should not exceed this when pump should be running +#define DIP_MAX_CURR_ERROR_DURATION_MS 2000 ///< motor controller current errors persisting beyond this duration will trigger an alarm -#define DIAL_IN_FLOW_SAMPLE_FREQ ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) -#define SIZE_OF_ROLLING_AVG ( DIAL_IN_FLOW_SAMPLE_FREQ * 2 ) // measured dialIn flow is filtered w/ moving average -#define MAX_FLOW_FILTER_INTERVAL 5 // slowest sample interval for filter is every 5th sample +#define DIP_SPEED_ADC_TO_RPM_FACTOR 1.280938 ///< conversion factor from ADC counts to RPM for dialIn pump motor +#define DIP_CURRENT_ADC_TO_MA_FACTOR 3.002 ///< conversion factor from ADC counts to mA for dialIn pump motor +#define DIP_REV_PER_LITER 150.24 ///< rotor revolutions per liter +#define DIP_ML_PER_MIN_TO_PUMP_RPM_FACTOR ( DIP_REV_PER_LITER / ML_PER_LITER ) ///< +#define DIP_GEAR_RATIO 32.0 ///< dialIn pump motor to dialIn pump gear ratio +#define DIP_MOTOR_RPM_TO_PWM_DC_FACTOR 0.00035 ///< ~28 BP motor RPM = 1% PWM duty cycle +#define DIP_PWM_ZERO_OFFSET 0.1 ///< 10% PWM duty cycle = zero speed +#define DIP_PWM_FROM_ML_PER_MIN(rate) ( (rate) * DIP_ML_PER_MIN_TO_PUMP_RPM_FACTOR * DIP_GEAR_RATIO * DIP_MOTOR_RPM_TO_PWM_DC_FACTOR + DIP_PWM_ZERO_OFFSET ) ///< + +#define DIAL_IN_PUMP_ADC_FULL_SCALE_V 3.0 ///< BP analog signals are 0-3V (while int. ADC ref V may be different) +#define DIAL_IN_PUMP_ADC_ZERO 1998 ///< Mid-point (zero) for ADC readings. +#define SIGN_FROM_12_BIT_VALUE(v) ( (S16)(v) - (S16)DIAL_IN_PUMP_ADC_ZERO ) ///< Macro converts a 12-bit ADC reading to a signed 16-bit value. + +#define SIZE_OF_ROLLING_AVG ( ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) * 10 ) ///< measured dialIn flow is filtered w/ moving average + +/// Enumeration of dialysate inlet pump states. typedef enum DialInPump_States { - DIAL_IN_PUMP_OFF_STATE = 0, - DIAL_IN_PUMP_RAMPING_UP_STATE, - DIAL_IN_PUMP_RAMPING_DOWN_STATE, - DIAL_IN_PUMP_CONTROL_TO_TARGET_STATE, - NUM_OF_DIAL_IN_PUMP_STATES + DIAL_IN_PUMP_OFF_STATE = 0, ///< Off state for the dialysate inlet pump. + DIAL_IN_PUMP_RAMPING_UP_STATE, ///< Ramping up state for the dialysate inlet pump. + DIAL_IN_PUMP_RAMPING_DOWN_STATE, ///< Ramping down state for the dialysate inlet pump. + DIAL_IN_PUMP_CONTROL_TO_TARGET_STATE, ///< Control to target state for the dialysate inlet pump. + NUM_OF_DIAL_IN_PUMP_STATES ///< Number of dialysate inlet pump states. } DIAL_IN_PUMP_STATE_T; +/// Enumeration of dialysate inlet self test states. typedef enum DialInFlow_Self_Test_States { - DIAL_IN_FLOW_SELF_TEST_STATE_START = 0, - DIAL_IN_FLOW_TEST_STATE_IN_PROGRESS, - DIAL_IN_FLOW_TEST_STATE_COMPLETE, - NUM_OF_DIAL_IN_FLOW_SELF_TEST_STATES + DIAL_IN_FLOW_SELF_TEST_STATE_START = 0, ///< Start state for the dialysate inlet pump self test. + DIAL_IN_FLOW_TEST_STATE_IN_PROGRESS, ///< Test in progress state for the dialysate inlet pump self test. + DIAL_IN_FLOW_TEST_STATE_COMPLETE, ///< Test completed state for the dialysate inlet pump self test. + NUM_OF_DIAL_IN_FLOW_SELF_TEST_STATES ///< Number of dialysate inlet pump self test states. } DIAL_IN_FLOW_SELF_TEST_STATE_T; // pin assignments for pump stop and direction outputs -#define STOP_DI_PUMP_GIO_PORT_PIN 2U -#define DIR_DI_PUMP_SPI5_PORT_MASK 0x00000100 // (ENA - re-purposed as output GPIO) +#define STOP_DI_PUMP_GIO_PORT_PIN 2U ///< Pin # on GIO A for stopping the dialysate inlet pump. +#define DIR_DI_PUMP_SPI5_PORT_MASK 0x00000100 ///< Pin on unused SPI5 peripheral (ENA) - re-purposed as output GPIO to set dialysate inlet pump direction. // dialIn pump stop and direction macros -#define SET_DIP_DIR() {mibspiREG5->PC3 |= DIR_DI_PUMP_SPI5_PORT_MASK;} -#define CLR_DIP_DIR() {mibspiREG5->PC3 &= ~DIR_DI_PUMP_SPI5_PORT_MASK;} +#define SET_DIP_DIR() {mibspiREG5->PC3 |= DIR_DI_PUMP_SPI5_PORT_MASK;} ///< Macro for setting the dialysate inlet pump direction pin high. +#define CLR_DIP_DIR() {mibspiREG5->PC3 &= ~DIR_DI_PUMP_SPI5_PORT_MASK;} ///< Macro for setting the dialysate inlet pump direction pin low. #ifndef BREADBOARD_TARGET - #define SET_DIP_STOP() gioSetBit( gioPORTA, STOP_DI_PUMP_GIO_PORT_PIN, PIN_SIGNAL_LOW ) - #define CLR_DIP_STOP() gioSetBit( gioPORTA, STOP_DI_PUMP_GIO_PORT_PIN, PIN_SIGNAL_HIGH ) + #define SET_DIP_STOP() gioSetBit( gioPORTA, STOP_DI_PUMP_GIO_PORT_PIN, PIN_SIGNAL_LOW ) ///< Macro for setting the dialysate inlet pump stop pin low. + #define CLR_DIP_STOP() gioSetBit( gioPORTA, STOP_DI_PUMP_GIO_PORT_PIN, PIN_SIGNAL_HIGH ) ///< Macro for setting the dialysate inlet pump stop pin high. #else #define SET_DIP_STOP() gioSetBit( gioPORTA, STOP_DI_PUMP_GIO_PORT_PIN, PIN_SIGNAL_HIGH ) #define CLR_DIP_STOP() gioSetBit( gioPORTA, STOP_DI_PUMP_GIO_PORT_PIN, PIN_SIGNAL_LOW ) #endif // ********** private data ********** -static DIAL_IN_PUMP_STATE_T dialInPumpState = DIAL_IN_PUMP_OFF_STATE; // current state of dialIn flow controller state machine -static U32 dialInFlowDataPublicationTimerCounter = 5; // used to schedule dialIn flow data publication to CAN bus -static BOOL isDialInPumpOn = FALSE; // dialIn pump is currently running -static F32 dialInPumpPWMDutyCyclePct = 0.0; // initial dialIn pump PWM duty cycle -static F32 dialInPumpPWMDutyCyclePctSet = 0.0; // currently set dialIn pump PWM duty cycle -static MOTOR_DIR_T dialInPumpDirection = MOTOR_DIR_FORWARD; // requested dialIn flow direction -static MOTOR_DIR_T dialInPumpDirectionSet = MOTOR_DIR_FORWARD; // currently set dialIn flow direction +static DIAL_IN_PUMP_STATE_T dialInPumpState = DIAL_IN_PUMP_OFF_STATE; ///< current state of dialIn flow controller state machine +static U32 dialInFlowDataPublicationTimerCounter = 5; ///< used to schedule dialIn flow data publication to CAN bus +static BOOL isDialInPumpOn = FALSE; ///< dialIn pump is currently running +static F32 dialInPumpPWMDutyCyclePct = 0.0; ///< initial dialIn pump PWM duty cycle +static F32 dialInPumpPWMDutyCyclePctSet = 0.0; ///< currently set dialIn pump PWM duty cycle +static MOTOR_DIR_T dialInPumpDirection = MOTOR_DIR_FORWARD; ///< requested dialIn flow direction +static MOTOR_DIR_T dialInPumpDirectionSet = MOTOR_DIR_FORWARD; ///< currently set dialIn flow direction static PUMP_CONTROL_MODE_T dialInPumpControlMode = PUMP_CONTROL_MODE_CLOSED_LOOP; ///< requested dialIn pump control mode. static PUMP_CONTROL_MODE_T dialInPumpControlModeSet = PUMP_CONTROL_MODE_CLOSED_LOOP;///< currently set dialIn pump control mode. -DATA_DECL( U32, DialInFlowDataPub, dialInFlowDataPublishInterval, DIAL_IN_FLOW_DATA_PUB_INTERVAL, DIAL_IN_FLOW_DATA_PUB_INTERVAL ); // interval (in ms) at which to publish dialIn flow data to CAN bus -DATA_DECL( S32, TargetDialInFlowRate, targetDialInFlowRate, 0, 0 ); // requested dialIn flow rate -DATA_DECL( F32, MeasuredDialInFlowRate, measuredDialInFlowRate, 0.0, 0.0 ); // measured dialIn flow rate -DATA_DECL( F32, MeasuredDialInPumpRotorSpeed, dialInPumpRotorSpeedRPM, 0.0, 0.0 );// measured dialIn pump rotor speed -DATA_DECL( F32, MeasuredDialInPumpSpeed, dialInPumpSpeedRPM, 0.0, 0.0 ); // measured dialIn pump motor speed -DATA_DECL( F32, MeasuredDialInPumpMCSpeed, adcDialInPumpMCSpeedRPM, 0.0, 0.0 ); // measured dialIn pump motor controller speed -DATA_DECL( F32, MeasuredDialInPumpMCCurrent, adcDialInPumpMCCurrentmA, 0.0, 0.0 );// measured dialIn pump motor controller current +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 +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 +static OVERRIDE_F32_T adcDialInPumpMCSpeedRPM = { 0.0, 0.0, 0.0, 0 }; ///< measured dialysate inlet pump motor controller speed +static OVERRIDE_F32_T adcDialInPumpMCCurrentmA = { 0.0, 0.0, 0.0, 0 }; ///< measured dialysate inlet pump motor controller current -static U32 dipControlTimerCounter = 0; // determines when to perform control on dialIn flow +static U32 dipControlTimerCounter = 0; ///< determines when to perform control on dialIn flow -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 -static F32 flowReadingsTotal = 0.0; // rolling total - used to calc average -static U32 flowReadingsCount = 0; // # of samples in flow rolling average buffer -static U32 flowReadingsTmrCtr = 0; // determines when to add samples to filter +static U32 dipRotorRevStartTime = 0; ///< dialysate inlet pump rotor rotation start time (in ms) +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 U32 dipCurrErrorDurationCtr = 0; // used for tracking persistence of dip current errors +static U16 dipLastMotorHallSensorCount = 0; ///< last hall sensor count for the dialysate inlet pump motor +static MOTOR_DIR_T dipMotorDirectionFromHallSensors = MOTOR_DIR_FORWARD; ///< pump direction according to hall sensor count +static U32 dipMotorSpeedCalcTimerCtr = 0; ///< counter determines interval for calculating dialysate inlet pump motor speed from hall sensor count. -static DIAL_IN_FLOW_SELF_TEST_STATE_T dialInPumpSelfTestState = DIAL_IN_FLOW_SELF_TEST_STATE_START; // current dialIn pump self test state -static U32 dialInPumpSelfTestTimerCount = 0; // timer counter for dialIn pump self test +static U32 errorDialInFlowVsMotorSpeedPersistTimerCtr = 0; ///< persistence timer counter for flow vs. motor speed error condition. +static U32 errorDialInMotorOffPersistTimerCtr = 0; ///< persistence timer counter for motor off check error condition. +static U32 errorDialInMotorSpeedPersistTimerCtr = 0; ///< persistence timer counter for motor speed error condition. +static U32 errorDialInRotorSpeedPersistTimerCtr = 0; ///< persistence timer counter for rotor speed 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 +static F32 flowReadingsTotal = 0.0; ///< rolling total - used to calc average +static U32 flowReadingsCount = 0; ///< number of samples in flow rolling average buffer + +static U32 dipCurrErrorDurationCtr = 0; ///< used for tracking persistence of dip current errors + +static DIAL_IN_FLOW_SELF_TEST_STATE_T dialInPumpSelfTestState = DIAL_IN_FLOW_SELF_TEST_STATE_START; ///< current dialIn pump self test state +static U32 dialInPumpSelfTestTimerCount = 0; ///< timer counter for dialIn pump self test + // ********** private function prototypes ********** static DIAL_IN_PUMP_STATE_T handleDialInPumpOffState( void ); @@ -144,21 +177,26 @@ static void publishDialInFlowData( void ); static void resetDialInFlowMovingAverage( void ); static void filterDialInFlowReadings( F32 flow ); +static void updateDialInPumpSpeedAndDirectionFromHallSensors( void ); +static void checkDialInPumpRotor( void ); static void checkDialInPumpDirection( void ); +static void checkDialInPumpSpeeds( void ); +static void checkDialInPumpFlowAgainstSpeed( void ); static void checkDialInPumpMCCurrent( void ); static DATA_GET_PROTOTYPE( U32, getPublishDialInFlowDataInterval ); -/************************************************************************* - * @brief initDialInFlow +/*********************************************************************//** + * @brief * The initDialInFlow function initializes the DialInFlow module. * @details * Inputs : none * Outputs : DialInFlow module initialized. - * @param none * @return none *************************************************************************/ void initDialInFlow( void ) { + dipLastMotorHallSensorCount = getFPGADialInPumpHallSensorCount(); + stopDialInPump(); setDialInPumpDirection( MOTOR_DIR_FORWARD ); @@ -171,8 +209,8 @@ MIN_DIAL_IN_PUMP_PWM_DUTY_CYCLE, MAX_DIAL_IN_PUMP_PWM_DUTY_CYCLE ); } -/************************************************************************* - * @brief setDialInPumpTargetFlowRate +/*********************************************************************//** + * @brief * The setDialInPumpTargetFlowRate function sets a new target flow rate and * pump direction. * @details @@ -239,13 +277,12 @@ return result; } -/************************************************************************* - * @brief signalDialInPumpHardStop +/*********************************************************************//** + * @brief * The signalDialInPumpHardStop function stops the dialIn pump immediately. * @details * Inputs : none * Outputs : DialIn pump stopped, set point reset, state changed to off - * @param none * @return none *************************************************************************/ void signalDialInPumpHardStop( void ) @@ -258,13 +295,61 @@ resetPIController( PI_CONTROLLER_ID_DIALYSATE_FLOW, MIN_DIAL_IN_PUMP_PWM_DUTY_CYCLE ); } -/************************************************************************* - * @brief execDialInFlowMonitor +/*********************************************************************//** + * @brief + * The signalDialInPumpRotorHallSensor function handles the dialysate inlet pump rotor \n + * hall sensor detection. Calculates rotor speed (in RPM). Stops pump if \n + * there is a pending request to home the pump. + * @details + * Inputs : dipRotorRevStartTime, dipStopAtHomePosition + * Outputs : dipRotorRevStartTime, dialInPumpRotorSpeedRPM + * @return none + *************************************************************************/ +void signalDialInPumpRotorHallSensor( void ) +{ + U32 rotTime = getMSTimerCount(); + U32 deltaTime = calcTimeBetween( dipRotorRevStartTime, rotTime ); + + // calculate rotor speed (in RPM) + dialInPumpRotorSpeedRPM.data = ( 1.0 / (F32)deltaTime ) * (F32)MS_PER_SECOND * (F32)SEC_PER_MIN; + dipRotorRevStartTime = rotTime; + + // if we're supposed to stop pump at home position, stop pump now. + if ( TRUE == dipStopAtHomePosition ) + { + signalDialInPumpHardStop(); + dipStopAtHomePosition = FALSE; + } +} + +/*********************************************************************//** + * @brief + * The homeDialInPump function initiates a dialysate inlet pump home operation. + * @details + * Inputs : dialInPumpState + * Outputs : dipStopAtHomePosition, dipHomeStartTime, dialysate inlet pump started (slow) + * @return none + *************************************************************************/ +BOOL homeDialInPump( void ) +{ + BOOL result = FALSE; + + if ( DIAL_IN_PUMP_OFF_STATE == dialInPumpState ) + { + dipStopAtHomePosition = TRUE; + dipHomeStartTime = getMSTimerCount(); + result = setDialInPumpTargetFlowRate( DIP_HOME_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + } + + return result; +} + +/*********************************************************************//** + * @brief * The execDialInFlowMonitor function executes the dialIn flow monitor. * @details * Inputs : none * Outputs : measuredDialInFlowRate, adcDialInPumpMCSpeedRPM, adcDialInPumpMCCurrentmA - * @param none * @return none *************************************************************************/ void execDialInFlowMonitor( void ) @@ -278,24 +363,33 @@ filterDialInFlowReadings( dipFlow ); + // calculate dialysate inlet pump motor speed/direction from hall sensor count + updateDialInPumpSpeedAndDirectionFromHallSensors(); + // don't start enforcing checks until out of init/POST mode if ( getCurrentOperationMode() != MODE_INIT ) { + // check pump direction checkDialInPumpDirection(); + // check pump controller current checkDialInPumpMCCurrent(); + // check pump speeds and flow + checkDialInPumpSpeeds(); + checkDialInPumpFlowAgainstSpeed(); + // check for home position, zero/low speed + checkDialInPumpRotor(); } // publish dialIn flow data on interval publishDialInFlowData(); } -/************************************************************************* - * @brief execDialInFlowController +/*********************************************************************//** + * @brief * The execDialInFlowController function executes the dialIn flow controller. * @details * Inputs : dialInPumpState * Outputs : dialInPumpState - * @param none * @return none *************************************************************************/ void execDialInFlowController( void ) @@ -324,14 +418,13 @@ } } -/************************************************************************* - * @brief handleDialInPumpOffState +/*********************************************************************//** + * @brief * The handleDialInPumpOffState function handles the dialIn pump off state \n * of the dialIn pump controller state machine. * @details * Inputs : targetDialInFlowRate, dialInPumpDirection * Outputs : dialInPumpPWMDutyCyclePctSet, dialInPumpDirectionSet, isDialInPumpOn - * @param none * @return next state *************************************************************************/ static DIAL_IN_PUMP_STATE_T handleDialInPumpOffState( void ) @@ -342,7 +435,7 @@ if ( getTargetDialInFlowRate() != 0 ) { // set initial PWM duty cycle - dialInPumpPWMDutyCyclePctSet = DIP_PWM_ZERO_OFFSET + MAX_DIAL_IN_PUMP_PWM_STEP_CHANGE; + dialInPumpPWMDutyCyclePctSet = DIP_PWM_ZERO_OFFSET + MAX_DIAL_IN_PUMP_PWM_STEP_UP_CHANGE; setDialInPumpControlSignalPWM( dialInPumpPWMDutyCyclePctSet ); // allow dialIn pump to run in requested direction setDialInPumpDirection( dialInPumpDirection ); @@ -354,14 +447,13 @@ return result; } -/************************************************************************* - * @brief handleDialInPumpRampingUpState +/*********************************************************************//** + * @brief * The handleDialInPumpRampingUpState function handles the ramp up state \n * of the dialIn pump controller state machine. * @details * Inputs : dialInPumpPWMDutyCyclePctSet * Outputs : dialInPumpPWMDutyCyclePctSet - * @param none * @return next state *************************************************************************/ static DIAL_IN_PUMP_STATE_T handleDialInPumpRampingUpState( void ) @@ -372,7 +464,7 @@ if ( 0 == getTargetDialInFlowRate() ) { // start ramp down to stop - dialInPumpPWMDutyCyclePctSet -= MAX_DIAL_IN_PUMP_PWM_STEP_CHANGE; + dialInPumpPWMDutyCyclePctSet -= MAX_DIAL_IN_PUMP_PWM_STEP_DN_CHANGE; setDialInPumpControlSignalPWM( dialInPumpPWMDutyCyclePctSet ); result = DIAL_IN_PUMP_RAMPING_DOWN_STATE; } @@ -393,29 +485,28 @@ // continue ramp up else { - dialInPumpPWMDutyCyclePctSet += MAX_DIAL_IN_PUMP_PWM_STEP_CHANGE; + dialInPumpPWMDutyCyclePctSet += MAX_DIAL_IN_PUMP_PWM_STEP_UP_CHANGE; setDialInPumpControlSignalPWM( dialInPumpPWMDutyCyclePctSet ); } return result; } -/************************************************************************* - * @brief handleDialInPumpRampingDownState +/*********************************************************************//** + * @brief * The handleDialInPumpRampingDownState function handles the ramp down state \n * of the dialIn pump controller state machine. * @details * Inputs : dialInPumpPWMDutyCyclePctSet * Outputs : dialInPumpPWMDutyCyclePctSet - * @param none * @return next state *************************************************************************/ static DIAL_IN_PUMP_STATE_T handleDialInPumpRampingDownState( void ) { DIAL_IN_PUMP_STATE_T result = DIAL_IN_PUMP_RAMPING_DOWN_STATE; // have we essentially reached zero speed - if ( dialInPumpPWMDutyCyclePctSet < (MAX_DIAL_IN_PUMP_PWM_STEP_CHANGE + DIP_PWM_ZERO_OFFSET) ) + if ( dialInPumpPWMDutyCyclePctSet < (MAX_DIAL_IN_PUMP_PWM_STEP_UP_CHANGE + DIP_PWM_ZERO_OFFSET) ) { stopDialInPump(); result = DIAL_IN_PUMP_OFF_STATE; @@ -437,21 +528,20 @@ // continue ramp down else { - dialInPumpPWMDutyCyclePctSet -= MAX_DIAL_IN_PUMP_PWM_STEP_CHANGE; + dialInPumpPWMDutyCyclePctSet -= MAX_DIAL_IN_PUMP_PWM_STEP_DN_CHANGE; setDialInPumpControlSignalPWM( dialInPumpPWMDutyCyclePctSet ); } return result; } -/************************************************************************* - * @brief handleDialInPumpControlToTargetState +/*********************************************************************//** + * @brief * The handleDialInPumpControlToTargetState function handles the "control to \n * target" state of the dialIn pump controller state machine. * @details * Inputs : none * Outputs : dialInPumpState - * @param none * @return next state *************************************************************************/ static DIAL_IN_PUMP_STATE_T handleDialInPumpControlToTargetState( void ) @@ -477,8 +567,8 @@ return result; } -/************************************************************************* - * @brief setDialInPumpControlSignalPWM +/*********************************************************************//** + * @brief * The setDialInPumpControlSignalPWM function sets the PWM duty cycle for \n * the dialysate inlet pump to a given %. * @details @@ -492,13 +582,12 @@ etpwmSetCmpA( etpwmREG2, (U32)( (S32)( ( newPWM * (F32)(etpwmREG2->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ) ); } -/************************************************************************* - * @brief stopDialInPump +/*********************************************************************//** + * @brief * The stopDialInPump function sets the dialIn pump stop signal. * @details * Inputs : none * Outputs : dialIn pump stop signal activated, PWM duty cycle zeroed - * @param none * @return none *************************************************************************/ static void stopDialInPump( void ) @@ -509,22 +598,21 @@ SET_DIP_STOP(); } -/************************************************************************* - * @brief releaseDialInPumpStop +/*********************************************************************//** + * @brief * The releaseDialInPumpStop function clears the dialIn pump stop signal. * @details * Inputs : none * Outputs : dialIn pump stop signal - * @param none * @return none *************************************************************************/ static void releaseDialInPumpStop( void ) { CLR_DIP_STOP(); } -/************************************************************************* - * @brief setDialInPumpDirection +/*********************************************************************//** + * @brief * The setDialInPumpDirection function sets the set dialIn pump direction to \n * the given direction. * @details @@ -553,99 +641,91 @@ } } -/************************************************************************* - * @brief getPublishDialInFlowDataInterval +/*********************************************************************//** + * @brief * The getPublishDialInFlowDataInterval function gets the dialIn flow data \n * publication interval. * @details * Inputs : dialInFlowDataPublishInterval * Outputs : none - * @param none * @return the current dialIn flow data publication interval (in ms). *************************************************************************/ DATA_GET( U32, getPublishDialInFlowDataInterval, dialInFlowDataPublishInterval ) -/************************************************************************* - * @brief getTargetDialInFlowRate +/*********************************************************************//** + * @brief * The getTargetDialInFlowRate function gets the current target dialIn flow \n * rate. * @details * Inputs : targetDialInFlowRate * Outputs : none - * @param none * @return the current target dialIn flow rate (in mL/min). *************************************************************************/ DATA_GET( S32, getTargetDialInFlowRate, targetDialInFlowRate ) -/************************************************************************* - * @brief getMeasuredDialInFlowRate +/*********************************************************************//** + * @brief * The getMeasuredDialInFlowRate function gets the measured dialIn flow \n * rate. * @details * Inputs : measuredDialInFlowRate * Outputs : none - * @param none - * @return the current dialIn flow rate (in mL/min). +/ * @return the current dialIn flow rate (in mL/min). *************************************************************************/ DATA_GET( F32, getMeasuredDialInFlowRate, measuredDialInFlowRate ) -/************************************************************************* - * @brief getMeasuredDialInPumpRotorSpeed +/*********************************************************************//** + * @brief * The getMeasuredDialInPumpRotorSpeed function gets the measured dialIn flow \n * rate. * @details * Inputs : dialInPumpRotorSpeedRPM * Outputs : none - * @param none * @return the current dialIn flow rate (in mL/min). *************************************************************************/ DATA_GET( F32, getMeasuredDialInPumpRotorSpeed, dialInPumpRotorSpeedRPM ) -/************************************************************************* - * @brief getMeasuredDialInPumpSpeed +/*********************************************************************//** + * @brief * The getMeasuredDialInPumpSpeed function gets the measured dialIn flow \n * rate. * @details * Inputs : dialInPumpSpeedRPM * Outputs : none - * @param none * @return the current dialIn flow rate (in mL/min). *************************************************************************/ DATA_GET( F32, getMeasuredDialInPumpSpeed, dialInPumpSpeedRPM ) -/************************************************************************* - * @brief getMeasuredDialInPumpMCSpeed +/*********************************************************************//** + * @brief * The getMeasuredDialInPumpMCSpeed function gets the measured dialIn pump \n * speed. * @details * Inputs : adcDialInPumpMCSpeedRPM * Outputs : none - * @param none * @return the current dialIn pump speed (in RPM). *************************************************************************/ DATA_GET( F32, getMeasuredDialInPumpMCSpeed, adcDialInPumpMCSpeedRPM ) -/************************************************************************* - * @brief getMeasuredDialInPumpMCCurrent +/*********************************************************************//** + * @brief * The getMeasuredDialInPumpMCCurrent function gets the measured dialIn pump \n * current. * @details * Inputs : adcDialInPumpMCCurrentmA * Outputs : none - * @param none - * @return the current dialIn pump current (in mA). +/ * @return the current dialIn pump current (in mA). *************************************************************************/ DATA_GET( F32, getMeasuredDialInPumpMCCurrent, adcDialInPumpMCCurrentmA ) -/************************************************************************* - * @brief publishDialInFlowData +/*********************************************************************//** + * @brief * The publishDialInFlowData function publishes dialIn flow data at the set \n * interval. * @details * Inputs : target flow rate, measured flow rate, measured MC speed, \n * measured MC current * Outputs : DialIn flow data is published to CAN bus. - * @param none * @return none *************************************************************************/ static void publishDialInFlowData( void ) @@ -654,128 +734,132 @@ if ( ++dialInFlowDataPublicationTimerCounter >= getPublishDialInFlowDataInterval() ) { S32 flowStPt = (S32)getTargetDialInFlowRate(); -#ifndef SHOW_RAW_FLOW_VALUES F32 measFlow = getMeasuredDialInFlowRate(); -#else - F32 measFlow = getFPGADialysateFlow(); -#endif F32 measRotSpd = getMeasuredDialInPumpRotorSpeed(); F32 measSpd = getMeasuredDialInPumpSpeed(); F32 measMCSpd = getMeasuredDialInPumpMCSpeed(); F32 measMCCurr = getMeasuredDialInPumpMCCurrent(); F32 pumpPWMPctDutyCycle = dialInPumpPWMDutyCyclePctSet * FRACTION_TO_PERCENT_FACTOR; -#ifdef DEBUG_ENABLED -// // TODO - temporary debug code - remove later -// char debugFlowStr[ 256 ]; -// -// sprintf( debugFlowStr, "Dial. Set Pt:%5d, Meas. Flow:%5d, Speed:%5d RPM, Current:%5d mA, PWM:%5d \n", flowStPt, (S32)measFlow, (S32)measMCSpd, (S32)measMCCurr, (S32)pumpPWMPctDutyCycle ); -// sendDebugData( (U08*)debugFlowStr, strlen(debugFlowStr) ); -#endif broadcastDialInFlowData( flowStPt, measFlow, measRotSpd, measSpd, measMCSpd, measMCCurr, pumpPWMPctDutyCycle ); dialInFlowDataPublicationTimerCounter = 0; } } -/************************************************************************* - * @brief resetDialInFlowMovingAverage +/*********************************************************************//** + * @brief * The resetDialInFlowMovingAverage function resets the properties of the \n * dialIn flow moving average sample buffer. * @details * Inputs : none * Outputs : flowReadingsTotal, flowReadingsIdx, flowReadingsCount all set to zero. - * @param none - * @return none *************************************************************************/ static void resetDialInFlowMovingAverage( void ) { - flowReadingsTotal = 0.0; flowReadingsIdx = 0; flowReadingsCount = 0; - flowReadingsTmrCtr = 0; + flowReadingsTotal = 0.0; dipControlTimerCounter = 0; } -/************************************************************************* - * @brief filterDialInFlowReadings +/*********************************************************************//** + * @brief * The filterDialInFlowReadings function adds a new flow sample to the filter \n * if decimation rate for current set point calls for it. * @details * Inputs : none * Outputs : flowReadings[], flowReadingsIdx, flowReadingsCount - * @param flow : newest dialIn flow sample * @return none *************************************************************************/ static void filterDialInFlowReadings( F32 flow ) { - BOOL addSampleToFilter = FALSE; - - if ( ( targetDialInFlowRate.data < MIN_DIAL_IN_FLOW_RATE ) || ( targetDialInFlowRate.data >= MAX_DIAL_IN_FLOW_RATE ) ) +#ifndef RAW_FLOW_SENSOR_DATA + if ( flowReadingsCount >= SIZE_OF_ROLLING_AVG ) { - addSampleToFilter = TRUE; + flowReadingsTotal -= flowReadings[ flowReadingsIdx ]; } - else + flowReadings[ flowReadingsIdx ] = flow; + flowReadingsTotal += flow; + flowReadingsIdx = INC_WRAP( flowReadingsIdx, 0, SIZE_OF_ROLLING_AVG - 1 ); + flowReadingsCount = INC_CAP( flowReadingsCount, SIZE_OF_ROLLING_AVG ); + measuredDialInFlowRate.data = flowReadingsTotal / (F32)flowReadingsCount; +#else + measuredDialInFlowRate.data = flow; +#endif +} + +/*********************************************************************//** + * @brief + * The updateDialInPumpSpeedAndDirectionFromHallSensors function calculates \n + * the dialysate inlet pump motor speed and direction from hall sensor counter on \n + * a 1 second interval. + * @details + * Inputs : dipLastMotorHallSensorCount, dipMotorSpeedCalcTimerCtr, current count from FPGA + * Outputs : dipMotorDirectionFromHallSensors, dialInPumpSpeedRPM + * @return none + *************************************************************************/ +static void updateDialInPumpSpeedAndDirectionFromHallSensors( void ) +{ + if ( ++dipMotorSpeedCalcTimerCtr >= DIP_SPEED_CALC_INTERVAL ) { - switch ( flowReadingsTmrCtr ) - { - case 0: - addSampleToFilter = TRUE; - break; + U16 dipMotorHallSensorCount = getFPGADialInPumpHallSensorCount(); + U16 incDelta = ( dipMotorHallSensorCount >= dipLastMotorHallSensorCount ? dipMotorHallSensorCount - dipLastMotorHallSensorCount : ( HEX_64_K - dipLastMotorHallSensorCount ) + dipMotorHallSensorCount ); + U16 decDelta = HEX_64_K - incDelta; + U16 delta; - case 1: - addSampleToFilter = FALSE; - break; - - case 2: - if ( targetDialInFlowRate.data >= 400 ) - { - addSampleToFilter = TRUE; - } - break; - - case 3: - if ( targetDialInFlowRate.data >= 200 ) - { - addSampleToFilter = TRUE; - } - break; - - case 4: - if ( targetDialInFlowRate.data >= 300 ) - { - addSampleToFilter = TRUE; - } - break; - - default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_DIAL_IN_FLOW_INVALID_FILTER_STATE, flowReadingsTmrCtr ) - break; + // determine dialysate inlet pump speed/direction from delta hall sensor count since last interval + if ( incDelta < decDelta ) + { + dipMotorDirectionFromHallSensors = MOTOR_DIR_FORWARD; + delta = incDelta; + dialInPumpSpeedRPM.data = ( (F32)delta / (F32)DIP_HALL_EDGE_COUNTS_PER_REV ) * (F32)SEC_PER_MIN; } + else + { + dipMotorDirectionFromHallSensors = MOTOR_DIR_REVERSE; + delta = decDelta; + dialInPumpSpeedRPM.data = ( (F32)delta / (F32)DIP_HALL_EDGE_COUNTS_PER_REV ) * (F32)SEC_PER_MIN * -1.0; + } + + // update last count for next time + dipLastMotorHallSensorCount = dipMotorHallSensorCount; + dipMotorSpeedCalcTimerCtr = 0; } +} - if ( TRUE == addSampleToFilter ) +/*********************************************************************//** + * @brief + * The checkDialInPumpRotor function checks the rotor for the dialysate inlet \n + * pump. If homing, this function will stop when hall sensor detected. If pump \n + * is off or running very slowly, rotor speed will be set to zero. + * @details + * Inputs : dipStopAtHomePosition, dipHomeStartTime, dipRotorRevStartTime + * Outputs : pump may be stopped if homing, dialInPumpRotorSpeedRPM may be set to zero. + * @return none + *************************************************************************/ +static void checkDialInPumpRotor( void ) +{ + // if homing, check timeout + if ( ( TRUE == dipStopAtHomePosition ) && ( TRUE == didTimeout( dipHomeStartTime, DIP_HOME_TIMEOUT_MS ) ) ) { - if ( flowReadingsCount >= SIZE_OF_ROLLING_AVG ) - { - flowReadingsTotal -= flowReadings[ flowReadingsIdx ]; - } - flowReadings[ flowReadingsIdx ] = flow; - flowReadingsTotal += flow; - flowReadingsIdx = INC_WRAP( flowReadingsIdx, 0, SIZE_OF_ROLLING_AVG - 1 ); - flowReadingsCount = INC_CAP( flowReadingsCount, SIZE_OF_ROLLING_AVG ); - measuredDialInFlowRate.data = flowReadingsTotal / (F32)flowReadingsCount; + signalDialInPumpHardStop(); + dipStopAtHomePosition = FALSE; + // TODO - alarm??? } - flowReadingsTmrCtr = INC_WRAP( flowReadingsTmrCtr, 0, MAX_FLOW_FILTER_INTERVAL - 1 ); + // if pump is stopped or running very slowly, set rotor speed to zero + if ( TRUE == didTimeout( dipRotorRevStartTime, DIP_HOME_TIMEOUT_MS ) ) + { + dialInPumpRotorSpeedRPM.data = 0.0; + } } -/************************************************************************* - * @brief checkDialInPumpDirection +/*********************************************************************//** + * @brief * The checkDialInPumpDirection function checks the set direction vs. \n * the direction implied by the sign of the measured MC speed. * @details * Inputs : adcDialInPumpMCSpeedRPM, dialInPumpDirectionSet, dialInPumpState * Outputs : none - * @param none * @return none *************************************************************************/ static void checkDialInPumpDirection( void ) @@ -784,23 +868,151 @@ if ( DIAL_IN_PUMP_CONTROL_TO_TARGET_STATE == dialInPumpState ) { - // check set direction vs. direction from sign of motor controller speed + // check set direction vs. direction from hall sensors or sign of motor controller speed dipMCDir = ( getMeasuredDialInPumpMCSpeed() >= 0.0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); - if ( dialInPumpDirectionSet != dipMCDir ) + if ( ( dialInPumpDirectionSet != dipMCDir ) || ( dialInPumpDirectionSet != dipMotorDirectionFromHallSensors ) ) { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DIAL_IN_PUMP_MC_DIRECTION_CHECK, (U32)dialInPumpDirectionSet, (U32)dipMCDir ) +#ifndef DISABLE_PUMP_DIRECTION_CHECKS + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DIAL_IN_PUMP_MC_DIRECTION_CHECK, (U32)dialInPumpDirectionSet, (U32)dipMotorDirectionFromHallSensors ) +#endif } } } -/************************************************************************* - * @brief checkDialInPumpMCCurrent +/*********************************************************************//** + * @brief + * The checkDialInPumpSpeeds function checks several aspects of the dialysate \n + * inlet pump speed. \n + * 1. while pump is commanded off, measured motor speed should be < limit. \n + * 2. while pump is controlling, measured motor speed should be within allowed range of commanded speed. \n + * 3. measured motor speed should be within allowed range of measured rotor speed. \n + * All 3 checks have a persistence time that must be met before an alarm is triggered. + * @details + * Inputs : targetDialInFlowRate, dialInPumpSpeedRPM, dialInPumpRotorSpeedRPM + * Outputs : alarm(s) may be triggered + * @return none + *************************************************************************/ +static void checkDialInPumpSpeeds( void ) +{ + F32 measMotorSpeed = getMeasuredDialInPumpSpeed(); + S32 cmdRate = getTargetDialInFlowRate(); + + // check for pump running while commanded off + if ( 0 == cmdRate ) + { + if ( measMotorSpeed > DIP_MAX_MOTOR_SPEED_WHILE_OFF_RPM ) + { + if ( ++errorDialInMotorOffPersistTimerCtr >= DIP_OFF_ERROR_PERSIST ) + { +#ifndef DISABLE_PUMP_SPEED_CHECKS + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DIAL_IN_PUMP_OFF_CHECK, measMotorSpeed ); +#endif + } + } + else + { + errorDialInMotorOffPersistTimerCtr = 0; + } + } + else + { + errorDialInMotorOffPersistTimerCtr = 0; + } + + if ( DIAL_IN_PUMP_CONTROL_TO_TARGET_STATE == dialInPumpState ) + { + F32 cmdMotorSpeed = ( (F32)cmdRate / (F32)ML_PER_LITER ) * DIP_REV_PER_LITER * DIP_GEAR_RATIO; + F32 deltaMotorSpeed = FABS( measMotorSpeed - cmdMotorSpeed ); + F32 measRotorSpeed = getMeasuredDialInPumpRotorSpeed(); + F32 measMotorSpeedInRotorRPM = measMotorSpeed / DIP_GEAR_RATIO; + F32 deltaRotorSpeed = FABS( measRotorSpeed - measMotorSpeedInRotorRPM ); + + // check measured motor speed vs. commanded motor speed while controlling to target + if ( deltaMotorSpeed > DIP_MAX_MOTOR_SPEED_ERROR_RPM ) + { + if ( ++errorDialInMotorSpeedPersistTimerCtr >= DIP_MOTOR_SPEED_ERROR_PERSIST ) + { +#ifndef DISABLE_PUMP_SPEED_CHECKS + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DIAL_IN_PUMP_MOTOR_SPEED_CHECK, (F32)cmdRate, measMotorSpeed ); +#endif + } + } + else + { + errorDialInMotorSpeedPersistTimerCtr = 0; + } + + // check measured rotor speed vs. measured motor speed while controlling to target + if ( deltaRotorSpeed > DIP_MAX_ROTOR_VS_MOTOR_DIFF_RPM ) + { + if ( ++errorDialInRotorSpeedPersistTimerCtr >= DIP_ROTOR_SPEED_ERROR_PERSIST ) + { +#ifndef DISABLE_PUMP_SPEED_CHECKS + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DIAL_IN_PUMP_ROTOR_SPEED_CHECK, measRotorSpeed, measMotorSpeed ); +#endif + } + } + else + { + errorDialInRotorSpeedPersistTimerCtr = 0; + } + + } + else + { + errorDialInMotorSpeedPersistTimerCtr = 0; + errorDialInRotorSpeedPersistTimerCtr = 0; + } +} + +/*********************************************************************//** + * @brief + * The checkDialInPumpFlowAgainstSpeed function checks the measured dialysate flow \n + * against the implied flow of the measured pump speed when in treatment mode \n + * and controlling to target flow. If a sufficient difference persists, a \n + * flow vs. motor speed check error is triggered. + * @details + * Inputs : measuredDialInFlowRate, dialInPumpSpeedRPM, errorDialInFlowVsMotorSpeedPersistTimerCtr + * Outputs : alarm may be triggered + * @return none + *************************************************************************/ +static void checkDialInPumpFlowAgainstSpeed( void ) +{ + // check only performed while in treatment mode and while we're in control to target state + if ( ( MODE_TREA == getCurrentOperationMode() ) && ( DIAL_IN_PUMP_CONTROL_TO_TARGET_STATE == dialInPumpState ) ) + { + F32 flow = getMeasuredDialInFlowRate(); + F32 speed = getMeasuredDialInPumpSpeed(); + F32 impliedFlow = ( ( speed / DIP_GEAR_RATIO ) / DIP_REV_PER_LITER ) * (F32)ML_PER_LITER; + F32 delta = FABS( flow - impliedFlow ); + + if ( delta > DIP_MAX_FLOW_VS_SPEED_DIFF_ML_MIN ) + { + if ( ++errorDialInFlowVsMotorSpeedPersistTimerCtr >= DIP_FLOW_VS_SPEED_PERSIST ) + { +#ifndef DISABLE_PUMP_FLOW_CHECKS + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DIAL_IN_PUMP_FLOW_VS_MOTOR_SPEED_CHECK, flow, impliedFlow ); +#endif + } + } + else + { + errorDialInFlowVsMotorSpeedPersistTimerCtr = 0; + } + } + else + { + errorDialInFlowVsMotorSpeedPersistTimerCtr = 0; + } +} + +/*********************************************************************//** + * @brief * The checkDialInPumpMCCurrent function checks the measured MC current vs. \n * the set state of the dialIn pump (stopped or running). * @details * Inputs : dialInPumpState, dipCurrErrorDurationCtr, adcDialInPumpMCCurrentmA * Outputs : none - * @param none * @return none *************************************************************************/ static void checkDialInPumpMCCurrent( void ) @@ -816,7 +1028,7 @@ dipCurrErrorDurationCtr += TASK_PRIORITY_INTERVAL; if ( dipCurrErrorDurationCtr > DIP_MAX_CURR_ERROR_DURATION_MS ) { -#ifndef DISABLE_MOTOR_CURRENT_ERRORS +#ifndef DISABLE_MOTOR_CURRENT_CHECKS SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DIAL_IN_PUMP_MC_CURRENT_CHECK, getMeasuredDialInPumpMCCurrent() ); #endif } @@ -835,7 +1047,7 @@ dipCurrErrorDurationCtr += TASK_PRIORITY_INTERVAL; if ( dipCurrErrorDurationCtr > DIP_MAX_CURR_ERROR_DURATION_MS ) { -#ifndef DISABLE_MOTOR_CURRENT_ERRORS +#ifndef DISABLE_MOTOR_CURRENT_CHECKS SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DIAL_IN_PUMP_MC_CURRENT_CHECK, getMeasuredDialInPumpMCCurrent() ); #endif } @@ -847,14 +1059,13 @@ } } -/************************************************************************* - * @brief execDialInFlowTest +/*********************************************************************//** + * @brief * The execDialInFlowTest function executes the state machine for the \n * DialInFlow self test. * @details * Inputs : none * Outputs : none - * @param none * @return the current state of the DialInFlow self test. *************************************************************************/ SELF_TEST_STATUS_T execDialInFlowTest( void ) @@ -872,8 +1083,8 @@ *************************************************************************/ -/************************************************************************* - * @brief testSetDialInFlowDataPublishIntervalOverride +/*********************************************************************//** + * @brief * The testSetDialInFlowDataPublishIntervalOverride function overrides the \n * dialIn flow data publish interval. * @details @@ -898,8 +1109,8 @@ return result; } -/************************************************************************* - * @brief testResetDialInFlowDataPublishIntervalOverride +/*********************************************************************//** + * @brief * The testResetDialInFlowDataPublishIntervalOverride function resets the override \n * of the dialIn flow data publish interval. * @details @@ -921,7 +1132,7 @@ return result; } -/************************************************************************* +/*********************************************************************//** * @brief * The testSetTargetDialInFlowRateOverride function overrides the target \n * dialysate inlet flow rate. \n @@ -956,14 +1167,13 @@ return result; } -/************************************************************************* +/*********************************************************************//** * @brief * The testResetTargetDialInFlowRateOverride function resets the override of the \n * target dialysate inlet flow rate. * @details * Inputs : none * Outputs : targetDialInFlowRate - * @param none * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetTargetDialInFlowRateOverride( void ) @@ -982,7 +1192,7 @@ return result; } -/************************************************************************* +/*********************************************************************//** * @brief * The testResetMeasuredDialInFlowRateOverride function overrides the measured \n * dialIn flow rate. @@ -1006,7 +1216,7 @@ return result; } -/************************************************************************* +/*********************************************************************//** * @brief * The testResetMeasuredDialInFlowRateOverride function resets the override of the \n * measured dialIn flow rate. @@ -1029,7 +1239,7 @@ return result; } -/************************************************************************* +/*********************************************************************//** * @brief * The testSetMeasuredDialInPumpRotorSpeedOverride function overrides the measured \n * dialIn pump rotor speed. @@ -1053,7 +1263,7 @@ return result; } -/************************************************************************* +/*********************************************************************//** * @brief * The testResetMeasuredDialInPumpRotorSpeedOverride function resets the override of the \n * measured dialIn pump rotor speed. @@ -1076,7 +1286,7 @@ return result; } -/************************************************************************* +/*********************************************************************//** * @brief * The testSetMeasuredDialInPumpSpeedOverride function overrides the measured \n * dialIn pump motor speed. @@ -1100,7 +1310,7 @@ return result; } -/************************************************************************* +/*********************************************************************//** * @brief * The testResetMeasuredDialInPumpSpeedOverride function resets the override of the \n * measured dialIn pump motor speed. @@ -1123,7 +1333,7 @@ return result; } -/************************************************************************* +/*********************************************************************//** * @brief * The testSetMeasuredDialInPumpMCSpeedOverride function overrides the measured \n * dialIn pump motor speed. @@ -1147,7 +1357,7 @@ return result; } -/************************************************************************* +/*********************************************************************//** * @brief * The testResetMeasuredDialInPumpMCSpeedOverride function resets the override of the \n * measured dialIn pump motor speed. @@ -1170,7 +1380,7 @@ return result; } -/************************************************************************* +/*********************************************************************//** * @brief * The testSetMeasuredDialInPumpMCCurrentOverride function overrides the measured \n * dialIn pump motor current. @@ -1194,7 +1404,7 @@ return result; } -/************************************************************************* +/*********************************************************************//** * @brief * The testResetMeasuredDialInPumpMCCurrentOverride function resets the override of the \n * measured dialIn pump motor current. @@ -1217,4 +1427,4 @@ return result; } - +/**@}*/