/************************************************************************** * * Copyright (c) 2019-2019 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 DialOutUF.c * * @date 16-Dec-2019 * @author S. Nash & L. Baloa * * @brief Monitor/Controller for dialysate outlet pump and load sensors. * **************************************************************************/ #ifndef _VECTORCAST_ #include #endif #include "can.h" #include "etpwm.h" #include "Common.h" #include "FPGA.h" #include "InternalADC.h" #include "OperationModes.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "TaskPriority.h" #include "Timers.h" #include "DialOutUF.h" // ********** private definitions ********** #define DIAL_OUT_FLOW_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) // interval (ms/task time) at which the dialOut flow data is published on the CAN bus #define MAX_DIAL_OUT_FLOW_RATE 500 // mL/min #define MIN_DIAL_OUT_FLOW_RATE 100 // mL/min #define MAX_DIAL_OUT_PUMP_PWM_STEP_CHANGE 0.02 // duty cycle TODO - fixed or parameterized or set in motor controller? #define MAX_DIAL_OUT_PUMP_PWM_DUTY_CYCLE 0.88 // controller will error if PWM duty cycle > 90%, so set max to 88% #define MIN_DIAL_OUT_PUMP_PWM_DUTY_CYCLE 0.12 // controller will error if PWM duty cycle < 10%, so set min to 12% #define DOP_CONTROL_INTERVAL ( 500 / TASK_GENERAL_INTERVAL ) // interval (ms/task time) at which the dialOut pump is controlled #define DOP_P_COEFFICIENT 0.0002 // P term for dialOut pump control #define DOP_I_COEFFICIENT 0.00002 // I term for dialOut pump control #define DOP_MAX_ERROR_SUM 10.0 // for anti-wind-up in I term #define DOP_MIN_ERROR_SUM -10.0 #define DOP_MAX_PWM_DC_DELTA 0.01 // prevents large steps in PWM duty cycle #define DOP_MIN_PWM_DC_DELTA -0.01 #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_ERROR_DURATION_MS 2000 // motor controller current errors persisting beyond this duration will trigger an alarm #define DOP_SPEED_ADC_TO_RPM_FACTOR 1.375 // conversion factor from ADC counts to RPM for dialOut pump motor #define DOP_CURRENT_ADC_TO_MA_FACTOR 2.65 // conversion factor from ADC counts to mA for dialOut pump motor #define DOP_REV_PER_LITER 124.0 // rotor revolutions per liter #define DOP_ML_PER_MIN_TO_PUMP_RPM_FACTOR ( DOP_REV_PER_LITER / ML_PER_LITER ) #define DOP_GEAR_RATIO 32.0 // dialOut pump motor to dialOut pump gear ratio #define DOP_MOTOR_RPM_TO_PWM_DC_FACTOR 0.0003717 // ~27 BP 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 ) #define DIAL_OUTPUMP_ADC_FULL_SCALE_V 3.0 // BP analog signals are 0-3V (while int. ADC ref V is 3.3V) #define DIAL_OUTPUMP_ADC_MID_PT_BITS ( (F32)( INT_ADC_FULL_SCALE_BITS >> 1 ) * ( DIAL_OUTPUMP_ADC_FULL_SCALE_V / INT_ADC_REF_V ) ) #define SIGN_FROM_12_BIT_VALUE(v) ( (S16)(v) - (S16)DIAL_OUTPUMP_ADC_MID_PT_BITS ) #define DIAL_OUT_FLOW_SAMPLE_FREQ ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) #define SIZE_OF_ROLLING_AVG (U32)( (F32)DIAL_OUT_FLOW_SAMPLE_FREQ * 0.8 ) // measured dialOut flow is filtered w/ moving average #define MAX_FLOW_FILTER_INTERVAL 5 // slowest sample interval for filter is every 5th sample typedef enum DialOutPump_States { DIAL_OUT_PUMP_OFF_STATE = 0, DIAL_OUT_PUMP_RAMPING_UP_STATE, DIAL_OUT_PUMP_RAMPING_DOWN_STATE, DIAL_OUT_PUMP_CONTROL_TO_TARGET_STATE, NUM_OF_DIAL_OUT_PUMP_STATES } DIAL_OUT_PUMP_STATE_T; typedef enum DialOutUF_Self_Test_States { DIAL_OUT_FLOW_SELF_TEST_STATE_START = 0, DIAL_OUT_FLOW_TEST_STATE_IN_PROGRESS, DIAL_OUT_FLOW_TEST_STATE_COMPLETE, NUM_OF_DIAL_OUT_FLOW_SELF_TEST_STATES } DIAL_OUT_FLOW_SELF_TEST_STATE_T; // CAN3 port pin assignments for pump stop and direction outputs #define STOP_CAN3_PORT_MASK 0x00000002 // (Tx - re-purposed as output GPIO for dialOut pump stop signal) #define DIR_CAN3_PORT_MASK 0x00000002 // (Rx - re-purposed as output GPIO for dialOut pump direction signal) // dialOut pump stop and direction macros #define SET_DOP_DIR() {canREG3->RIOC |= DIR_CAN3_PORT_MASK;} #define SET_DOP_STOP() {canREG3->TIOC |= STOP_CAN3_PORT_MASK;} #define CLR_DOP_DIR() {canREG3->RIOC &= ~DIR_CAN3_PORT_MASK;} #define CLR_DOP_STOP() {canREG3->TIOC &= ~STOP_CAN3_PORT_MASK;} // ********** private data ********** static DIAL_OUT_PUMP_STATE_T dialOutPumpState = DIAL_OUT_PUMP_OFF_STATE; // current state of dialOut flow controller state machine static U32 dialOutFlowDataPublicationTimerCounter = 0; // used to schedule dialOut flow data publication to CAN bus static BOOL isDialOutPumpOn = FALSE; // dialOut pump is currently running static F32 dialOutPumpPWMDutyCyclePct = 0.0; // initial dialOut pump PWM duty cycle static F32 dialOutPumpPWMDutyCyclePctSet = 0.0; // currently set dialOut pump PWM duty cycle static MOTOR_DIR_T dialOutPumpDirection = MOTOR_DIR_FORWARD; // requested dialOut flow direction static MOTOR_DIR_T dialOutPumpDirectionSet = MOTOR_DIR_FORWARD; // currently set dialOut flow direction DATA_DECL( U32, DialOutUFDataPub, dialOutFlowDataPublishInterval, DIAL_OUT_FLOW_DATA_PUB_INTERVAL, DIAL_OUT_FLOW_DATA_PUB_INTERVAL ); // interval (in ms) at which to publish dialOut flow data to CAN bus DATA_DECL( S32, TargetDialOutUFRate, targetDialOutUFRate, 0, 0 ); // requested dialOut flow rate DATA_DECL( F32, MeasuredDialOutUFRate, measuredDialOutUFLoad, 0.0, 0.0 ); // measured dialOut flow rate DATA_DECL( F32, MeasuredDialOutPumpRotorSpeed, dialOutPumpRotorSpeedRPM, 0.0, 0.0 );// measured dialOut pump rotor speed DATA_DECL( F32, MeasuredDialOutPumpSpeed, dialOutPumpSpeedRPM, 0.0, 0.0 ); // measured dialOut pump motor speed DATA_DECL( F32, MeasuredDialOutPumpMCSpeed, adcDialOutPumpMCSpeedRPM, 0.0, 0.0 ); // measured dialOut pump motor controller speed DATA_DECL( F32, MeasuredDialOutPumpMCCurrent, adcDialOutPumpMCCurrentmA, 0.0, 0.0 );// measured dialOut pump motor controller current static U32 dopCurrErrorDurationCtr = 0; // used for tracking persistence of dop current errors static DIAL_OUT_FLOW_SELF_TEST_STATE_T dialOutPumpSelfTestState = DIAL_OUT_FLOW_SELF_TEST_STATE_START; // current dialOut pump self test state static U32 dialOutPumpSelfTestTimerCount = 0; // timer counter for dialOut pump self test // ********** private function prototypes ********** static DIAL_OUT_PUMP_STATE_T handleDialOutPumpOffState( void ); static DIAL_OUT_PUMP_STATE_T handleDialOutPumpRampingUpState( void ); static DIAL_OUT_PUMP_STATE_T handleDialOutPumpRampingDownState( void ); static DIAL_OUT_PUMP_STATE_T handleDialOutPumpControlToTargetState( void ); static void stopDialOutPump( void ); static void releaseDialOutPumpStop( void ); static void setDialOutPumpDirection( MOTOR_DIR_T dir ); static void publishDialOutUFData( void ); static void checkDialOutPumpDirection( void ); static void checkDialOutPumpMCCurrent( void ); static DATA_GET_PROTOTYPE( U32, getPublishDialOutUFDataInterval ); /************************************************************************* * @brief initDialOutUF * The initDialOutUF function initializes the DialOutUF module. * @details * Inputs : none * Outputs : DialOutUF module initialized. * @param none * @return none *************************************************************************/ void initDialOutUF( void ) { stopDialOutPump(); setDialOutPumpDirection( MOTOR_DIR_FORWARD ); } /************************************************************************* * @brief setDialOutPumpTargetFlowRate * The setDialOutPumpTargetFlowRate function sets a new target flow rate and * pump direction. * @details * Inputs : isDialOutPumpOn, dialOutPumpDirectionSet * Outputs : targetDialOutUFRate, dialOutPumpdirection, dialOutPumpPWMDutyCyclePct * @param flowRate : new target dialOut flow rate * @param dir : new dialOut flow direction * @return TRUE if new flow rate & dir are set, FALSE if not *************************************************************************/ BOOL setDialOutPumpTargetFlowRate( U32 flowRate, MOTOR_DIR_T dir ) { BOOL result = FALSE; // direction change while pump is running is not allowed if ( ( FALSE == isDialOutPumpOn ) || ( 0 == flowRate ) || ( dir == dialOutPumpDirectionSet ) ) { // verify flow rate if ( flowRate <= MAX_DIAL_OUT_FLOW_RATE ) { targetDialOutUFRate.data = ( dir == MOTOR_DIR_FORWARD ? (S32)flowRate : (S32)flowRate * -1 ); dialOutPumpDirection = dir; // set PWM duty cycle target to an estimated initial target to ramp to based on target flow rate - then we'll control to flow when ramp completed dialOutPumpPWMDutyCyclePct = DOP_PWM_FROM_ML_PER_MIN((F32)flowRate); // ~ 8% per 100 mL/min with a 10% zero offset added in (e.g. 100 mL/min = 8+10 = 18%) switch ( dialOutPumpState ) { case DIAL_OUT_PUMP_RAMPING_UP_STATE: // see if we need to reverse direction of ramp if ( dialOutPumpPWMDutyCyclePct < dialOutPumpPWMDutyCyclePctSet ) { dialOutPumpState = DIAL_OUT_PUMP_RAMPING_DOWN_STATE; } break; case DIAL_OUT_PUMP_RAMPING_DOWN_STATE: // see if we need to reverse direction of ramp if ( dialOutPumpPWMDutyCyclePct > dialOutPumpPWMDutyCyclePctSet ) { dialOutPumpState = DIAL_OUT_PUMP_RAMPING_UP_STATE; } break; case DIAL_OUT_PUMP_CONTROL_TO_TARGET_STATE: // start ramp to new target in appropriate direction if ( dialOutPumpPWMDutyCyclePctSet > dialOutPumpPWMDutyCyclePct ) { dialOutPumpState = DIAL_OUT_PUMP_RAMPING_DOWN_STATE; } else { dialOutPumpState = DIAL_OUT_PUMP_RAMPING_UP_STATE; } break; default: // ok - not all states need to be handled here break; } result = TRUE; } else // requested flow rate too high { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_DIAL_OUT_FLOW_SET_TOO_HIGH, flowRate ) } } return result; } /************************************************************************* * @brief signalDialOutPumpHardStop * The signalDialOutPumpHardStop function stops the dialOut pump immediately. * @details * Inputs : none * Outputs : DialOut pump stopped, set point reset, state changed to off * @param none * @return none *************************************************************************/ void signalDialOutPumpHardStop( void ) { targetDialOutUFRate.data = 0; stopDialOutPump(); dialOutPumpState = DIAL_OUT_PUMP_OFF_STATE; dialOutPumpPWMDutyCyclePct = 0.0; } /************************************************************************* * @brief execDialOutUFMonitor * The execDialOutUFMonitor function executes the dialOut flow monitor. * @details * Inputs : none * Outputs : measuredDialOutUFLoad, adcDialOutPumpMCSpeedRPM, adcDialOutPumpMCCurrentmA * @param none * @return none *************************************************************************/ void execDialOutUFMonitor( void ) { U16 dopRPM = getIntADCReading( INT_ADC_DIAL_OUT_PUMP_SPEED ); U16 dopmA = getIntADCReading( INT_ADC_DIAL_OUT_PUMP_MOTOR_CURRENT ); F32 dopLoad = 0.0; // TODO - get load cell from FPGA (or dialin for now) adcDialOutPumpMCSpeedRPM.data = (F32)(SIGN_FROM_12_BIT_VALUE(dopRPM)) * DOP_SPEED_ADC_TO_RPM_FACTOR; adcDialOutPumpMCCurrentmA.data = (F32)(SIGN_FROM_12_BIT_VALUE(dopmA)) * DOP_CURRENT_ADC_TO_MA_FACTOR; // don't start enforcing checks until out of init/POST mode if ( getCurrentOperationMode() != MODE_INIT ) { checkDialOutPumpDirection(); checkDialOutPumpMCCurrent(); } // publish dialOut flow data on interval publishDialOutUFData(); } /************************************************************************* * @brief execDialOutUFController * The execDialOutUFController function executes the dialOut flow controller. * @details * Inputs : dialOutPumpState * Outputs : dialOutPumpState * @param none * @return none *************************************************************************/ void execDialOutUFController( void ) { switch ( dialOutPumpState ) { case DIAL_OUT_PUMP_OFF_STATE: dialOutPumpState = handleDialOutPumpOffState(); break; case DIAL_OUT_PUMP_RAMPING_UP_STATE: dialOutPumpState = handleDialOutPumpRampingUpState(); break; case DIAL_OUT_PUMP_RAMPING_DOWN_STATE: dialOutPumpState = handleDialOutPumpRampingDownState(); break; case DIAL_OUT_PUMP_CONTROL_TO_TARGET_STATE: dialOutPumpState = handleDialOutPumpControlToTargetState(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_DIAL_OUT_FLOW_INVALID_DIAL_OUT_PUMP_STATE, dialOutPumpState ) break; } } /************************************************************************* * @brief handleDialOutPumpOffState * The handleDialOutPumpOffState function handles the dialOut pump off state \n * of the dialOut pump controller state machine. * @details * Inputs : targetDialOutUFRate, dialOutPumpDirection * Outputs : dialOutPumpPWMDutyCyclePctSet, dialOutPumpDirectionSet, isDialOutPumpOn * @param none * @return next state *************************************************************************/ static DIAL_OUT_PUMP_STATE_T handleDialOutPumpOffState( void ) { DIAL_OUT_PUMP_STATE_T result = DIAL_OUT_PUMP_OFF_STATE; // if we've been given a flow rate, setup ramp up and transition to ramp up state if ( getTargetDialOutUFRate() != 0 ) { // set initial PWM duty cycle dialOutPumpPWMDutyCyclePctSet = MAX_DIAL_OUT_PUMP_PWM_STEP_CHANGE; etpwmSetCmpA( etpwmREG1, (U32)FLOAT_TO_INT_WITH_ROUND( dialOutPumpPWMDutyCyclePctSet * (F32)(etpwmREG1->TBPRD) ) ); // allow dialOut pump to run in requested direction setDialOutPumpDirection( dialOutPumpDirection ); releaseDialOutPumpStop(); // start PWM for dialOut pump etpwmStartTBCLK(); isDialOutPumpOn = TRUE; result = DIAL_OUT_PUMP_RAMPING_UP_STATE; } return result; } /************************************************************************* * @brief handleDialOutPumpRampingUpState * The handleDialOutPumpRampingUpState function handles the ramp up state \n * of the dialOut pump controller state machine. * @details * Inputs : dialOutPumpPWMDutyCyclePctSet * Outputs : dialOutPumpPWMDutyCyclePctSet * @param none * @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 ( 0 == getTargetDialOutUFRate() ) { // start ramp down to stop dialOutPumpPWMDutyCyclePctSet -= MAX_DIAL_OUT_PUMP_PWM_STEP_CHANGE; etpwmSetCmpA( etpwmREG1, (U32)FLOAT_TO_INT_WITH_ROUND( dialOutPumpPWMDutyCyclePctSet * (F32)(etpwmREG1->TBPRD) ) ); result = DIAL_OUT_PUMP_RAMPING_DOWN_STATE; } // have we reached end of ramp up? else if ( dialOutPumpPWMDutyCyclePctSet >= dialOutPumpPWMDutyCyclePct ) { result = DIAL_OUT_PUMP_CONTROL_TO_TARGET_STATE; } // continue ramp up else { dialOutPumpPWMDutyCyclePctSet += MAX_DIAL_OUT_PUMP_PWM_STEP_CHANGE; etpwmSetCmpA( etpwmREG1, (U32)FLOAT_TO_INT_WITH_ROUND( dialOutPumpPWMDutyCyclePctSet * (F32)(etpwmREG1->TBPRD) ) ); } return result; } /************************************************************************* * @brief handleDialOutPumpRampingDownState * The handleDialOutPumpRampingDownState function handles the ramp down state \n * of the dialOut pump controller state machine. * @details * Inputs : dialOutPumpPWMDutyCyclePctSet * Outputs : dialOutPumpPWMDutyCyclePctSet * @param none * @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_CHANGE + DOP_PWM_ZERO_OFFSET) ) { stopDialOutPump(); result = DIAL_OUT_PUMP_OFF_STATE; } // have we reached end of ramp down? else if ( dialOutPumpPWMDutyCyclePctSet <= dialOutPumpPWMDutyCyclePct ) { result = DIAL_OUT_PUMP_CONTROL_TO_TARGET_STATE; } // continue ramp down else { dialOutPumpPWMDutyCyclePctSet -= MAX_DIAL_OUT_PUMP_PWM_STEP_CHANGE; etpwmSetCmpA( etpwmREG1, (U32)FLOAT_TO_INT_WITH_ROUND( dialOutPumpPWMDutyCyclePctSet * (F32)(etpwmREG1->TBPRD) ) ); } return result; } /************************************************************************* * @brief handleDialOutPumpControlToTargetState * The handleDialOutPumpControlToTargetState function handles the "control to \n * target" state of the dialOut pump controller state machine. * @details * Inputs : none * Outputs : dialOutPumpState * @param none * @return next state *************************************************************************/ static DIAL_OUT_PUMP_STATE_T handleDialOutPumpControlToTargetState( void ) { DIAL_OUT_PUMP_STATE_T result = DIAL_OUT_PUMP_CONTROL_TO_TARGET_STATE; // TODO - control algorithm return result; } /************************************************************************* * @brief stopDialOutPump * The stopDialOutPump function sets the dialOut pump stop signal. * @details * Inputs : none * Outputs : dialOut pump stop signal activated, PWM duty cycle zeroed * @param none * @return none *************************************************************************/ static void stopDialOutPump( void ) { isDialOutPumpOn = FALSE; dialOutPumpPWMDutyCyclePctSet = 0.0; etpwmSetCmpA( etpwmREG1, 0 ); etpwmStopTBCLK(); SET_DOP_STOP(); } /************************************************************************* * @brief releaseDialOutPumpStop * The releaseDialOutPumpStop function clears the dialOut pump stop signal. * @details * Inputs : none * Outputs : dialOut pump stop signal * @param none * @return none *************************************************************************/ static void releaseDialOutPumpStop( void ) { CLR_DOP_STOP(); } /************************************************************************* * @brief setDialOutPumpDirection * The setDialOutPumpDirection function sets the set dialOut pump direction to \n * the given direction. * @details * Inputs : dialOutPumpState * Outputs : dialOutPumpState * @param dir : dialOut pump direction to set * @return none *************************************************************************/ static void setDialOutPumpDirection( MOTOR_DIR_T dir ) { switch ( dir ) { case MOTOR_DIR_FORWARD: dialOutPumpDirectionSet = dir; SET_DOP_DIR(); break; case MOTOR_DIR_REVERSE: dialOutPumpDirectionSet = dir; CLR_DOP_DIR(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_DIAL_OUT_FLOW_INVALID_DIAL_OUT_PUMP_DIRECTION, dir ) break; } } /************************************************************************* * @brief getPublishDialOutUFDataInterval * The getPublishDialOutUFDataInterval function gets the dialOut flow data \n * publication interval. * @details * Inputs : dialOutFlowDataPublishInterval * Outputs : none * @param none * @return the current dialOut flow data publication interval (in ms). *************************************************************************/ DATA_GET( U32, getPublishDialOutUFDataInterval, dialOutFlowDataPublishInterval ) /************************************************************************* * @brief getTargetDialOutUFRate * The getTargetDialOutUFRate function gets the current target dialOut flow \n * rate. * @details * Inputs : targetDialOutUFRate * Outputs : none * @param none * @return the current target dialOut flow rate (in mL/min). *************************************************************************/ DATA_GET( S32, getTargetDialOutUFRate, targetDialOutUFRate ) /************************************************************************* * @brief getMeasuredDialOutUFLoad * The getMeasuredDialOutUFLoad function gets the measured dialOut flow \n * rate. * @details * Inputs : measuredDialOutUFLoad * Outputs : none * @param none * @return the current dialOut flow rate (in mL/min). *************************************************************************/ DATA_GET( F32, getMeasuredDialOutUFLoad, measuredDialOutUFLoad ) /************************************************************************* * @brief getMeasuredDialOutPumpRotorSpeed * The getMeasuredDialOutPumpRotorSpeed function gets the measured dialOut flow \n * rate. * @details * Inputs : dialOutPumpRotorSpeedRPM * Outputs : none * @param none * @return the current dialOut flow rate (in mL/min). *************************************************************************/ DATA_GET( F32, getMeasuredDialOutPumpRotorSpeed, dialOutPumpRotorSpeedRPM ) /************************************************************************* * @brief getMeasuredDialOutPumpSpeed * The getMeasuredDialOutPumpSpeed function gets the measured dialOut flow \n * rate. * @details * Inputs : dialOutPumpSpeedRPM * Outputs : none * @param none * @return the current dialOut flow rate (in mL/min). *************************************************************************/ DATA_GET( F32, getMeasuredDialOutPumpSpeed, dialOutPumpSpeedRPM ) /************************************************************************* * @brief getMeasuredDialOutPumpMCSpeed * The getMeasuredDialOutPumpMCSpeed function gets the measured dialOut pump \n * speed. * @details * Inputs : adcDialOutPumpMCSpeedRPM * Outputs : none * @param none * @return the current dialOut pump speed (in RPM). *************************************************************************/ DATA_GET( F32, getMeasuredDialOutPumpMCSpeed, adcDialOutPumpMCSpeedRPM ) /************************************************************************* * @brief getMeasuredDialOutPumpMCCurrent * The getMeasuredDialOutPumpMCCurrent function gets the measured dialOut pump \n * current. * @details * Inputs : adcDialOutPumpMCCurrentmA * Outputs : none * @param none * @return the current dialOut pump current (in mA). *************************************************************************/ DATA_GET( F32, getMeasuredDialOutPumpMCCurrent, adcDialOutPumpMCCurrentmA ) /************************************************************************* * @brief publishDialOutUFData * The publishDialOutUFData function publishes dialOut flow data at the set \n * interval. * @details * Inputs : target flow rate, measured flow rate, measured MC speed, \n * measured MC current * Outputs : DialOut flow data is published to CAN bus. * @param none * @return none *************************************************************************/ static void publishDialOutUFData( void ) { // publish dialOut flow data on interval if ( ++dialOutFlowDataPublicationTimerCounter > getPublishDialOutUFDataInterval() ) { S32 flowStPt = (S32)getTargetDialOutUFRate(); F32 measLoad = getMeasuredDialOutUFLoad(); F32 measRotSpd = getMeasuredDialOutPumpRotorSpeed(); F32 measSpd = getMeasuredDialOutPumpSpeed(); F32 measMCSpd = getMeasuredDialOutPumpMCSpeed(); F32 measMCCurr = getMeasuredDialOutPumpMCCurrent(); #ifdef DEBUG_ENABLED // TODO - temporary debug code - remove later S32 pwm = (S32)( 100.0 * dialOutPumpPWMDutyCyclePctSet ); char debugStr[ 256 ]; sprintf( debugStr, "Target Flow:%5d, Meas. Flow:%5d, Speed:%5d RPM, Current:%5d mA, PWM:%5d \n", flowStPt, (S32)measLoad, (S32)measMCSpd, (S32)measMCCurr, pwm ); sendDebugData( (U08*)debugStr, strlen(debugStr) ); #endif // TODO - broadcastDialOutUFData( flowStPt, measLoad, measRotSpd, measSpd, measMCSpd, measMCCurr ); dialOutFlowDataPublicationTimerCounter = 0; } } /************************************************************************* * @brief checkDialOutPumpDirection * The checkDialOutPumpDirection function checks the set direction vs. \n * the direction implied by the sign of the measured MC speed. * @details * Inputs : * Outputs : * @param 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 sign of motor controller speed dopMCDir = ( getMeasuredDialOutPumpMCSpeed() >= 0.0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); if ( dialOutPumpDirectionSet != dopMCDir ) { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DIAL_OUT_PUMP_MC_DIRECTION_CHECK, (U32)dialOutPumpDirectionSet, (U32)dopMCDir ) } } } /************************************************************************* * @brief checkDialOutPumpMCCurrent * The checkDialOutPumpMCCurrent function checks the measured MC current vs. \n * the set state of the dialOut pump (stopped or running). * @details * Inputs : * Outputs : * @param none * @return none *************************************************************************/ static void checkDialOutPumpMCCurrent( void ) { F32 dopCurr; // dialOut pump should be off if ( DIAL_OUT_PUMP_OFF_STATE == dialOutPumpState ) { dopCurr = fabs( getMeasuredDialOutPumpMCCurrent() ); if ( dopCurr > DOP_MAX_CURR_WHEN_STOPPED_MA ) { dopCurrErrorDurationCtr += TASK_PRIORITY_INTERVAL; if ( dopCurrErrorDurationCtr > DOP_MAX_CURR_ERROR_DURATION_MS ) { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DIAL_OUT_PUMP_MC_CURRENT_CHECK, getMeasuredDialOutPumpMCCurrent() ); } } else { dopCurrErrorDurationCtr = 0; } } // dialOut pump should be running else { dopCurr = fabs( getMeasuredDialOutPumpMCCurrent() ); if ( ( dopCurr < DOP_MIN_CURR_WHEN_RUNNING_MA ) || ( dopCurr > DOP_MAX_CURR_WHEN_RUNNING_MA ) ) { dopCurrErrorDurationCtr += TASK_PRIORITY_INTERVAL; if ( dopCurrErrorDurationCtr > DOP_MAX_CURR_ERROR_DURATION_MS ) { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DIAL_OUT_PUMP_MC_CURRENT_CHECK, getMeasuredDialOutPumpMCCurrent() ); } } else { dopCurrErrorDurationCtr = 0; } } } /************************************************************************* * @brief execDialOutUFTest * The execDialOutUFTest function executes the state machine for the \n * DialOutUF self test. * @details * Inputs : none * Outputs : none * @param none * @return the current state of the DialOutUF self test. *************************************************************************/ SELF_TEST_STATUS_T execDialOutUFTest( void ) { SELF_TEST_STATUS_T result = SELF_TEST_STATUS_FAILED; // TODO - implement self test(s) return result; } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /************************************************************************* * @brief testSetDialOutUFDataPublishIntervalOverride * The testSetDialOutUFDataPublishIntervalOverride function overrides the \n * dialOut flow data publish interval. * @details * Inputs : none * Outputs : dialOutFlowDataPublishInterval * @param value : override dialOut flow data publish interval with (in ms) * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetDialOutUFDataPublishIntervalOverride( U32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { U32 intvl = value / TASK_PRIORITY_INTERVAL; result = TRUE; dialOutFlowDataPublishInterval.ovData = intvl; dialOutFlowDataPublishInterval.override = OVERRIDE_KEY; } return result; } /************************************************************************* * @brief testResetDialOutUFDataPublishIntervalOverride * The testResetDialOutUFDataPublishIntervalOverride function resets the override \n * of the dialOut flow data publish interval. * @details * Inputs : none * Outputs : dialOutFlowDataPublishInterval * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetDialOutUFDataPublishIntervalOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; dialOutFlowDataPublishInterval.override = OVERRIDE_RESET; dialOutFlowDataPublishInterval.ovData = dialOutFlowDataPublishInterval.ovInitData; } return result; } /************************************************************************* * @brief testSetTargetDialOutUFRateOverride and testResetTargetDialOutUFRateOverride * The testSetTargetDialOutUFRateOverride function overrides the target \n * dialOut flow rate. \n * The testResetTargetDialOutUFRateOverride function resets the override of the \n * target dialOut flow rate. * @details * Inputs : none * Outputs : targetDialOutUFRate * @param value : override target dialOut flow rate (in mL/min) * @return TRUE if override successful, FALSE if not *************************************************************************/ DATA_OVERRIDE_FUNC( S32, testSetTargetDialOutUFRateOverride, testResetTargetDialOutUFRateOverride, targetDialOutUFRate ) /************************************************************************* * @brief testSetMeasuredDialOutUFLoadOverride and testResetMeasuredDialOutUFLoadOverride * The testSetMeasuredDialOutUFLoadOverride function overrides the measured \n * dialOut load. \n * The testResetMeasuredDialOutUFLoadOverride function resets the override of the \n * measured dialOut load. * @details * Inputs : none * Outputs : measuredDialOutUFLoad * @param value : override measured dialOut flow rate (in mL/min) * @return TRUE if override successful, FALSE if not *************************************************************************/ DATA_OVERRIDE_FUNC( F32, testSetMeasuredDialOutUFLoadOverride, testResetMeasuredDialOutUFLoadOverride, measuredDialOutUFLoad ) /************************************************************************* * @brief testSetMeasuredDialOutPumpRotorSpeedOverride and testResetMeasuredDialOutPumpRotorSpeedOverride * The testSetMeasuredDialOutPumpRotorSpeedOverride function overrides the measured \n * dialOut pump rotor speed. \n * The testResetMeasuredDialOutPumpRotorSpeedOverride function resets the override of the \n * measured dialOut pump rotor speed. * @details * Inputs : none * Outputs : dialOutPumpRotorSpeedRPM * @param value : override measured dialOut pump rotor speed (in RPM) * @return TRUE if override successful, FALSE if not *************************************************************************/ DATA_OVERRIDE_FUNC( F32, testSetMeasuredDialOutPumpRotorSpeedOverride, testResetMeasuredDialOutPumpRotorSpeedOverride, dialOutPumpRotorSpeedRPM ) /************************************************************************* * @brief testSetMeasuredDialOutPumpSpeedOverride and testResetMeasuredDialOutPumpSpeedOverride * The testSetMeasuredDialOutPumpSpeedOverride function overrides the measured \n * dialOut pump motor speed. \n * The testResetMeasuredDialOutPumpSpeedOverride function resets the override of the \n * measured dialOut pump motor speed. * @details * Inputs : none * Outputs : dialOutPumpSpeedRPM * @param value : override measured dialOut pump motor speed (in RPM) * @return TRUE if override successful, FALSE if not *************************************************************************/ DATA_OVERRIDE_FUNC( F32, testSetMeasuredDialOutPumpSpeedOverride, testResetMeasuredDialOutPumpSpeedOverride, dialOutPumpSpeedRPM ) /************************************************************************* * @brief testSetMeasuredDialOutPumpMCSpeedOverride and testResetMeasuredDialOutPumpMCSpeedOverride * The testSetMeasuredDialOutPumpMCSpeedOverride function overrides the measured \n * dialOut pump motor speed. \n * The testResetMeasuredDialOutPumpMCSpeedOverride function resets the override of the \n * measured dialOut pump motor speed. * @details * Inputs : none * Outputs : adcDialOutPumpMCSpeedRPM * @param value : override measured dialOut pump speed (in RPM) * @return TRUE if override successful, FALSE if not *************************************************************************/ DATA_OVERRIDE_FUNC( F32, testSetMeasuredDialOutPumpMCSpeedOverride, testResetMeasuredDialOutPumpMCSpeedOverride, adcDialOutPumpMCSpeedRPM ) /************************************************************************* * @brief testSetMeasuredDialOutPumpMCCurrentOverride and testResetMeasuredDialOutPumpMCCurrentOverride * The testSetMeasuredDialOutPumpMCCurrentOverride function overrides the measured \n * dialOut pump motor current. \n * The testResetMeasuredDialOutPumpMCCurrentOverride function resets the override of the \n * measured dialOut pump motor current. * @details * Inputs : none * Outputs : adcDialOutPumpMCCurrentmA * @param value : override measured dialOut pump current (in mA) * @return TRUE if override successful, FALSE if not *************************************************************************/ DATA_OVERRIDE_FUNC( F32, testSetMeasuredDialOutPumpMCCurrentOverride, testResetMeasuredDialOutPumpMCCurrentOverride, adcDialOutPumpMCCurrentmA )