/************************************************************************** * * Copyright (c) 2020-2020 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 * * @date 22-Jan-2020 * @author S. Nash * * @brief Monitor/Controller for dialysate outlet pump and load cell sensor. * **************************************************************************/ #ifndef _VECTORCAST_ #include #endif #include "etpwm.h" #include "gio.h" #include "mibspi.h" #include "Common.h" #include "FPGA.h" #include "InternalADC.h" #include "OperationModes.h" #include "PIControllers.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "TaskPriority.h" #include "Timers.h" #include "DialOutFlow.h" // ********** private definitions ********** #define DIAL_OUT_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) // interval (ms/task time) at which the dialout vol data is published on the CAN bus #define MAX_DIAL_OUT_FLOW_RATE 650 // mL/min #define MIN_DIAL_OUT_FLOW_RATE 100 // mL/min #define MAX_DIAL_OUT_PUMP_PWM_STEP_CHANGE 0.005 // max duty cycle change when ramping #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 ( 1000 / TASK_GENERAL_INTERVAL ) // interval (ms/task time) at which the dialOut pump is controlled #define DOP_P_COEFFICIENT 0.00005 // P term for dialOut pump control #define DOP_I_COEFFICIENT 0.00015 // I term for dialOut pump control #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_ADC_FULL_SCALE_V 3.0 // DOP analog signals are 0-3V (while int. ADC ref V is 3.3V) #define DOP_ADC_MID_PT_BITS ( (F32)( INT_ADC_FULL_SCALE_BITS >> 1 ) * ( DOP_ADC_FULL_SCALE_V / INT_ADC_REF_V ) ) #define SIGN_FROM_12_BIT_VALUE(v) ( (S16)(v) - (S16)DOP_ADC_MID_PT_BITS ) /*** setDialOutFlowRxTotalVolumeAndRxTime ***/ #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 // dialIn pump motor to dialIn pump gear ratio #define DOP_MOTOR_RPM_TO_PWM_DC_FACTOR 0.00042 // ~24 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 MAX_RX_TOTAL_VOLUME_ML 8000 //#define MIN_RX_TOTAL_VOLUME_ML 100 //#define MAX_UF_RATE_ML_PER_HOUR 2500.0 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 DialOut_Pump_Self_Test_States { DIAL_OUT_PUMP_SELF_TEST_STATE_START = 0, DIAL_OUT_PUMP_TEST_STATE_IN_PROGRESS, DIAL_OUT_PUMP_TEST_STATE_COMPLETE, NUM_OF_DIAL_OUT_PUMP_SELF_TEST_STATES } DIAL_OUT_PUMP_SELF_TEST_STATE_T; // pin assignments and macros for pump stop and direction outputs #define STOP_DO_PUMP_MIBSPI1_PORT_MASK 0x00000400 // (MIBSPI1 SIMO[0] - re-purposed as output GPIO) #define SET_DOP_STOP() {mibspiREG1->PC3 |= STOP_DO_PUMP_MIBSPI1_PORT_MASK;} #define CLR_DOP_STOP() {mibspiREG1->PC3 &= ~STOP_DO_PUMP_MIBSPI1_PORT_MASK;} //#define STOP_DO_PUMP_SPI4_PORT_MASK 0x00000200 // (SPI4CLK - re-purposed as output GPIO) //#define SET_DOP_STOP() {spiREG4->PC3 |= STOP_DO_PUMP_SPI4_PORT_MASK;} //#define CLR_DOP_STOP() {spiREG4->PC3 &= ~STOP_DO_PUMP_SPI4_PORT_MASK;} #define STOP_DO_PUMP_GIO_PORT_PIN 6U #define SET_DOP_DIR() gioSetBit( gioPORTA, STOP_DO_PUMP_GIO_PORT_PIN, PIN_SIGNAL_HIGH ) #define CLR_DOP_DIR() gioSetBit( gioPORTA, STOP_DO_PUMP_GIO_PORT_PIN, PIN_SIGNAL_LOW ) // ********** private data ********** static DIAL_OUT_PUMP_STATE_T dialOutPumpState = DIAL_OUT_PUMP_OFF_STATE; static U32 dialOutFlowDataPublicationTimerCounter = 6; // set non-zero to phase dialout vol data publication to CAN bus static BOOL isDialOutPumpOn = FALSE; static U32 lastGivenRate = 0.0; static F32 dialOutPumpPWMDutyCyclePct = 0.0; static F32 dialOutPumpPWMDutyCyclePctSet = 0.0; static MOTOR_DIR_T dialOutPumpDirection = MOTOR_DIR_FORWARD; static MOTOR_DIR_T dialOutPumpDirectionSet = MOTOR_DIR_FORWARD; static PUMP_CONTROL_MODE_T dialOutPumpControlMode = PUMP_CONTROL_MODE_CLOSED_LOOP; static PUMP_CONTROL_MODE_T dialOutPumpControlModeSet = PUMP_CONTROL_MODE_CLOSED_LOOP; DATA_DECL( U32, DialOutDataPub, DialOutDataPublishInterval, DIAL_OUT_DATA_PUB_INTERVAL, DIAL_OUT_DATA_PUB_INTERVAL ); // interval (in ms) at which to publish dialout vol data to CAN bus DATA_ARRAY_DECL( F32, LoadCellWeightsInGrams, NUM_OF_LOAD_CELLS, loadCellWeightInGrams ); DATA_DECL( F32, TotalTargetDialOutVolInMl, referenceUFVolumeInMl, 0.0, 0.0 ); // target dialout UF vol DATA_DECL( F32, TotalMeasuredUFVolumeInMl, totalMeasuredUFVolumeInMl, 0.0, 0.0 ); // measured dialout UF vol DATA_DECL( F32, MeasuredDialOutPumpMCSpeed, dialOutPumpMCSpeedRPM, 0.0, 0.0 ); // measured dialOut pump motor controller speed DATA_DECL( F32, MeasuredDialOutPumpMCCurrent, dialOutPumpMCCurrentmA, 0.0, 0.0 );// measured dialOut pump motor controller current 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 static U32 dopControlTimerCounter = 0; static U32 dopCurrErrorDurationCtr = 0; static DIAL_OUT_PUMP_SELF_TEST_STATE_T dialOutPumpSelfTestState = DIAL_OUT_PUMP_SELF_TEST_STATE_START; static U32 dialOutPumpSelfTestTimerCount = 0; // Broadcasting variables DIAL_OUT_FLOW_DATA_T dialOutBroadCastVariables; // ********** 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 setDialOutPumpControlSignalPWM( F32 newPWM ); static void stopDialOutPump( void ); static void releaseDialOutPumpStop( void ); static void setDialOutPumpDirection( MOTOR_DIR_T dir ); static void publishDialOutFlowData( void ); //static void checkDialOutPumpDirection( void ); //static void checkDialOutPumpMCCurrent( void ); static DATA_GET_PROTOTYPE( U32, getPublishDialOutDataInterval ); /************************************************************************* * @brief * The initDialOutFlow function initializes the DialOutFlow module. * @details * Inputs : none * Outputs : DialOutFlow module initialized. * @param none * @return none *************************************************************************/ void initDialOutFlow( void ) { U32 i; stopDialOutPump(); setDialOutPumpDirection( MOTOR_DIR_FORWARD ); // 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, MIN_DIAL_OUT_PUMP_PWM_DUTY_CYCLE, MAX_DIAL_OUT_PUMP_PWM_DUTY_CYCLE ); } /************************************************************************* * @brief * The setDialOutPumpTargetRate function sets a new target flow rate, pump \n * direction, and control mode. * @details * Inputs : isDialOutPumpOn, dialOutPumpDirectionSet * Outputs : targetDialOutFlowRate, dialOutPumpdirection, dialOutPumpPWMDutyCyclePct * @param flowRate : new target dialysate outlet flow rate * @param dir : new dialysate outlet flow direction * @param mode : new control mode * @return TRUE if new flow rate & dir are set, FALSE if not *************************************************************************/ BOOL setDialOutPumpTargetRate( U32 flowRate, MOTOR_DIR_T dir, PUMP_CONTROL_MODE_T mode ) { 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 ) { lastGivenRate = flowRate; dialOutPumpDirection = dir; dialOutPumpControlMode = mode; // set PWM duty cycle target to an estimated initial target to ramp to based on target flow rate - then we'll control to flow when ramp completed dialOutPumpPWMDutyCyclePct = DOP_PWM_FROM_ML_PER_MIN((F32)flowRate); 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 { // TODO - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_DIAL_OUT_FLOW_SET_TOO_HIGH, flowRate ) } } return result; } /************************************************************************* * @brief * The setDialOutUFVolumes function sets the ultrafiltration reference and \n * measured total volumes (in mL). * @details * Inputs : none * Outputs : referenceUFVolumeInMl and totalMeasuredUFVolumeInMl * @param refVol : New ultrafiltration reference volume (in mL). * @param totVol : New ultrafiltration total volume (in mL). * @return none *************************************************************************/ void setDialOutUFVolumes( F32 refVol, F32 totVol ) { referenceUFVolumeInMl.data = refVol; totalMeasuredUFVolumeInMl.data = totVol; } /************************************************************************* * @brief * The signalDialOutPumpHardStop function stops the dialysate outlet pump \n * immediately. * @details * Inputs : none * Outputs : Dialysate outlet pump stopped, set point reset, state changed to off * @param none * @return none *************************************************************************/ void signalDialOutPumpHardStop( void ) { lastGivenRate = 0; stopDialOutPump(); dialOutPumpState = DIAL_OUT_PUMP_OFF_STATE; dialOutPumpPWMDutyCyclePct = 0.0; dopControlTimerCounter = 0; resetPIController( PI_CONTROLLER_ID_ULTRAFILTRATION, MIN_DIAL_OUT_PUMP_PWM_DUTY_CYCLE ); } /************************************************************************* * @brief * The setDialOutUFVolumes function sets the ultrafiltration reference and \n * measured total volumes (in mL). * @details * Inputs : none * 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. * @param res2Backup : New weight from backup load cell of reservoir 2. * @return none *************************************************************************/ void setNewLoadCellReadings( F32 res1Primary, F32 res1Backup, F32 res2Primary, F32 res2Backup ) { loadCellWeightInGrams[ LOAD_CELL_RESERVOIR_1_PRIMARY ].data = res1Primary; loadCellWeightInGrams[ LOAD_CELL_RESERVOIR_1_BACKUP ].data = res1Backup; loadCellWeightInGrams[ LOAD_CELL_RESERVOIR_2_PRIMARY ].data = res2Primary; loadCellWeightInGrams[ LOAD_CELL_RESERVOIR_2_BACKUP ].data = res2Backup; } /************************************************************************* * @brief execDialOutFlowMonitor * The execDialOutFlowMonitor function executes the dialout vol monitor. * @details * Inputs : none * Outputs : measuredDialOutFlowRate, dialOutPumpMCSpeedRPM, dialOutPumpMCCurrentmA * @param none * @return none *************************************************************************/ void execDialOutFlowMonitor( void ) { U16 bpRPM = getIntADCReading( INT_ADC_DIAL_OUT_PUMP_SPEED ); U16 bpmA = getIntADCReading( INT_ADC_DIAL_OUT_PUMP_MOTOR_CURRENT ); dialOutPumpMCSpeedRPM.data = (F32)(SIGN_FROM_12_BIT_VALUE(bpRPM)) * DOP_SPEED_ADC_TO_RPM_FACTOR; dialOutPumpMCCurrentmA.data = (F32)(SIGN_FROM_12_BIT_VALUE(bpmA)) * DOP_CURRENT_ADC_TO_MA_FACTOR; // TODO - checks publishDialOutFlowData(); } /************************************************************************* * @brief execDialOutFlowController * The execDialOutFlowController function executes the dialout vol controller. * @details * Inputs : dialOutPumpState * Outputs : dialOutPumpState * @param none * @return none *************************************************************************/ void execDialOutFlowController( 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 : targetDialOutFlowRate, 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 ( lastGivenRate > 0 ) { // set initial PWM duty cycle dialOutPumpPWMDutyCyclePctSet = DOP_PWM_ZERO_OFFSET + MAX_DIAL_OUT_PUMP_PWM_STEP_CHANGE; setDialOutPumpControlSignalPWM( dialOutPumpPWMDutyCyclePctSet ); // allow dialOut pump to run in requested direction setDialOutPumpDirection( dialOutPumpDirection ); releaseDialOutPumpStop(); 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 ( dialOutPumpPWMDutyCyclePct < NEARLY_ZERO ) { // start ramp down to stop dialOutPumpPWMDutyCyclePctSet -= MAX_DIAL_OUT_PUMP_PWM_STEP_CHANGE; setDialOutPumpControlSignalPWM( dialOutPumpPWMDutyCyclePctSet ); result = DIAL_OUT_PUMP_RAMPING_DOWN_STATE; } // have we reached end of ramp up? else if ( dialOutPumpPWMDutyCyclePctSet >= dialOutPumpPWMDutyCyclePct ) { resetPIController( PI_CONTROLLER_ID_ULTRAFILTRATION, dialOutPumpPWMDutyCyclePctSet ); dialOutPumpControlModeSet = dialOutPumpControlMode; // if open loop mode, set PWM to requested duty cycle where it will stay during control state if ( dialOutPumpControlModeSet == PUMP_CONTROL_MODE_OPEN_LOOP ) { dialOutPumpPWMDutyCyclePctSet = dialOutPumpPWMDutyCyclePct; setDialOutPumpControlSignalPWM( dialOutPumpPWMDutyCyclePct ); } result = DIAL_OUT_PUMP_CONTROL_TO_TARGET_STATE; } // continue ramp up else { dialOutPumpPWMDutyCyclePctSet += MAX_DIAL_OUT_PUMP_PWM_STEP_CHANGE; setDialOutPumpControlSignalPWM( dialOutPumpPWMDutyCyclePctSet ); } 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 ) { resetPIController( PI_CONTROLLER_ID_ULTRAFILTRATION, dialOutPumpPWMDutyCyclePctSet ); dialOutPumpControlModeSet = dialOutPumpControlMode; // if open loop mode, set PWM to requested duty cycle where it will stay during control state if ( dialOutPumpControlModeSet == PUMP_CONTROL_MODE_OPEN_LOOP ) { dialOutPumpPWMDutyCyclePctSet = dialOutPumpPWMDutyCyclePct; setDialOutPumpControlSignalPWM( dialOutPumpPWMDutyCyclePct ); } result = DIAL_OUT_PUMP_CONTROL_TO_TARGET_STATE; } // continue ramp down else { dialOutPumpPWMDutyCyclePctSet -= MAX_DIAL_OUT_PUMP_PWM_STEP_CHANGE; setDialOutPumpControlSignalPWM( dialOutPumpPWMDutyCyclePctSet ); } 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; // control at set interval if ( ++dopControlTimerCounter >= DOP_CONTROL_INTERVAL ) { if ( dialOutPumpControlModeSet == PUMP_CONTROL_MODE_CLOSED_LOOP ) { F32 refVol = getTotalTargetDialOutUFVolumeInMl(); F32 totVol = getTotalMeasuredUFVolumeInMl(); F32 newPWM; newPWM = runPIController( PI_CONTROLLER_ID_ULTRAFILTRATION, refVol, totVol ); dialOutPumpPWMDutyCyclePctSet = newPWM; setDialOutPumpControlSignalPWM( newPWM ); } dopControlTimerCounter = 0; } return result; } /************************************************************************* * @brief * The setDialOutPumpControlSignalPWM function set the PWM of the dialysate \n * outlet pump. * * @param newPWM a fraction of between 0.0 and 1.0. * @return none *************************************************************************/ static void setDialOutPumpControlSignalPWM( F32 newPWM ) { etpwmSetCmpA( etpwmREG3, (U16)( FLOAT_TO_INT_WITH_ROUND( newPWM * (F32)( etpwmREG3->TBPRD ) ) ) ); } /************************************************************************* * @brief stopDialOutPump * 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 * @param none * @return none *************************************************************************/ static void stopDialOutPump( void ) { setDialOutPumpControlSignalPWM( 0 ); SET_DOP_STOP(); isDialOutPumpOn = FALSE; } /************************************************************************* * @brief * The releaseDialOutPumpStop function clears the dialysate outlet pump stop signal. * @details * Inputs : none * Outputs : dialysate outlet pump stop signal * @param none * @return none *************************************************************************/ static void releaseDialOutPumpStop( void ) { CLR_DOP_STOP(); } /************************************************************************* * @brief setDialOutPumpDirection * The setDialOutPumpDirection function sets the set dialIn pump direction to \n * the given direction. * @details * Inputs : dialOutPumpState * Outputs : dialOutPumpState * @param dir : dialIn 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 publishDialOutFlowData * The publishDialOutFlowData function publishes dialout vol data at the set \n * interval. * @details * Inputs : target flow rate, measured flow rate, measured MC speed, \n * measured MC current * Outputs : dialout vol data is published to CAN bus. * @param none * @return none *************************************************************************/ static void publishDialOutFlowData( void ) { // publish dialysate outlet pump and UF volume data on interval if ( ++dialOutFlowDataPublicationTimerCounter > DIAL_OUT_DATA_PUB_INTERVAL ) { dialOutBroadCastVariables.refUFVolMl = getTotalTargetDialOutUFVolumeInMl(); dialOutBroadCastVariables.measUFVolMl = getTotalMeasuredUFVolumeInMl(); dialOutBroadCastVariables.measRotSpdRPM = getMeasuredDialOutPumpRotorSpeed(); dialOutBroadCastVariables.measSpdRPM = getMeasuredDialOutPumpSpeed(); dialOutBroadCastVariables.measMCSpdRPM = getMeasuredDialOutPumpMCSpeed(); dialOutBroadCastVariables.measMCCurrmA = getMeasuredDialOutPumpMCCurrent(); dialOutBroadCastVariables.setPWMpct = dialOutPumpPWMDutyCyclePctSet * FRACTION_TO_PERCENT_FACTOR; broadcastDialOutFlowData( &dialOutBroadCastVariables); dialOutFlowDataPublicationTimerCounter = 0; } } /************************************************************************* * GET SUPPORT FUNCTIONS *************************************************************************/ /************************************************************************* * @brief * The getPublishDialOutFlowDataInterval function gets the dialysate out flow \n * data publication interval. * @details * Inputs : DialOutDataPublishInterval * Outputs : none * @param none * @return the current dialysate out flow data publication interval (in ms). *************************************************************************/ DATA_GET( U32, getPublishDialOutFlowDataInterval, DialOutDataPublishInterval ) /************************************************************************* * @brief * The getLoadCellWeightInGrams function gets the load cell weight. * @details * Inputs : loadCellWeightInGrams * Outputs : none * @param loadCellID : ID of load cell to get * @return the current load cell weight in grams *************************************************************************/ DATA_ARRAY_GET( F32, getLoadCellWeightInGrams, loadCellID, NUM_OF_LOAD_CELLS - 1, loadCellWeightInGrams, 0.0 ) /************************************************************************* * @brief * The getTotalTargetDialOutUFVolumeInMl function gets the target UF volume. * @details * Inputs : referenceUFVolumeInMl * Outputs : none * @param none * @return the current target UF volume in mL. *************************************************************************/ DATA_GET( F32, getTotalTargetDialOutUFVolumeInMl, referenceUFVolumeInMl ) /************************************************************************* * @brief * The getTotalMeasuredUFVolumeInMl function gets the measured UF volume. * @details * Inputs : totalMeasuredUFVolumeInMl * Outputs : none * @param none * @return the current UF volume (in mL). *************************************************************************/ DATA_GET( F32, getTotalMeasuredUFVolumeInMl, totalMeasuredUFVolumeInMl ) /************************************************************************* * @brief * The getMeasuredDialOutPumpRotorSpeed function gets the measured dialysate \n * outlet pump rotor speed. * @details * Inputs : dialOutPumpRotorSpeedRPM * Outputs : none * @param none * @return the current dialysate outlet pump rotor speed (in RPM). *************************************************************************/ DATA_GET( F32, getMeasuredDialOutPumpRotorSpeed, dialOutPumpRotorSpeedRPM ) /************************************************************************* * @brief * The getMeasuredDialOutPumpSpeed function gets the measured dialysate outlet \n * pump motor speed. * @details * Inputs : dialOutPumpSpeedRPM * Outputs : none * @param none * @return the current dialysate outlet pump motor speed (in RPM). *************************************************************************/ DATA_GET( F32, getMeasuredDialOutPumpSpeed, dialOutPumpSpeedRPM ) /************************************************************************* * @brief * The getMeasuredDialOutPumpMCSpeed function gets the measured dialOut pump \n * speed. * @details * Inputs : dialOutPumpMCSpeedRPM * Outputs : none * @param none * @return the current dialOut pump speed (in RPM). *************************************************************************/ DATA_GET( F32, getMeasuredDialOutPumpMCSpeed, dialOutPumpMCSpeedRPM ) /************************************************************************* * @brief * The getMeasuredDialOutPumpMCCurrent function gets the measured dialOut pump \n * current. * @details * Inputs : dialOutPumpMCCurrentmA * Outputs : none * @param none * @return the current dialOut pump current (in mA). *************************************************************************/ DATA_GET( F32, getMeasuredDialOutPumpMCCurrent, dialOutPumpMCCurrentmA) /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /************************************************************************* * @brief * The testSetDialOutPumpAndLoadCellDataPublishIntervalOverride function overrides the \n * dialout vol data publish interval. * @details * Inputs : none * Outputs : DialOutDataPublishInterval * @param value : override dialout vol data publish interval with (in ms) * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetDialOutPumpAndLoadCellDataPublishIntervalOverride( U32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { U32 intvl = value / TASK_PRIORITY_INTERVAL; result = TRUE; DialOutDataPublishInterval.ovData = intvl; DialOutDataPublishInterval.override = OVERRIDE_KEY; } return result; } /************************************************************************* * @brief * The testResetDialOutPumpAndLoadCellDataPublishIntervalOverride function resets the override \n * of the dialout vol data publish interval. * @details * Inputs : none * Outputs : DialOutDataPublishInterval * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetDialOutPumpAndLoadCellDataPublishIntervalOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; DialOutDataPublishInterval.override = OVERRIDE_RESET; DialOutDataPublishInterval.ovData = DialOutDataPublishInterval.ovInitData; } return result; } /************************************************************************* * @brief * The testSetDialOutUFRefVolumeOverride function overrides the target \n * dialout vol rate. \n * The testResetDialOutUFRefVolumeOverride function resets the override of the \n * target dialout vol rate. * @details * Inputs : none * Outputs : TotalTargetDialOutVolInMl * @param value : override target dialout vol rate (in mL/min) * @return TRUE if override successful, FALSE if not *************************************************************************/ DATA_OVERRIDE_FUNC( F32, testSetDialOutUFRefVolumeOverride, testResetDialOutUFRefVolumeOverride, referenceUFVolumeInMl ) /************************************************************************* * @brief * The testSetDialOutUFTotVolumeOverride function overrides the measured \n * dialout vol rate. \n * The testResetDialOutUFTotVolumeOverride function resets the override of the \n * measured dialout vol rate. * @details * Inputs : none * Outputs : totalMeasuredUFVolumeInMl * @param value : override measured dialout vol rate (in mL/min) * @return TRUE if override successful, FALSE if not *************************************************************************/ DATA_OVERRIDE_FUNC( F32, testSetDialOutUFTotVolumeOverride, testResetDialOutUFTotVolumeOverride, totalMeasuredUFVolumeInMl ) /************************************************************************* * @brief testSetMeasuredDialOutPumpRotorSpeedOverride and testResetMeasuredDialOutPumpRotorSpeedOverride * The testSetMeasuredDialOutPumpRotorSpeedOverride function overrides the measured \n * dialIn pump rotor speed. \n * The testResetMeasuredDialOutPumpRotorSpeedOverride function resets the override of the \n * measured dialIn pump rotor speed. * @details * Inputs : none * Outputs : DialOutPumpRotorSpeedRPM * @param value : override measured dialIn 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 * dialIn pump motor speed. \n * The testResetMeasuredDialOutPumpSpeedOverride function resets the override of the \n * measured dialIn pump motor speed. * @details * Inputs : none * Outputs : DialOutPumpSpeedRPM * @param value : override measured dialIn 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 * dialIn pump motor speed. \n * The testResetMeasuredDialOutPumpMCSpeedOverride function resets the override of the \n * measured dialIn pump motor speed. * @details * Inputs : none * Outputs : dialOutPumpMCSpeedRPM * @param value : override measured dialIn pump speed (in RPM) * @return TRUE if override successful, FALSE if not *************************************************************************/ DATA_OVERRIDE_FUNC( F32, testSetMeasuredDialOutPumpMCSpeedOverride, testResetMeasuredDialOutPumpMCSpeedOverride, dialOutPumpMCSpeedRPM ) /************************************************************************* * @brief testSetMeasuredDialOutPumpMCCurrentOverride and testResetMeasuredDialOutPumpMCCurrentOverride * The testSetMeasuredDialOutPumpMCCurrentOverride function overrides the measured \n * dialIn pump motor current. \n * The testResetMeasuredDialOutPumpMCCurrentOverride function resets the override of the \n * measured dialIn pump motor current. * @details * Inputs : none * Outputs : dialOutPumpMCCurrentmA * @param value : override measured dialIn pump current (in mA) * @return TRUE if override successful, FALSE if not *************************************************************************/ DATA_OVERRIDE_FUNC( F32, testSetMeasuredDialOutPumpMCCurrentOverride, testResetMeasuredDialOutPumpMCCurrentOverride, dialOutPumpMCCurrentmA ) /************************************************************************* * @brief * The testSetDialOutLoadCellWeightOverride function overrides the value of the \n * load cell sensor with a given weight (in grams). \n * The testResetDialOutLoadCellWeightOverride function resets the override of the \n * load cell sensor. * @details * Inputs : none * 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 *************************************************************************/ DATA_ARRAY_OVERRIDE_FUNC( F32, testSetDialOutLoadCellWeightOverride, testResetDialOutLoadCellWeightOverride, loadCellWeightInGrams, sensor, NUM_OF_LOAD_CELLS-1 )