/************************************************************************** * * Copyright (c) 2020-2023 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 Pressures.c * * @author (last) Dara Navaei * @date (last) 14-Sep-2023 * * @author (original) Sean * @date (original) 04-Apr-2020 * ***************************************************************************/ #include #include "AlarmMgmt.h" #include "FPGA.h" #include "InternalADC.h" #include "MessageSupport.h" #include "NVDataMgmt.h" #include "OperationModes.h" #include "PersistentAlarm.h" #include "Pressures.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "TaskPriority.h" #include "TemperatureSensors.h" #include "Timers.h" #include "Utilities.h" #include "Valves.h" /** * @addtogroup DGPressures * @{ */ // ********** private definitions ********** #define PUMP_PRESSURE_ZERO 759 ///< ADC counts equivalent to 0 PSI for pump in/out pressure sensors. #define PUMP_PRESSURE_PSIA_PER_COUNT 0.06583F ///< PSIA per ADC count conversion factor for pump in/out pressure sensors. #define PUMP_V3_PRESSURE_ZERO 782 ///< Beta ADC counts equivalent to 0 psi for pump in/out pressure sensors. #define PUMP_V3_PRESSURE_PSIA_PER_COUNT 0.065359F ///< Beta PSIA ADC count conversion factor for pump in/out pressure sensors. #define PUMP_PRESSURE_PSIA_TO_PSI_OFFSET 14.7F ///< Subtract this offset to convert PSIA to PSI. #define ONE_BAR_TO_PSI_CONVERSION 14.5F ///< 1 bar to PSI conversion. #define ONE_BAR_TO_MILLI_BAR 1000 ///< 1 bar to milli-bar conversion. #define COUNTS_TO_MILLI_BAR 100 ///< Counts to milli-bar conversion. #define PRESSURE_SAMPLES_TO_AVERAGE ( 200 / TASK_PRIORITY_INTERVAL ) ///< Averaging pressure data over the reporting interval. #define PRESSURE_AVERAGE_MULTIPLIER ( 1.0F / (F32)PRESSURE_SAMPLES_TO_AVERAGE ) ///< Optimization - multiplying is faster than dividing. #define MIN_VALID_PRESSURE_RANGE_PSIA 0.0F ///< Minimum valid range on pressure psia. #define MAX_VALID_PRESSURE_RANGE_PSIA 200.0F ///< Maximum valid range on pressure psia. #define MIN_VALID_BARO_PRESSURE_PSIA 10.1F ///< Minimum valid barometric pressure in psia. #define MAX_VALID_BARO_PRESSURE_PSIA 15.4F ///< Maximum valid barometric pressure in psia. #define MIN_INLET_WATER_PRESSURE_WARNING_LOW_PSIG 23.0F ///< Minimum allowed low pressure value in psig. #define MIN_FLUSH_INLET_PRESSURE_WARNING_LOW_PSIG 14.0F ///< Minimum allowed low pressure value for Flush in psig. #define MIN_FLUSH_INLET_PRESSURE_TO_CLEAR_PSIG 15.0F ///< Minimum allowed low pressure value for flush in psig. #define MIN_INLET_PRESSURE_TO_CLEAR_WARINING_PSIG 24.0F ///< Minimum allowed low pressure value in psig. #define MAX_INLET_WATER_PRESSURE_WARNING_HIGH_PSIG 80.0F ///< Maximum allowed high pressure value in psig. #define MIN_INLET_WATER_PRESSURE_WARNING_HIGH_PSIG 78.0F ///< Minimum allowed high pressure value in psig. #define INLET_WATER_PRES_OUT_OF_RANGE_TIMEOUT_MS ( 20 * MS_PER_SECOND ) ///< Persistence period for pressure out of range error in milliseconds. #define INLET_WATER_PRES_OUT_OF_RANGE_CLEAR_MS ( 10 * MS_PER_SECOND ) ///< Persistence period for pressure out of range clear in milliseconds. #define PRESSURE_OUT_OF_RANGE_TIMEOUT_MS ( 5 * MS_PER_SECOND ) ///< Pressure out of range persistence period in milliseconds. #define PRESSURES_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Interval (ms/task time) at which the pressures data is published on the CAN bus. #define DATA_PUBLISH_COUNTER_START_COUNT 10 ///< Data publish counter start count. #define PRESSURE_SENSORS_ADC_CHECK_ARRAY_LEN 4 ///< Pressure sensors ADC check array length. #define CLEANING_MODE_LOW_PRESSURE_STATE_NUMBER 3 ///< Cleaning mode low pressure state number. static const U32 TWO_TO_POWER_OF_6 = ( 1 << 6 ); ///< 2^6. static const U32 TWO_TO_POWER_OF_7 = ( 1 << 7 ); ///< 2^7. static const U32 TWO_TO_POWER_OF_15 = ( 1 << 15 ); ///< 2^15. static const U32 TWO_TO_POWER_OF_16 = ( 1 << 16 ); ///< 2^16. static const U32 TWO_TO_POWER_OF_17 = ( 1 << 17 ); ///< 2^17. static const U32 TWO_TO_POWER_OF_21 = ( 1 << 21 ); ///< 2^21. /// Defined states for the pressures monitor state machine. typedef enum PresOccl_States { PRESSURE_INIT_STATE = 0, ///< Initialization state. PRESSURE_CONTINUOUS_READ_STATE, ///< Continuous read sensors state. NUM_OF_PRESSURE_STATES ///< Number of pressure monitor states. } PRESSURE_STATE_T; /// Defined states for the pressures self-test state machine. typedef enum Pressures_Self_Test_States { PRESSURE_SELF_TEST_STATE_START = 0, ///< Self-test start state. PRESSURE_TEST_STATE_IN_PROGRESS, ///< Self-test in progress state. PRESSURE_TEST_STATE_COMPLETE, ///< Self-test completed state. NUM_OF_PRESSURE_SELF_TEST_STATES ///< Number of pressure self-test states. } PRESSURE_SELF_TEST_STATE_T; /// Barometric sensor conversion coefficients typedef struct { U16 pressureSensitivity; ///< Barometric sensor pressure sensitivity constant. U16 pressureOffset; ///< Barometric sensor pressure offset constant. U16 pressureSensitivityTempCoeff; ///< Barometric sensor pressure sensitivity temperature coefficient. U16 pressureOffsetTempCoeff; ///< Barometric sensor pressure offset temperature coefficient. } BARO_SENSOR_CONSTS_T; // ********** private data ********** static PRESSURE_STATE_T pressuresState; ///< current state of pressure monitor state machine. static U32 pressuresDataPublicationTimerCounter; ///< used to schedule pressure data publication to CAN bus. static OVERRIDE_U32_T pressuresDataPublishInterval = { PRESSURES_DATA_PUB_INTERVAL, PRESSURES_DATA_PUB_INTERVAL, 0, 0 }; /// Pressure data publish interval. static OVERRIDE_F32_T pressures[ NUM_OF_PRESSURE_SENSORS ]; ///< Measured pressure from sensors. static S32 msrdPressureSum[ NUM_OF_PRESSURE_SENSORS ]; ///< Raw pressure sensor sums for averaging. static U32 pressureFilterCounter; ///< Used to schedule pressure sensor filtering. static BARO_SENSOR_CONSTS_T baroConvConsts; ///< Barometric sensor conversion constants. static PRESSURE_SELF_TEST_STATE_T pressuresSelfTestState; ///< Current pressure self-test state. static SELF_TEST_STATUS_T pressuresSelfTestResult; ///< Self-test result of the Pressures module. static DG_PRES_SENSORS_CAL_RECORD_T pressuresCalRecord; ///< Pressures calibration record. // ********** private function prototypes ********** static PRESSURE_STATE_T handlePressuresInitState( void ); static PRESSURE_STATE_T handlePressuresContReadState( void ); static void publishPressuresData( void ); static F32 calculateBaroPressure( U32 adcSum ); static F32 getCalibrationAppliedPressure( U08 sensorId, F32 pressure ); static F32 getBaroPressurePSI( void ); static void monitorPressureSensors( void ); /*********************************************************************//** * @brief * The initPressures function initializes the Pressures module. * @details Inputs: none * @details Outputs: Pressures module initialized. * @return none *************************************************************************/ void initPressures( void ) { U08 i; pressuresState = PRESSURE_INIT_STATE; pressuresSelfTestState = PRESSURE_SELF_TEST_STATE_START; pressuresDataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; pressureFilterCounter = 0; for ( i = 0; i < NUM_OF_PRESSURE_SENSORS; i++ ) { pressures[ i ].data = 0.0F; pressures[ i ].ovData = 0.0F; pressures[ i ].ovInitData = 0.0F; pressures[ i ].override = OVERRIDE_RESET; msrdPressureSum[ i ] = 0; } initPersistentAlarm( ALARM_ID_DG_INLET_WATER_PRESSURE_IN_LOW_RANGE, INLET_WATER_PRES_OUT_OF_RANGE_CLEAR_MS, INLET_WATER_PRES_OUT_OF_RANGE_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_DG_INLET_WATER_PRESSURE_IN_HIGH_RANGE, INLET_WATER_PRES_OUT_OF_RANGE_CLEAR_MS, INLET_WATER_PRES_OUT_OF_RANGE_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_DG_PRESSURE_OUT_OF_RANGE, 0, PRESSURE_OUT_OF_RANGE_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_DG_BARO_PRESSURE_OUT_OF_RANGE, 0, PRESSURE_OUT_OF_RANGE_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_PRESSURE_TOO_HIGH, 0, INLET_WATER_PRES_OUT_OF_RANGE_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_PRESSURE_TOO_LOW, 0, INLET_WATER_PRES_OUT_OF_RANGE_TIMEOUT_MS ); } /*********************************************************************//** * @brief * The checkInletWaterPressure function checks inlet water pressure value * and triggers an alarm when pressure value is out of allowed range. * @details Inputs: RO pump inlet pressure sensor value * @details Outputs: Triggers low pressure persistent alarm * @return none *************************************************************************/ void checkInletWaterPressure( void ) { F32 pressure = getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_INLET ); if ( VALVE_STATE_OPEN == getValveStateName( VPI ) ) { #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_WATER_QUALITY_CHECK ) != SW_CONFIG_ENABLE_VALUE ) #endif { BOOL isPressureTooLow; BOOL isPressureTooHigh; F32 maxInletWaterPressureWarningLow = MIN_INLET_WATER_PRESSURE_WARNING_LOW_PSIG; F32 minInletWaterPressureWarningLow = MIN_INLET_PRESSURE_TO_CLEAR_WARINING_PSIG; DG_OP_MODE_T opMode = getCurrentOperationMode(); switch ( opMode ) { case DG_MODE_STAN: maxInletWaterPressureWarningLow = MIN_FLUSH_INLET_PRESSURE_WARNING_LOW_PSIG; minInletWaterPressureWarningLow = MIN_FLUSH_INLET_PRESSURE_TO_CLEAR_PSIG; break; case DG_MODE_FLUS: case DG_MODE_HEAT: case DG_MODE_CHEM: case DG_MODE_CHFL: case DG_MODE_ROPS: // Per PRS 401 the low pressure limit for the cleaning modes that have the filter flush state is 14 psig. // In the cleaning modes, flush, heat disinfect, chem disinfect, chem flush disinfect, and RO permeate sample, the 3rd state is // flush drain so only in that state the limit is set to 14 psig. // NOTE: Active cool does not have a flush drain state. if ( CLEANING_MODE_LOW_PRESSURE_STATE_NUMBER == getCurrentOperationSubMode() ) { maxInletWaterPressureWarningLow = MIN_FLUSH_INLET_PRESSURE_WARNING_LOW_PSIG; } break; default: // Do nothing for the rest of the modes since the default inlet pressure has been set. break; } isPressureTooLow = ( pressure < maxInletWaterPressureWarningLow ? TRUE : FALSE ); isPressureTooHigh = ( pressure > MAX_INLET_WATER_PRESSURE_WARNING_HIGH_PSIG ? TRUE : FALSE ); switch( opMode ) { case DG_MODE_GENE: case DG_MODE_FILL: case DG_MODE_DRAI: case DG_MODE_STAN: if ( TRUE == isAlarmActive( ALARM_ID_DG_INLET_WATER_PRESSURE_IN_LOW_RANGE ) ) { isPressureTooLow = ( pressure >= minInletWaterPressureWarningLow ? FALSE : TRUE ); } // Per PRS 401 checkPersistentAlarm( ALARM_ID_DG_INLET_WATER_PRESSURE_IN_LOW_RANGE, isPressureTooLow, pressure, maxInletWaterPressureWarningLow ); if ( TRUE == isAlarmActive( ALARM_ID_DG_INLET_WATER_PRESSURE_IN_HIGH_RANGE ) ) { isPressureTooHigh = ( pressure <= MIN_INLET_WATER_PRESSURE_WARNING_HIGH_PSIG ? FALSE : TRUE ); } // Per PRS 841 checkPersistentAlarm( ALARM_ID_DG_INLET_WATER_PRESSURE_IN_HIGH_RANGE, isPressureTooHigh, pressure, MAX_INLET_WATER_PRESSURE_WARNING_HIGH_PSIG ); break; case DG_MODE_FLUS: case DG_MODE_HEAT: case DG_MODE_HCOL: case DG_MODE_CHEM: case DG_MODE_CHFL: case DG_MODE_ROPS: // TODO define the PRS checkPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_PRESSURE_TOO_HIGH, isPressureTooHigh, pressure, MAX_INLET_WATER_PRESSURE_WARNING_HIGH_PSIG ); // TODO define the PRS checkPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_PRESSURE_TOO_LOW, isPressureTooLow, pressure, MIN_INLET_PRESSURE_TO_CLEAR_WARINING_PSIG ); break; #ifndef _VECTORCAST_ // This default is reachable in VectorCAST but it is not testable since no static variables or other functions are called // So it is masked in VectorCAST default: // NOTE: Do nothing for the rest of the modes break; #endif } } } else { // VPI is closed - clear all alarms checkPersistentAlarm( ALARM_ID_DG_INLET_WATER_PRESSURE_IN_LOW_RANGE, FALSE, pressure, MIN_INLET_WATER_PRESSURE_WARNING_LOW_PSIG ); checkPersistentAlarm( ALARM_ID_DG_INLET_WATER_PRESSURE_IN_HIGH_RANGE, FALSE, pressure, MAX_INLET_WATER_PRESSURE_WARNING_HIGH_PSIG ); checkPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_PRESSURE_TOO_HIGH, FALSE, pressure, MAX_INLET_WATER_PRESSURE_WARNING_HIGH_PSIG ); checkPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_PRESSURE_TOO_LOW, FALSE, pressure, MIN_INLET_PRESSURE_TO_CLEAR_WARINING_PSIG ); } } /*********************************************************************//** * @brief * The getMeasuredArterialPressure function gets the current arterial pressure. * @details Inputs: arterialPressure * @details Outputs: none * @param pressureID pressure sensor ID * @return the current arterial pressure (in mmHg). *************************************************************************/ F32 getMeasuredDGPressure( U32 pressureID ) { F32 result = 0.0F; if ( pressureID < NUM_OF_PRESSURE_SENSORS ) { result = getF32OverrideValue( &pressures[ pressureID ] ); } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_PRESSURE_SENSOR_SELECTED, pressureID ); } return result; } /*********************************************************************//** * @brief * The resetPressuresPOSTState function resets the pressures POST state. * @details Inputs: none * @details Outputs: pressuresSelfTestState * @return none *************************************************************************/ void resetPressuresPOSTState( void ) { pressuresSelfTestState = PRESSURE_SELF_TEST_STATE_START; } /*********************************************************************//** * @brief * The execPressures function executes the pressures' monitor state machine * and publish pressures' data. * @details Inputs: pressuresState * @details Outputs: pressuresState * @return none *************************************************************************/ void execPressures( void ) { // state machine switch ( pressuresState ) { case PRESSURE_INIT_STATE: pressuresState = handlePressuresInitState(); break; case PRESSURE_CONTINUOUS_READ_STATE: pressuresState = handlePressuresContReadState(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_PRESSURE_INVALID_EXEC_STATE, pressuresState ) pressuresState = PRESSURE_INIT_STATE; break; } // publish pressure/occlusion data on interval publishPressuresData(); } /*********************************************************************//** * @brief * The execPressureSelfTest function executes the pressures self-test's * state machine. * @details Inputs: pressuresSelfTestState * @details Outputs: pressuresSelfTestState * @return PressuresSelfTestResult (SELF_TEST_STATUS_T) *************************************************************************/ SELF_TEST_STATUS_T execPressureSelfTest( void ) { switch ( pressuresSelfTestState ) { case PRESSURE_SELF_TEST_STATE_START: { BOOL calStatus = getNVRecord2Driver( GET_CAL_PRESSURE_SENOSRS, (U08*)&pressuresCalRecord, sizeof( DG_PRES_SENSORS_CAL_RECORD_T ), NUM_OF_CAL_DATA_PRES_SENSORS, ALARM_ID_NO_ALARM ); if ( TRUE == calStatus ) { pressuresSelfTestState = PRESSURE_TEST_STATE_IN_PROGRESS; pressuresSelfTestResult = SELF_TEST_STATUS_IN_PROGRESS; } else { pressuresSelfTestResult = SELF_TEST_STATUS_FAILED; } } break; case PRESSURE_TEST_STATE_IN_PROGRESS: // currently no POST test to run for pressure sensors, but they are range checked regularly pressuresSelfTestState = PRESSURE_TEST_STATE_COMPLETE; pressuresSelfTestResult = SELF_TEST_STATUS_PASSED; break; case PRESSURE_TEST_STATE_COMPLETE: // Done with self-test break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_DG_PRESSURES_INVALID_SELF_TEST_STATE, pressuresSelfTestState ); break; } return pressuresSelfTestResult; } /*********************************************************************//** * @brief * The handlePressuresInitState function handles the pressures initialize state * of the pressures monitor state machine. * @details Inputs: none * @details Outputs: none * @return next state *************************************************************************/ static PRESSURE_STATE_T handlePressuresInitState( void ) { return PRESSURE_CONTINUOUS_READ_STATE; } /*********************************************************************//** * @brief * The handlePressuresContReadState function handles the continuous read state * of the pressures monitor state machine. * @details Inputs: pressureFilterCounter * @details Outputs: pressure sensor values updated * @return next state *************************************************************************/ static PRESSURE_STATE_T handlePressuresContReadState( void ) { PRESSURE_STATE_T result = PRESSURE_CONTINUOUS_READ_STATE; U32 zeroPressureOffset = PUMP_PRESSURE_ZERO; F32 count2PressureConv = PUMP_PRESSURE_PSIA_PER_COUNT; U08 sensorId; #ifndef _RELEASE_ if ( ( HW_CONFIG_BETA == getHardwareConfigStatus() ) && ( getCurrentOperationMode() != DG_MODE_INIT ) ) { zeroPressureOffset = PUMP_V3_PRESSURE_ZERO; count2PressureConv = PUMP_V3_PRESSURE_PSIA_PER_COUNT; } #endif // Update sums for pressure average calculations msrdPressureSum[ PRESSURE_SENSOR_RO_PUMP_INLET ] += (S32)getIntADCReading( INT_ADC_RO_PUMP_INLET_PRESSURE ) - zeroPressureOffset; msrdPressureSum[ PRESSURE_SENSOR_RO_PUMP_OUTLET ] += (S32)getIntADCReading( INT_ADC_RO_PUMP_OUTLET_PRESSURE ) - zeroPressureOffset; msrdPressureSum[ PRESSURE_SENSOR_DRAIN_PUMP_INLET ] += (S32)getIntADCReading( INT_ADC_DRAIN_PUMP_INLET_PRESSURE ) - zeroPressureOffset; msrdPressureSum[ PRESSURE_SENSOR_DRAIN_PUMP_OUTLET ] += (S32)getIntADCReading( INT_ADC_DRAIN_PUMP_OUTLET_PRESSURE ) - zeroPressureOffset; msrdPressureSum[ PRESSURE_SENSOR_BAROMETRIC ] += (S32)( getFPGABaroPressure() & MASK_OFF_U32_MSB ); // Check if a new calibration is available if ( TRUE == isNewCalibrationRecordAvailable() ) { getNVRecord2Driver( GET_CAL_PRESSURE_SENOSRS, (U08*)&pressuresCalRecord, sizeof( DG_PRES_SENSORS_CAL_RECORD_T ), NUM_OF_CAL_DATA_PRES_SENSORS, ALARM_ID_NO_ALARM ); } // filter every 200ms if ( ++pressureFilterCounter >= PRESSURE_SAMPLES_TO_AVERAGE ) { F32 adcSum; F32 pressureBeforeCal = 0.0F; F32 baroPressure = getBaroPressurePSI(); pressureFilterCounter = 0; for ( sensorId = 0; sensorId < NUM_OF_PRESSURE_SENSORS; sensorId++ ) { adcSum = (F32)msrdPressureSum[ sensorId ] * PRESSURE_AVERAGE_MULTIPLIER; switch ( sensorId ) { case PRESSURE_SENSOR_RO_PUMP_INLET: case PRESSURE_SENSOR_RO_PUMP_OUTLET: case PRESSURE_SENSOR_DRAIN_PUMP_OUTLET: case PRESSURE_SENSOR_DRAIN_PUMP_INLET: pressureBeforeCal = ( adcSum * count2PressureConv ) - baroPressure; pressures[ sensorId ].data = getCalibrationAppliedPressure( sensorId, pressureBeforeCal ); msrdPressureSum[ sensorId ] = 0; break; case PRESSURE_SENSOR_BAROMETRIC: baroConvConsts.pressureSensitivity = getFPGABaroPressureSensitivity(); baroConvConsts.pressureSensitivityTempCoeff = getFPGABaroTempCoeffOfPressSensitvity(); baroConvConsts.pressureOffset = getFPGABaroPressureOffset(); baroConvConsts.pressureOffsetTempCoeff = getFPGABaroTempCoeffOfPressOffset(); pressureBeforeCal = calculateBaroPressure( (U32)adcSum ); pressures[ sensorId ].data = getCalibrationAppliedPressure( sensorId, pressureBeforeCal ); msrdPressureSum[ sensorId ] = 0; break; #ifndef _VECTORCAST_ default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_PRESSURE_SENSOR_SELECTED, sensorId ); break; #endif } } } monitorPressureSensors(); return result; } /*********************************************************************//** * @brief * The publishPressuresData function publishes DG pressures data at a set interval. * @details Inputs: pressuresDataPublicationTimerCounter * @details Outputs: pressuresDataPublicationTimerCounter * @return none *************************************************************************/ static void publishPressuresData( void ) { // publish pressure/occlusion data on interval if ( ++pressuresDataPublicationTimerCounter >= getU32OverrideValue( &pressuresDataPublishInterval ) ) { PRESSURES_DATA_T data; data.roPumpInletPressure = getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_INLET ); data.roPumpOutletPressure = getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_OUTLET ); data.drainPumpInletPressure = getMeasuredDGPressure( PRESSURE_SENSOR_DRAIN_PUMP_INLET ); data.drainPumpOutletPressure = getMeasuredDGPressure( PRESSURE_SENSOR_DRAIN_PUMP_OUTLET ); data.barometricPressure = getMeasuredDGPressure( PRESSURE_SENSOR_BAROMETRIC ); pressuresDataPublicationTimerCounter = 0; broadcastData( MSG_ID_DG_PRESSURES_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( PRESSURES_DATA_T ) ); } } /*********************************************************************//** * @brief * The calculateBaroPressure function calculates the barometric pressure * @details Inputs: measuredPressureReadingsSum * @details Outputs: none * @param adcSum sum of barometric pressure sensor ADC counts * @return barometric pressure in millibars *************************************************************************/ static F32 calculateBaroPressure( U32 adcSum ) { S32 tempDiff = getBaroSensorTemperatureDiff(); S64 tempOffset = ( baroConvConsts.pressureOffsetTempCoeff * tempDiff ) / TWO_TO_POWER_OF_6; S64 presOffset = baroConvConsts.pressureOffset * TWO_TO_POWER_OF_17; S64 offset = presOffset + tempOffset; S64 tempSensitivity = ( baroConvConsts.pressureSensitivityTempCoeff * tempDiff ) / TWO_TO_POWER_OF_7; S64 presSensitivity = baroConvConsts.pressureSensitivity * TWO_TO_POWER_OF_16; S64 sensitivity = tempSensitivity + presSensitivity; S32 pres = (S32)( ( ( adcSum * sensitivity ) / TWO_TO_POWER_OF_21 ) - offset ) / TWO_TO_POWER_OF_15; F32 presPSI = ( (F32)pres / (F32)( COUNTS_TO_MILLI_BAR * ONE_BAR_TO_MILLI_BAR ) ) * ONE_BAR_TO_PSI_CONVERSION; return presPSI; } /*********************************************************************//** * @brief * The getCalibrationAppliedPressure function applies the calibration values * to the provided pressure and returns the values. * @details Inputs: pressuresCalRecord * @details Outputs: none * @param sensorId the ID of the pressure sensor * @param pressure the pressure before applying calibration to it * @return calibration applied pressure *************************************************************************/ static F32 getCalibrationAppliedPressure( U08 sensorId, F32 pressure ) { F32 calPressure = pow( pressure, 4 ) * pressuresCalRecord.pressureSensors[ (PRESSURE_SENSORS_T)sensorId ].fourthOrderCoeff + pow( pressure, 3 ) * pressuresCalRecord.pressureSensors[ (PRESSURE_SENSORS_T)sensorId ].thirdOrderCoeff + pow( pressure, 2 ) * pressuresCalRecord.pressureSensors[ (PRESSURE_SENSORS_T)sensorId ].secondOrderCoeff + pressure * pressuresCalRecord.pressureSensors[ (PRESSURE_SENSORS_T)sensorId ].gain + pressuresCalRecord.pressureSensors[ (PRESSURE_SENSORS_T)sensorId ].offset; return calPressure; } /*********************************************************************//** * @brief * The getBaroPressurePSI function returns the barometric pressure value. * @details Inputs: none * @details Outputs: none * @return barometric pressure value *************************************************************************/ static F32 getBaroPressurePSI( void ) { F32 baroPressure = getF32OverrideValue( &pressures[ PRESSURE_SENSOR_BAROMETRIC ] ); #ifndef _RELEASE_ if ( HW_CONFIG_BETA == getHardwareConfigStatus() ) { baroPressure = PUMP_PRESSURE_PSIA_TO_PSI_OFFSET; } #endif return baroPressure; } /*********************************************************************//** * @brief * The monitorPressureSensors function monitors the pressure sensors to be * in range. * @details Inputs: none * @details Outputs: none * @return none *************************************************************************/ static void monitorPressureSensors( void ) { PRESSURE_SENSORS_T sensorId; PRESSURE_SENSORS_T sensorInAlarm = PRESSURE_FIRST; F32 pressureReading = 0.0F; BOOL isBaroOutOfRange = FALSE; BOOL isPressureOutOfRange = FALSE; F32 alarmPressure = 0.0F; for ( sensorId = PRESSURE_FIRST; sensorId < NUM_OF_PRESSURE_SENSORS; sensorId++ ) { switch ( sensorId ) { case PRESSURE_SENSOR_RO_PUMP_INLET: case PRESSURE_SENSOR_RO_PUMP_OUTLET: case PRESSURE_SENSOR_DRAIN_PUMP_INLET: case PRESSURE_SENSOR_DRAIN_PUMP_OUTLET: // Get the pressure and convert it back to absolute by adding back the baro pressure value // Check if the pressure is out of the upper or lower range // Bitwise OR the current pressure sensor with the total pressure sensor to persistent alarm check // Remember the ID of the pressure sensor that is out of range. The ID is converted to float since the check persistent alarm function // accepts only floats. pressureReading = getMeasuredDGPressure( sensorId ) + getBaroPressurePSI(); if ( ( pressureReading < MIN_VALID_PRESSURE_RANGE_PSIA ) || ( pressureReading > MAX_VALID_PRESSURE_RANGE_PSIA ) ) { isPressureOutOfRange = TRUE; sensorInAlarm = sensorId; alarmPressure = pressureReading; } break; case PRESSURE_SENSOR_BAROMETRIC: if ( baroConvConsts.pressureSensitivity != 0 ) { // Check the baro and alarm if out of range. Make sure the conversion coefficients of the sensor has been read and received from FPGA pressureReading = getBaroPressurePSI(); isBaroOutOfRange = ( ( pressureReading < MIN_VALID_BARO_PRESSURE_PSIA ) || ( pressureReading > MAX_VALID_BARO_PRESSURE_PSIA ) ? TRUE : FALSE ); checkPersistentAlarm( ALARM_ID_DG_BARO_PRESSURE_OUT_OF_RANGE, isBaroOutOfRange, (F32)sensorId, pressureReading ); } break; #ifndef _VECTORCAST_ default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_PRESSURE_SENSOR_SELECTED, sensorId ); break; #endif } } // Once the sensors were all checked to be out of range, check the persistent alarm checkPersistentAlarm( ALARM_ID_DG_PRESSURE_OUT_OF_RANGE, isPressureOutOfRange, sensorInAlarm, alarmPressure ); } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testSetPressuresDataPublishIntervalOverride function overrides the * pressure data publish interval. * @details Inputs: none * @details Outputs: pressuresDataPublishInterval * @param value value to override pressure data publish interval with (in ms) * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetPressuresDataPublishIntervalOverride( U32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { U32 intvl = value / TASK_PRIORITY_INTERVAL; result = TRUE; pressuresDataPublishInterval.ovData = intvl; pressuresDataPublishInterval.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetPressuresDataPublishIntervalOverride function resets the override * of the pressure and occlusion data publish interval. * @details Inputs: none * @details Outputs: pressuresDataPublishInterval * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetPressuresDataPublishIntervalOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; pressuresDataPublishInterval.override = OVERRIDE_RESET; pressuresDataPublishInterval.ovData = pressuresDataPublishInterval.ovInitData; } return result; } /*********************************************************************//** * @brief * The testSetDGPressureSensorOverride function overrides the value of the * specified pressure sensor with a given value. * @details Inputs: none * @details Outputs: pressures[] * @param sensor pressure sensor ID * @param value override value for pressure data * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetDGPressureSensorOverride( U32 sensor, F32 value ) { BOOL result = FALSE; if ( sensor < NUM_OF_PRESSURE_SENSORS ) { if ( TRUE == isTestingActivated() ) { result = TRUE; pressures[ sensor ].ovData = value; pressures[ sensor ].override = OVERRIDE_KEY; } } return result; } /*********************************************************************//** * @brief * The testResetDGPressureSensorOverride function resets the override of the \n * specified DG pressure sensor. * @details Inputs: none * @details Outputs: pressures[] * @param sensor pressure sensor ID * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testResetDGPressureSensorOverride( U32 sensor ) { BOOL result = FALSE; if ( sensor < NUM_OF_PRESSURE_SENSORS ) { if ( TRUE == isTestingActivated() ) { result = TRUE; pressures[ sensor ].override = OVERRIDE_RESET; pressures[ sensor ].ovData = pressures[ sensor ].ovInitData; } } return result; } /**@}*/