Index: firmware/App/Controllers/DrainPump.c =================================================================== diff -u -rdcd360fb4dc37db2dcbeb7fb14fb327fe68235f4 -ra89d6b091874136d75a9bfbdbbc1ff00f42467b3 --- firmware/App/Controllers/DrainPump.c (.../DrainPump.c) (revision dcd360fb4dc37db2dcbeb7fb14fb327fe68235f4) +++ firmware/App/Controllers/DrainPump.c (.../DrainPump.c) (revision a89d6b091874136d75a9bfbdbbc1ff00f42467b3) @@ -1,14 +1,14 @@ /************************************************************************** * -* Copyright (c) 2019-2021 Diality Inc. - All Rights Reserved. +* 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) 10-Nov-2021 +* @date (last) 11-Jul-2022 * * @author (original) Sean * @date (original) 08-Apr-2020 @@ -52,30 +52,31 @@ #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.0547 ///< RPM to DAC conversion slope. -#define RPM_2_DAC_INTERCEPT 2.9968 ///< RPM to DAC conversion intercept. +#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.000005 ///< Toggle period to resolution in seconds. +#define TOGGLE_PERIOD_RESOLUTION_SECONDS 0.000005F ///< Toggle period to resolution in seconds. #define ROTATIONAL_TO_TOGGLE_PERIOD_CONVERSION 4 ///< Rotational to toggle period conversion coefficient. -#define DRAIN_PUMP_P_COEFFICIENT 0.5 ///< P term for drain pump delta pressure control. -#define DRAIN_PUMP_I_COEFFICIENT 1.0 ///< I term for drain pump delta pressure control. +#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.0 ///< Minimum allowed outlet pressure for closed loop control. -#define MAX_ALLOWED_TARGET_OUTLET_PRESSURE 15.0 ///< Maximum allowed outlet pressure for closed loop 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 ( 5 * MS_PER_SECOND ) ///< Open loop RPM out of range time out in ms. +#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 MS_PER_SECOND ///< Drain pump safety shutdown activation timeout. +#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 @@ -98,7 +99,7 @@ // ********** private data ********** static DRAIN_PUMP_STATE_T drainPumpState = DRAIN_PUMP_OFF_STATE; ///< Current state of drain pump controller state machine. -static U32 drainPumpDataPublicationTimerCounter = 0; ///< Used to schedule drain pump data publication to CAN bus. +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. @@ -118,7 +119,8 @@ 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 F32 targetFlushLineVolume_L = 0.0; ///< Target flush volume in liters. +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 = SEC_PER_MIN / ( 2 * TOGGLE_PERIOD_RESOLUTION_SECONDS * ROTATIONAL_TO_TOGGLE_PERIOD_CONVERSION ); @@ -130,23 +132,21 @@ static DRAIN_PUMP_STATE_T handleDrainPumpOpenLoopState( void ); static void stopDrainPump( void ); static void publishDrainPumpData( void ); -static BOOL processCalibrationData( void ); /*********************************************************************//** * @brief * The initDrainPump function initializes the DrainPump module. * @details Inputs: none - * @details Outputs: hasClosedLoopBeenRequested, targetFlushLineVolume_L, - * signalNewRPMRequest + * @details Outputs: hasClosedLoopBeenRequested, signalNewRPMRequest * @return none *************************************************************************/ void initDrainPump( void ) { stopDrainPump(); - hasClosedLoopBeenRequested = FALSE; - targetFlushLineVolume_L = 0.0; - signalNewRPMRequest = FALSE; + 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, @@ -175,12 +175,15 @@ 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; - result = TRUE; + 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 { @@ -207,8 +210,8 @@ if ( ( 0 == rpm ) || ( ( rpm >= MIN_DRAIN_PUMP_RPM ) && ( rpm <= MAX_DRAIN_PUMP_RPM ) ) ) { - pendingDrainPumpCmd = DRAIN_PUMP_OPEN_LOOP_STATE; - pendingDrainPumpCmdTarget = (F32)rpm; + pendingDrainPumpCmd = DRAIN_PUMP_OPEN_LOOP_STATE; + pendingDrainPumpCmdTarget = (F32)rpm; pendingDrainPumpCmdCountDown = delayMs / TASK_GENERAL_INTERVAL; result = TRUE; } @@ -299,14 +302,14 @@ 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; + 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; } @@ -321,47 +324,44 @@ *************************************************************************/ void execDrainPumpMonitor( void ) { - U16 const fpgaADCSpeedCount = getFPGADrainPumpSpeed(); + U16 fpgaADCSpeedCount = getFPGADrainPumpSpeed(); + drainPumpMeasuredRPM.data = ( DRAIN_PUMP_OFF_RPM_ADC_COUNT == fpgaADCSpeedCount ? 0 : ( CONVERSION_COEFF / fpgaADCSpeedCount ) ); - if ( DRAIN_PUMP_OFF_RPM_ADC_COUNT == fpgaADCSpeedCount ) +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_DRAIN_PUMP_MONITOR ) != SW_CONFIG_ENABLE_VALUE ) +#endif { - drainPumpMeasuredRPM.data = 0; - } - else - { - // Convert speed ADC to RPM - drainPumpMeasuredRPM.data = CONVERSION_COEFF / getFPGADrainPumpSpeed(); - } + // 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 ); -#ifndef IGNORE_DRAIN_PUMP_MONITOR - // The RPM is only checked in open loop state that the pump is run at a fixed RPM. - // The persistent alarm waits for a couple of seconds before raising an alarm, this is supposed to cover - // when the pump is turned on and it takes a while to ramp up to target RPM. - if ( PUMP_CONTROL_MODE_OPEN_LOOP == drainPumpControlModeSet ) - { - // Using abs since the read RPM can be above or below the target - U32 rpmDiff = abs( getDrainPumpTargetRPM() - getDrainPumpMeasuredRPM() ); + 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 ); - // Check if RPM is out of range - BOOL isRPMOutOfRange = ( rpmDiff > MAX_ALLOWED_OPEN_LOOP_RPM_OUT_OF_RANGE ? TRUE : FALSE ); + // 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 ); - } - - // 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_OFF_FAULT, isRPMTooHigh, getDrainPumpMeasuredRPM(), MIN_DRAIN_PUMP_RPM ); - - // If the off fault alarm has become active, trigger the safety shutdown - if ( isAlarmActive( ALARM_ID_DRAIN_PUMP_OFF_FAULT ) ) + 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 { - activateSafetyShutdown(); + // 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 ); } } -#endif // Publish drain pump data on interval publishDrainPumpData(); @@ -376,6 +376,14 @@ *************************************************************************/ 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 ) { @@ -396,9 +404,10 @@ targetDrainPumpRPM = (U32)pendingDrainPumpCmdTarget; drainPumpControlMode = PUMP_CONTROL_MODE_OPEN_LOOP; drainPumpControlModeSet = drainPumpControlMode; + signalNewRPMRequest = TRUE; } pendingDrainPumpCmdTarget = 0.0; - pendingDrainPumpCmd = DRAIN_PUMP_OFF_STATE; + pendingDrainPumpCmd = DRAIN_PUMP_OFF_STATE; } } @@ -435,9 +444,15 @@ SELF_TEST_STATUS_T execDrainPumpSelfTest( void ) { SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; + BOOL calStatus = FALSE; - BOOL calStatus = processCalibrationData(); + // 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; @@ -510,14 +525,15 @@ /*********************************************************************//** * @brief - * The getFlushLineVolume function returns the target flush line volume. - * @details Inputs: targetFlushLineVolume_L + * 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 getFlushLineVolume( void ) +F32 getFlushLineVolumeL( void ) { - return targetFlushLineVolume_L; + return drainLineVolumeRecord.volume; } /*********************************************************************//** @@ -539,8 +555,6 @@ // Set drain pump enable pin SET_DRAIN_PUMP_ENABLE(); - // Turn off the new RPM signal - signalNewRPMRequest = FALSE; // Set drain pump DAC drainPumpDACSet = drainPumpDAC; setFPGADrainPumpSpeed( drainPumpDACSet ); @@ -609,9 +623,9 @@ if ( TRUE == signalNewRPMRequest ) { // Set drain pump DAC - drainPumpDACSet = drainPumpDAC; - setFPGADrainPumpSpeed( drainPumpDACSet ); + drainPumpDACSet = drainPumpDAC; signalNewRPMRequest = FALSE; + setFPGADrainPumpSpeed( drainPumpDACSet ); } return state; @@ -661,39 +675,7 @@ } } -/*********************************************************************//** - * @brief - * The processCalibrationData function gets the calibration data and makes - * sure it is valid by checking the calibration date. The calibration date - * should not be 0. - * @details Inputs: none - * @details Outputs: modeRecircTargetFlushVolL - * @return TRUE if the calibration record is valid, otherwise FALSE - *************************************************************************/ -static BOOL processCalibrationData( void ) -{ - BOOL status = TRUE; - // Get the calibration record from NVDataMgmt - DG_DRAIN_LINE_VOLUME_T calData = getDGDrainLineVolumeRecord(); - - // Check if the calibration data that was received from NVDataMgmt is legitimate - // The calibration date item should not be zero. If the calibration date is 0, - // then the data is not stored in the NV memory or it was corrupted. - if ( 0 == calData.calibrationTime ) - { -#ifndef SKIP_CAL_CHECK - activateAlarmNoData( ALARM_ID_DG_DRAIN_LINE_VOLUME_INVALID_CAL_RECORD ); - status = FALSE; -#endif - } - - // The calibration data was valid, update the local copy - targetFlushLineVolume_L = calData.volume; - - return status; -} - /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/