/************************************************************************** * * Copyright (c) 2020-2022 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 DrainPump.c * * @author (last) Dara Navaei * @date (last) 11-Jul-2022 * * @author (original) Sean * @date (original) 08-Apr-2020 * ***************************************************************************/ #include #include "etpwm.h" #include "mibspi.h" #include "DrainPump.h" #include "FPGA.h" #include "MessageSupport.h" #include "NVDataMgmt.h" #include "OperationModes.h" #include "PersistentAlarm.h" #include "PIControllers.h" #include "Pressures.h" #include "SafetyShutdown.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "TaskPriority.h" #include "Timers.h" #include "Valves.h" #ifdef EMC_TEST_BUILD #include "Heaters.h" #endif /** * @addtogroup DrainPump * @{ */ // ********** private definitions ********** #define DRAIN_PUMP_MIN_DAC GET_RPM_2_DAC_CONVERSION( MIN_DRAIN_PUMP_RPM ) ///< Drain pump minimum RPM to DAC conversion. #define DRAIN_PUMP_MAX_DAC GET_RPM_2_DAC_CONVERSION( MAX_DRAIN_PUMP_RPM ) ///< Drain pump maximum RPM to DAC conversion. #define DRAIN_PUMP_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Interval (ms/task time) at which the Drain Pump data is published on the CAN bus. #define DRP_CONTROL_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the Drain pump is controlled. TODO original one is 1 second #define RPM_2_DAC_SLOPE 0.0547F ///< RPM to DAC conversion slope. #define RPM_2_DAC_INTERCEPT 2.9968F ///< RPM to DAC conversion intercept. #define GET_RPM_2_DAC_CONVERSION(rpm) ( ( RPM_2_DAC_SLOPE * rpm ) - RPM_2_DAC_INTERCEPT + \ FLOAT_TO_INT_ROUNDUP_OFFSET ) ///< RPM to DAC conversion equation. #define TOGGLE_PERIOD_RESOLUTION_SECONDS 0.000005F ///< Toggle period to resolution in seconds. #define ROTATIONAL_TO_TOGGLE_PERIOD_CONVERSION 4.0F ///< Rotational to toggle period conversion coefficient. #define DRAIN_PUMP_P_COEFFICIENT 0.5F ///< P term for drain pump delta pressure control. #define DRAIN_PUMP_I_COEFFICIENT 1.0F ///< I term for drain pump delta pressure control. #define MIN_ALLOWED_TARGET_OUTLET_PRESSURE -15.0F ///< Minimum allowed outlet pressure for closed loop control. #define MAX_ALLOWED_TARGET_OUTLET_PRESSURE 15.0F ///< Maximum allowed outlet pressure for closed loop control. #define MAX_ALLOWED_OPEN_LOOP_RPM_OUT_OF_RANGE 100 ///< Maximum allowed RPM out of range from target RPM in open loop. #define OPEN_LOOP_RPM_OUT_OF_RANGE_TIME_OUT ( 10 * MS_PER_SECOND ) ///< Open loop RPM out of range time out in ms. #define DRAIN_PUMP_ENABLE_SPI3_PORT_MASK 0x00000020 ///< CS5 - Out put GPIO for pump enable. #define SET_DRAIN_PUMP_ENABLE() {mibspiREG3->PC3 |= DRAIN_PUMP_ENABLE_SPI3_PORT_MASK;} ///< Drain pump enable set macro. #define CLR_DRAIN_PUMP_ENABLE() {mibspiREG3->PC3 &= ~DRAIN_PUMP_ENABLE_SPI3_PORT_MASK;} ///< Drain pump enable clear macro. #define SAFETY_SHUTDOWN_TIMEOUT ( 1 * MS_PER_SECOND ) ///< Drain pump safety shutdown activation timeout. #define DRAIN_PUMP_OFF_RPM_ADC_COUNT 0xFFFF ///< ADC count value when pump is off. #define DATA_PUBLISH_COUNTER_START_COUNT 60 ///< Data publish counter start count. /// Enumeration of drain pump states. typedef enum DrainPump_States { DRAIN_PUMP_OFF_STATE = 0, ///< Drain pump off state DRAIN_PUMP_CONTROL_TO_TARGET_STATE, ///< Drain pump control to target state DRAIN_PUMP_OPEN_LOOP_STATE, ///< Drain pump open loop state NUM_OF_DRAIN_PUMP_STATES ///< Number of drain pump states } DRAIN_PUMP_STATE_T; /// Enumeration of drain pump self-test states. typedef enum DrainPump_Self_Test_States { DRAIN_PUMP_SELF_TEST_STATE_START = 0, ///< Drain pump self-test start state DRAIN_PUMP_TEST_STATE_IN_PROGRESS, ///< Drain pump self-test in progress state DRAIN_PUMP_TEST_STATE_COMPLETE, ///< Drain pump self-test completed state NUM_OF_DRAIN_PUMP_SELF_TEST_STATES ///< Number of drain pump self-test states } DRAIN_PUMP_SELF_TEST_STATE_T; // ********** private data ********** static DRAIN_PUMP_STATE_T drainPumpState = DRAIN_PUMP_OFF_STATE; ///< Current state of drain pump controller state machine. static U32 drainPumpDataPublicationTimerCounter; ///< Used to schedule drain pump data publication to CAN bus. static U32 drainPumpDAC = 0; ///< Initial drain pump DAC value. static U32 drainPumpDACSet = 0; ///< Currently set drain pump DAC value. static PUMP_CONTROL_MODE_T drainPumpControlMode = NUM_OF_PUMP_CONTROL_MODES; ///< Requested drain pump control mode. static PUMP_CONTROL_MODE_T drainPumpControlModeSet = PUMP_CONTROL_MODE_CLOSED_LOOP; ///< Currently set drain pump control mode. static OVERRIDE_U32_T drainPumpDataPublishInterval = { DRAIN_PUMP_DATA_PUB_INTERVAL, DRAIN_PUMP_DATA_PUB_INTERVAL, 0, 0 }; ///< Interval (in ms) at which to publish drain pump data to CAN bus. static U32 targetDrainPumpRPM = 0; ///< Target drain pump RPM. static F32 targetDrainPumpOutletPressure = 0.0; ///< Target outlet pressure for the drain pump. static U32 drainControlTimerCounter = 0; ///< Determines when to perform control on drain pump. static BOOL hasClosedLoopBeenRequested = FALSE; ///< Closed loop pump control flag. static OVERRIDE_U32_T drainPumpMeasuredRPM = { 0, 0, 0, 0 }; ///< Measured drain pump RPM from feedback. static BOOL signalNewRPMRequest = FALSE; ///< Signal flag the indicates there is a new RPM request. static DRAIN_PUMP_STATE_T pendingDrainPumpCmd = DRAIN_PUMP_OFF_STATE; ///< Delayed (pending) drain pump command. static F32 pendingDrainPumpCmdTarget = 0.0; ///< Delayed (pending) drain pump command target (rpm or PSI depending on command). static U32 pendingDrainPumpCmdCountDown = 0; ///< Delayed (pending) drain pump command count down timer (in task intervals). static DG_DRAIN_LINE_VOLUME_T drainLineVolumeRecord; ///< Drain line volume record. static DG_DRAIN_PUMP_CAL_RECORD_T drainPumpCalRecord; ///< Drain pump calibration record. /// ADC to RPM conversion coefficient or RPM to ADC conversion. static const F32 CONVERSION_COEFF = (F32) SEC_PER_MIN / ( 2.0F * TOGGLE_PERIOD_RESOLUTION_SECONDS * ROTATIONAL_TO_TOGGLE_PERIOD_CONVERSION ); // ********** private function prototypes ********** static DRAIN_PUMP_STATE_T handleDrainPumpOffState( void ); static DRAIN_PUMP_STATE_T handleDrainPumpControlToTargetState( void ); static DRAIN_PUMP_STATE_T handleDrainPumpOpenLoopState( void ); static void stopDrainPump( void ); static void publishDrainPumpData( void ); /*********************************************************************//** * @brief * The initDrainPump function initializes the DrainPump module. * @details Inputs: none * @details Outputs: hasClosedLoopBeenRequested, signalNewRPMRequest * @return none *************************************************************************/ void initDrainPump( void ) { stopDrainPump(); hasClosedLoopBeenRequested = FALSE; signalNewRPMRequest = FALSE; drainPumpDataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; // Initialize the drain pump PI controller initializePIController( PI_CONTROLLER_ID_DRAIN_PUMP, DRAIN_PUMP_MIN_DAC, DRAIN_PUMP_P_COEFFICIENT, DRAIN_PUMP_I_COEFFICIENT, DRAIN_PUMP_MIN_DAC, DRAIN_PUMP_MAX_DAC ); // Initialize the persistent alarm for open loop RPM out of range initPersistentAlarm( ALARM_ID_DRAIN_PUMP_RPM_OUT_OF_RANGE, OPEN_LOOP_RPM_OUT_OF_RANGE_TIME_OUT, OPEN_LOOP_RPM_OUT_OF_RANGE_TIME_OUT ); // Initialize the persistent alarm for RPM not to be less than the min RPM when the pump is off initPersistentAlarm( ALARM_ID_DRAIN_PUMP_OFF_FAULT, SAFETY_SHUTDOWN_TIMEOUT, SAFETY_SHUTDOWN_TIMEOUT ); } /*********************************************************************//** * @brief * The setDrainPumpTargetSpeed function sets a new target RPM for the * drain pump. * @details Inputs: none * @details Outputs: drainPumpDAC, targetDrainPumpRPM, drainPumpControlMode, * drainPumpControlModeSet, signalNewRPMRequest * @param rpm new drain pump target RPM * @return TRUE if new target RPM is set, FALSE if not *************************************************************************/ BOOL setDrainPumpTargetRPM( U32 rpm ) { BOOL result = FALSE; if ( ( 0 == rpm ) || ( ( rpm >= MIN_DRAIN_PUMP_RPM ) && ( rpm <= MAX_DRAIN_PUMP_RPM ) ) ) { drainPumpDAC = (U32)GET_RPM_2_DAC_CONVERSION(rpm); targetDrainPumpRPM = rpm; drainPumpControlMode = PUMP_CONTROL_MODE_OPEN_LOOP; drainPumpControlModeSet = drainPumpControlMode; signalNewRPMRequest = TRUE; // If this function was called, delayed command does not need to be executed // so the pending count down is zeroed. pendingDrainPumpCmdCountDown = 0; result = TRUE; } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_DRAIN_PUMP_INVALID_RPM_SELECTED, rpm ) } return result; } /*********************************************************************//** * @brief * The setDrainPumpTargetRPMDelayed function sets a new target RPM for the * drain pump with delayed start. * @details Inputs: drainPumpDAC, targetDrainPumpSpeed, drainPumpControlMode, * drainPumpControlModeSet * @details Outputs: pendingDrainPumpCmd, pendingDrainPumpCmdTarget, pendingDrainPumpCmdCountDown * @param rpm new drain pump target RPM * @param delayMs delay duration (in ms) before drain pump started * @return TRUE if new target RPM is set, FALSE if not *************************************************************************/ BOOL setDrainPumpTargetRPMDelayed( U32 rpm, U32 delayMs ) { BOOL result = FALSE; if ( ( 0 == rpm ) || ( ( rpm >= MIN_DRAIN_PUMP_RPM ) && ( rpm <= MAX_DRAIN_PUMP_RPM ) ) ) { pendingDrainPumpCmd = DRAIN_PUMP_OPEN_LOOP_STATE; pendingDrainPumpCmdTarget = (F32)rpm; pendingDrainPumpCmdCountDown = delayMs / TASK_GENERAL_INTERVAL; result = TRUE; } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_DRAIN_PUMP_INVALID_RPM_SELECTED, rpm ) } return result; } /*********************************************************************//** * @brief * The setDrainPumpTargetOutletPressure function sets the drain pump to start * with given target PDr pressure. * @details Inputs: targetDrainPumpDeltaPressure, hasClosedLoopBeenRequested, * drainPumpDAC, drainPumpControlMode, drainPumpControlModeSet * @details Outputs: targetDrainPumpDeltaPressure, hasClosedLoopBeenRequested, * drainPumpDAC, drainPumpControlMode, drainPumpControlModeSet * @param pressure new target drain pump outlet pressure * @return TRUE if new target speed is set, FALSE if not *************************************************************************/ BOOL setDrainPumpTargetOutletPressure( F32 pressure ) { BOOL result = FALSE; // Check the delta pressure is in range if ( ( pressure >= MIN_ALLOWED_TARGET_OUTLET_PRESSURE ) && ( pressure <= MAX_ALLOWED_TARGET_OUTLET_PRESSURE ) ) { // Set all the variables for closed loop mode targetDrainPumpOutletPressure = pressure; hasClosedLoopBeenRequested = TRUE; drainPumpDAC = DRAIN_PUMP_MIN_DAC; drainPumpControlMode = PUMP_CONTROL_MODE_CLOSED_LOOP; drainPumpControlModeSet = drainPumpControlMode; result = TRUE; } else { SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_DRAIN_PUMP_INVALID_DELTA_PRESSURE_SELECTED, pressure ) } return result; } /*********************************************************************//** * @brief * The setDrainPumpTargetOutletPressureDelayed function sets the drain pump * to start with given target PDr pressure after given delay. * @details Inputs: targetDrainPumpDeltaPressure, hasClosedLoopBeenRequested, * drainPumpDAC, drainPumpControlMode, drainPumpControlModeSet * @details Outputs: targetDrainPumpDeltaPressure, hasClosedLoopBeenRequested, * drainPumpDAC, drainPumpControlMode, drainPumpControlModeSet * @param pressure new target drain pump outlet pressure * @param delayMS delay duration (in ms) before drain pump started * @return TRUE if new target speed is set, FALSE if not *************************************************************************/ BOOL setDrainPumpTargetOutletPressureDelayed( F32 pressure, U32 delayMs ) { BOOL result = FALSE; // Check the delta pressure is in range if ( ( pressure >= MIN_ALLOWED_TARGET_OUTLET_PRESSURE ) && ( pressure <= MAX_ALLOWED_TARGET_OUTLET_PRESSURE ) ) { pendingDrainPumpCmd = DRAIN_PUMP_CONTROL_TO_TARGET_STATE; pendingDrainPumpCmdTarget = pressure; pendingDrainPumpCmdCountDown = delayMs / TASK_GENERAL_INTERVAL; result = TRUE; } else { SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_DRAIN_PUMP_INVALID_DELTA_PRESSURE_SELECTED, pressure ) } return result; } /*********************************************************************//** * @brief * The signalDrainPumpHardStop function stops the Drain pump immediately. * @details Inputs: none * @details Outputs: targetDrainPumpRPM, drainPumpState, drainPumpControlMode, * hasClosedLoopBeenRequested, drainControlTimerCounter, drainPumpControlModeSet * @return none *************************************************************************/ void signalDrainPumpHardStop( void ) { stopDrainPump(); // Reset all the variables to stop mode targetDrainPumpRPM = 0; drainPumpState = DRAIN_PUMP_OFF_STATE; hasClosedLoopBeenRequested = FALSE; drainPumpControlMode = PUMP_CONTROL_MODE_CLOSED_LOOP; drainPumpControlModeSet = drainPumpControlMode; drainControlTimerCounter = 0; pendingDrainPumpCmd = DRAIN_PUMP_OFF_STATE; pendingDrainPumpCmdTarget = 0.0; pendingDrainPumpCmdCountDown = 0; } /*********************************************************************//** * @brief * The execDrainPumpMonitor function executes the drain pump monitor. * RPM = ( 1 / ADC ) * conversion coefficient. * ADC = ( 1 / RPM ) * conversion coefficient. * @details Inputs: drainPumpControlModeSet, drainPumpState * @details Outputs: drainPumpMeasuredRPM * @return none *************************************************************************/ void execDrainPumpMonitor( void ) { U16 fpgaADCSpeedCount = getFPGADrainPumpSpeed(); drainPumpMeasuredRPM.data = ( DRAIN_PUMP_OFF_RPM_ADC_COUNT == fpgaADCSpeedCount ? 0 : ( CONVERSION_COEFF / fpgaADCSpeedCount ) ); #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_DRAIN_PUMP_MONITOR ) != SW_CONFIG_ENABLE_VALUE ) #endif { // Check if the pump is in off state and the RPM is greater than the minimum RPM if ( DRAIN_PUMP_OFF_STATE == drainPumpState ) { BOOL isRPMTooHigh = ( getDrainPumpMeasuredRPM() > MIN_DRAIN_PUMP_RPM ? TRUE : FALSE ); checkPersistentAlarm( ALARM_ID_DRAIN_PUMP_RPM_OUT_OF_RANGE, FALSE, getDrainPumpMeasuredRPM(), MAX_ALLOWED_OPEN_LOOP_RPM_OUT_OF_RANGE ); checkPersistentAlarm( ALARM_ID_DRAIN_PUMP_OFF_FAULT, isRPMTooHigh, getDrainPumpMeasuredRPM(), MIN_DRAIN_PUMP_RPM ); // If the off fault alarm has become active, trigger the safety shutdown if ( TRUE == isAlarmActive( ALARM_ID_DRAIN_PUMP_OFF_FAULT ) ) { activateSafetyShutdown(); } } // The RPM is only checked in open loop state that the pump is run at a fixed RPM. else if ( DRAIN_PUMP_OPEN_LOOP_STATE == drainPumpState ) { // Using abs since the read RPM can be above or below the target U32 rpmDiff = abs( getDrainPumpTargetRPM() - getDrainPumpMeasuredRPM() ); BOOL isRPMOutOfRange = ( rpmDiff > MAX_ALLOWED_OPEN_LOOP_RPM_OUT_OF_RANGE ? TRUE : FALSE ); checkPersistentAlarm( ALARM_ID_DRAIN_PUMP_RPM_OUT_OF_RANGE, isRPMOutOfRange, getDrainPumpMeasuredRPM(), MAX_ALLOWED_OPEN_LOOP_RPM_OUT_OF_RANGE ); checkPersistentAlarm( ALARM_ID_DRAIN_PUMP_OFF_FAULT, FALSE, getDrainPumpMeasuredRPM(), MIN_DRAIN_PUMP_RPM ); } else { // There are not out of range conditions, clear the alarms checkPersistentAlarm( ALARM_ID_DRAIN_PUMP_RPM_OUT_OF_RANGE, FALSE, getDrainPumpMeasuredRPM(), MAX_ALLOWED_OPEN_LOOP_RPM_OUT_OF_RANGE ); checkPersistentAlarm( ALARM_ID_DRAIN_PUMP_OFF_FAULT, FALSE, getDrainPumpMeasuredRPM(), MIN_DRAIN_PUMP_RPM ); } } // Publish drain pump data on interval publishDrainPumpData(); } /*********************************************************************//** * @brief * The execDrainPumpController function executes the drain pump controller. * @details Inputs: drainPumpState * @details Outputs: drainPumpState * @return none *************************************************************************/ void execDrainPumpController( void ) { // Check if a new calibration is available if ( TRUE == isNewCalibrationRecordAvailable() ) { // This is only one record the number of items to check is 0 since the get NV data function does not do a for loop to check the calibration time getNVRecord2Driver( GET_CAL_DRAIN_LINE_VOLUME_RECORD, (U08*)&drainLineVolumeRecord, sizeof( DG_DRAIN_LINE_VOLUME_T ), 0, ALARM_ID_DG_DRAIN_LINE_VOLUME_INVALID_CAL_RECORD ); } // Handle pending drain pump command if ( pendingDrainPumpCmdCountDown > 0 ) { pendingDrainPumpCmdCountDown--; if ( 0 == pendingDrainPumpCmdCountDown ) { if ( DRAIN_PUMP_CONTROL_TO_TARGET_STATE == pendingDrainPumpCmd ) { targetDrainPumpOutletPressure = pendingDrainPumpCmdTarget; hasClosedLoopBeenRequested = TRUE; drainPumpDAC = DRAIN_PUMP_MIN_DAC; drainPumpControlMode = PUMP_CONTROL_MODE_CLOSED_LOOP; drainPumpControlModeSet = drainPumpControlMode; } else if ( DRAIN_PUMP_OPEN_LOOP_STATE == pendingDrainPumpCmd ) { drainPumpDAC = (U32)( pendingDrainPumpCmdTarget * RPM_2_DAC_SLOPE - RPM_2_DAC_INTERCEPT + FLOAT_TO_INT_ROUNDUP_OFFSET ); targetDrainPumpRPM = (U32)pendingDrainPumpCmdTarget; drainPumpControlMode = PUMP_CONTROL_MODE_OPEN_LOOP; drainPumpControlModeSet = drainPumpControlMode; signalNewRPMRequest = TRUE; } pendingDrainPumpCmdTarget = 0.0; pendingDrainPumpCmd = DRAIN_PUMP_OFF_STATE; } } // Execute drain pump state machine switch ( drainPumpState ) { case DRAIN_PUMP_OFF_STATE: drainPumpState = handleDrainPumpOffState(); break; case DRAIN_PUMP_CONTROL_TO_TARGET_STATE: drainPumpState = handleDrainPumpControlToTargetState(); break; case DRAIN_PUMP_OPEN_LOOP_STATE: drainPumpState = handleDrainPumpOpenLoopState(); break; default: // Wrong state was selected SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_DRAIN_PUMP_INVALID_EXEC_STATE, drainPumpState ) drainPumpState = DRAIN_PUMP_OFF_STATE; break; } } /*********************************************************************//** * @brief * The execDrainPumpSelfTest function executes the drain pump's self-test. * @details Inputs: none * @details Outputs: none * @return PressuresSelfTestResult (SELF_TEST_STATUS_T) *************************************************************************/ SELF_TEST_STATUS_T execDrainPumpSelfTest( void ) { SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; BOOL calStatus = FALSE; // This is only one record the number of items to check is 0 since the get NV data function does not do a for loop to check the calibration time calStatus |= getNVRecord2Driver( GET_CAL_DRAIN_LINE_VOLUME_RECORD, (U08*)&drainLineVolumeRecord, sizeof( DG_DRAIN_LINE_VOLUME_T ), 0, ALARM_ID_DG_DRAIN_LINE_VOLUME_INVALID_CAL_RECORD ); calStatus |= getNVRecord2Driver( GET_CAL_DRAIN_PUMP_RECORD, (U08*)&drainPumpCalRecord, sizeof( DG_DRAIN_PUMP_CAL_RECORD_T ), 0, ALARM_ID_NO_ALARM ); if ( TRUE == calStatus ) { result = SELF_TEST_STATUS_PASSED; } else { result = SELF_TEST_STATUS_FAILED; } return result; } /*********************************************************************//** * @brief * The getDrainPumpTargetRPM function gets the current target drain pump * RPM. * @details Inputs: targetDrainPumpRPM * @details Outputs: none * @return the current target drain pump RPM. *************************************************************************/ U32 getDrainPumpTargetRPM( void ) { return targetDrainPumpRPM; } /*********************************************************************//** * @brief * The getDrainPumpMeasuredRPM function returns the RPM read from the drain * pump RPM sensor. * @details Inputs: drainPumpMeasuredRPM * @details Outputs: none * @return drain pump RPM *************************************************************************/ U32 getDrainPumpMeasuredRPM( void ) { U32 rpm = drainPumpMeasuredRPM.data; if ( OVERRIDE_KEY == drainPumpMeasuredRPM.override ) { rpm = drainPumpMeasuredRPM.ovData; } return rpm; } /*********************************************************************//** * @brief * The getTargetDrainPumpOutletPressure function gets the current target * drain pump delta pressure. * @details Inputs: targetDrainPumpOutletPressure * @details Outputs: none * @return the current target drain pump outlet pressure. *************************************************************************/ F32 getDrainPumpTargetOutletPressure( void ) { return targetDrainPumpOutletPressure; } /*********************************************************************//** * @brief * The isDrainPumpOn function determines whether the drain pump is on. * @details Inputs: drainPumpDACSet * @details Outputs: none * @return TRUE if drain pump is on, FALSE if not. *************************************************************************/ BOOL isDrainPumpOn( void ) { return ( drainPumpDACSet > 0 ? TRUE : FALSE ); } /*********************************************************************//** * @brief * The getFlushLineVolumeL function returns the target flush line volume in * liters. * @details Inputs: drainLineVolumeRecord * @details Outputs: none * @return the target flush line volume in Liter *************************************************************************/ F32 getFlushLineVolumeL( void ) { return drainLineVolumeRecord.volume; } /*********************************************************************//** * @brief * The handleDrainPumpOffState function handles the drain pump off state of * the drain pump controller state machine. * @details Inputs: drainPumpControlModeSet, hasClosedLoopBeenRequested * * @details Outputs: drainPumpDACSet, signalNewRPMRequest * @return next state for the controller state machine *************************************************************************/ static DRAIN_PUMP_STATE_T handleDrainPumpOffState( void ) { DRAIN_PUMP_STATE_T result = DRAIN_PUMP_OFF_STATE; // If the target drain pump speed was not 0 and the control mode // is open loop, set the drain pump to open loop if ( ( getDrainPumpTargetRPM() > 0 ) && ( PUMP_CONTROL_MODE_OPEN_LOOP == drainPumpControlModeSet ) ) { // Set drain pump enable pin SET_DRAIN_PUMP_ENABLE(); // Set drain pump DAC drainPumpDACSet = drainPumpDAC; setFPGADrainPumpSpeed( drainPumpDACSet ); result = DRAIN_PUMP_OPEN_LOOP_STATE; } // If the drain pump is set to closed loop, call the proper state // It is checked for the value of delta pressure because it can be anything including 0 else if ( ( PUMP_CONTROL_MODE_CLOSED_LOOP == drainPumpControlModeSet ) && ( TRUE == hasClosedLoopBeenRequested ) ) { // set drain pump enable pin SET_DRAIN_PUMP_ENABLE(); resetPIController( PI_CONTROLLER_ID_DRAIN_PUMP, DRAIN_PUMP_MIN_DAC ); // set drain pump DAC drainPumpDACSet = drainPumpDAC; setFPGADrainPumpSpeed( drainPumpDACSet ); result = DRAIN_PUMP_CONTROL_TO_TARGET_STATE; } return result; } /*********************************************************************//** * @brief * The handleDrainPumpControlToTargetState function handles the control to * target state of the drain pump controller state machine. * @details Inputs: drainControlTimerCounter, drainPumpDACSet * @details Outputs: drainControlTimerCounter, drainPumpDACSet * @return next state of the controller state machine *************************************************************************/ static DRAIN_PUMP_STATE_T handleDrainPumpControlToTargetState( void ) { DRAIN_PUMP_STATE_T state = DRAIN_PUMP_CONTROL_TO_TARGET_STATE; // control at set interval if ( ++drainControlTimerCounter >= DRP_CONTROL_INTERVAL ) { F32 outletDrainPressure = getMeasuredDGPressure( PRESSURE_SENSOR_DRAIN_PUMP_OUTLET ); F32 dac = runPIController( PI_CONTROLLER_ID_DRAIN_PUMP, getDrainPumpTargetOutletPressure(), outletDrainPressure ); // The PI controller sends the DAC out and it is rounded to the nearest offset and is fed to the FPGA drainPumpDACSet = (U32)( dac + FLOAT_TO_INT_ROUNDUP_OFFSET ); setFPGADrainPumpSpeed( drainPumpDACSet ); drainControlTimerCounter = 0; } return state; } /*********************************************************************//** * @brief * The handleDrainPumpOpenLoopState function handles the open loop state. * @details Inputs: signalNewRPMRequest * @details Outputs: signalNewRPMRequest, drainPumpDACSet * @return next state of the controller state machine *************************************************************************/ static DRAIN_PUMP_STATE_T handleDrainPumpOpenLoopState( void ) { DRAIN_PUMP_STATE_T state = DRAIN_PUMP_OPEN_LOOP_STATE; // If there is a signal for a new RPM, change to the new RPM if ( TRUE == signalNewRPMRequest ) { // Set drain pump DAC drainPumpDACSet = drainPumpDAC; signalNewRPMRequest = FALSE; setFPGADrainPumpSpeed( drainPumpDACSet ); } return state; } /*********************************************************************//** * @brief * The stopDrainPump function sets the drain pump DAC to zero and stops * the pump. * @details Inputs: drainPumpDAC, drainPumpDACSet * @details Outputs: drainPumpDAC, drainPumpDACSet * @return none *************************************************************************/ static void stopDrainPump( void ) { drainPumpDAC = 0; drainPumpDACSet = 0; setFPGADrainPumpSpeed( drainPumpDACSet ); CLR_DRAIN_PUMP_ENABLE(); } /*********************************************************************//** * @brief * The publishDrainPumpData function publishes drain pump data at the set * interval. * @details Inputs: drainPumpDataPublicationTimerCounter * @details Outputs: drainPumpDataPublicationTimerCounter * @return none *************************************************************************/ static void publishDrainPumpData( void ) { // publish Drain pump data on interval if ( ++drainPumpDataPublicationTimerCounter >= getU32OverrideValue( &drainPumpDataPublishInterval ) ) { DRAIN_PUMP_DATA_T drainPumpData; // Populate the data structure for publication drainPumpData.rpmSetPoint = getDrainPumpTargetRPM(); drainPumpData.pumpDACSet = drainPumpDACSet; drainPumpData.drainPumpState = (U32)drainPumpState; drainPumpData.drainPumpRPM = getDrainPumpMeasuredRPM(); drainPumpData.trgtOutletPrsr = targetDrainPumpOutletPressure; broadcastData( MSG_ID_DRAIN_PUMP_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&drainPumpData, sizeof( DRAIN_PUMP_DATA_T ) ); drainPumpDataPublicationTimerCounter = 0; } } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testSetDrainPumpDataPublishIntervalOverride function overrides the * drain pump data publish interval. * @details Inputs: drainPumpDataPublishInterval * @details Outputs: drainPumpDataPublishInterval * @param value override drain pump data publish interval with (in ms) * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetDrainPumpDataPublishIntervalOverride( U32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { U32 intvl = value / TASK_PRIORITY_INTERVAL; drainPumpDataPublishInterval.ovData = intvl; drainPumpDataPublishInterval.override = OVERRIDE_KEY; result = TRUE; } return result; } /*********************************************************************//** * @brief * The testResetDrainPumpDataPublishIntervalOverride function resets the * override of the drain pump data publish interval. * @details Inputs: drainPumpDataPublishInterval * @details Outputs: drainPumpDataPublishInterval * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetDrainPumpDataPublishIntervalOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { drainPumpDataPublishInterval.override = OVERRIDE_RESET; drainPumpDataPublishInterval.ovData = drainPumpDataPublishInterval.ovInitData; result = TRUE; } return result; } /*********************************************************************//** * @brief * The testSetTargetDrainPumpRPMOverride function overrides the target * drain pump RPM. * @details Inputs: none * @details Outputs: none * @param value override target drain pump RPM * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetTargetDrainPumpRPM( U32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { if ( ( value >= MIN_DRAIN_PUMP_RPM ) && ( value <= MAX_DRAIN_PUMP_RPM ) ) { result = setDrainPumpTargetRPM( value ); } if ( 0 == value ) { signalDrainPumpHardStop(); } } return result; } /*********************************************************************//** * @brief * The testSetTargetDrainPumpDeltaPressureOverride function overrides * the target drain pump delta pressure. * @details Inputs: none * @details Outputs: none * @param value override target drain pump delta pressure * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetTargetDrainPumpOutletPressure( F32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { // Check if delta pressure is in range if ( ( value >= MIN_ALLOWED_TARGET_OUTLET_PRESSURE ) && ( value <= MAX_ALLOWED_TARGET_OUTLET_PRESSURE ) ) { result = setDrainPumpTargetOutletPressure( value ); } } return result; } /*********************************************************************//** * @brief * The testSetDrainPumpMeasuredRPMOverride function overrides the drain pump * measured RPM data. * @details Inputs: none * @details Outputs: drainPumpMeasuredRPM * @param value override drain pump measured data * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetDrainPumpMeasuredRPMOverride( U32 value ) { BOOL status = FALSE; // Check if the requested drain pump RPM is within range if ( ( value >= MIN_DRAIN_PUMP_RPM ) && ( value <= MAX_DRAIN_PUMP_RPM ) ) { // Check if the user is logged in if ( TRUE == isTestingActivated() ) { drainPumpMeasuredRPM.ovData = value; drainPumpMeasuredRPM.override = OVERRIDE_KEY; drainPumpMeasuredRPM.ovInitData = drainPumpMeasuredRPM.data; status = TRUE; } } return status; } /*********************************************************************//** * @brief * The testResetDrainPumpMeasuredRPMOverride function resets the drain pump * measured RPM data. * @details Inputs: none * @details Outputs: drainPumpMeasuredRPM * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetDrainPumpMeasuredRPMOverride( void ) { BOOL status = FALSE; // Check if the user is logged in if ( TRUE == isTestingActivated() ) { drainPumpMeasuredRPM.ovData = drainPumpMeasuredRPM.ovInitData; drainPumpMeasuredRPM.override = OVERRIDE_RESET; status = TRUE; } return status; } /**@}*/