Index: firmware/App/Controllers/Pressures.c =================================================================== diff -u -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 -r58d631f8ce26bf420a3fa087d4d1d86833aba002 --- firmware/App/Controllers/Pressures.c (.../Pressures.c) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) +++ firmware/App/Controllers/Pressures.c (.../Pressures.c) (revision 58d631f8ce26bf420a3fa087d4d1d86833aba002) @@ -14,10 +14,12 @@ * @date (original) 04-Apr-2020 * ***************************************************************************/ +#include #include "AlarmMgmt.h" #include "FPGA.h" -#include "InternalADC.h" +#include "InternalADC.h" +#include "NVDataMgmt.h" #include "OperationModes.h" #include "PersistentAlarm.h" #include "Pressures.h" @@ -74,14 +76,16 @@ static U32 pressureFilterCounter = 0; ///< Used to schedule pressure sensor filtering. 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 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 U32 getPublishPressuresDataInterval( void ); +static U32 getPublishPressuresDataInterval( void ); +static BOOL processCalibrationData( void ); static SELF_TEST_STATUS_T handleSelfTestADCCheck( void ); @@ -94,7 +98,7 @@ *************************************************************************/ void initPressures( void ) { - U32 i; + U32 i; for ( i = 0; i < NUM_OF_PRESSURE_SENSORS; i++ ) { @@ -111,8 +115,84 @@ pressuresDataPublicationTimerCounter = 0; initPersistentAlarm( ALARM_ID_INLET_WATER_LOW_PRESSURE, INLET_WATER_PRESSURE_PERSISTENCE_PERIOD, INLET_WATER_PRESSURE_PERSISTENCE_PERIOD ); - initPersistentAlarm( ALARM_ID_INLET_WATER_PRESSURE_FAULT, INLET_WATER_PRESSURE_PERSISTENCE_PERIOD, INLET_WATER_PRESSURE_PERSISTENCE_PERIOD ); + initPersistentAlarm( ALARM_ID_INLET_WATER_PRESSURE_FAULT, INLET_WATER_PRESSURE_PERSISTENCE_PERIOD, INLET_WATER_PRESSURE_PERSISTENCE_PERIOD ); + + // TODO remove, temporary code + for ( i = 0; i < NUM_OF_CAL_DATA_PRES_SENSORS; i++ ) + { + pressuresCalRecord.pressureSensors[ i ].fourthOrderCoeff = 0.0; + pressuresCalRecord.pressureSensors[ i ].thirdOrderCoeff = 0.0; + pressuresCalRecord.pressureSensors[ i ].secondOrderCoeff = 0.0; + pressuresCalRecord.pressureSensors[ i ].gain = 1.0; + pressuresCalRecord.pressureSensors[ i ].offset = 0.0; + } + // TODO remove, temporary code } + +/*********************************************************************//** + * @brief + * The checkInletPressure 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 checkInletPressure( void ) +{ +#ifndef DISABLE_WATER_QUALITY_CHECK + F32 const pressure = getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_INLET ); + BOOL const isPressureTooLow = ( pressure < MIN_INLET_WATER_PRESSURE ); + + checkPersistentAlarm( ALARM_ID_INLET_WATER_LOW_PRESSURE, isPressureTooLow, pressure, MIN_INLET_WATER_PRESSURE ); +#endif +} + +/*********************************************************************//** + * @brief + * The checkInletPressureFault function checks inlet water pressure value + * and triggers a machine fault when pressure value is out of allowed range. + * @details Inputs: RO pump inlet pressure sensor value + * @details Outputs: Triggers pressure fault persistent alarm + * @return none + *************************************************************************/ +void checkInletPressureFault( void ) +{ + F32 const pressure = getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_INLET ); + BOOL const isPressureTooLow = ( pressure < MIN_INLET_WATER_PRESSURE ); + + checkPersistentAlarm( ALARM_ID_INLET_WATER_PRESSURE_FAULT, isPressureTooLow, pressure, MIN_INLET_WATER_PRESSURE ); +} + +/*********************************************************************//** + * @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.0; + + if ( pressureID < NUM_OF_PRESSURE_SENSORS ) + { + if ( OVERRIDE_KEY == pressures[ pressureID ].override ) + { + result = pressures[ pressureID ].ovData; + } + else + { + result = pressures[ pressureID ].data; + } + } + else + { + activateAlarmNoData( ALARM_ID_DG_SOFTWARE_FAULT ); + } + + return result; +} /*********************************************************************//** * @brief @@ -143,6 +223,39 @@ // 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: + pressuresSelfTestState = PRESSURE_TEST_STATE_IN_PROGRESS; + pressuresSelfTestResult = SELF_TEST_STATUS_IN_PROGRESS; + break; + + case PRESSURE_TEST_STATE_IN_PROGRESS: + pressuresSelfTestResult = handleSelfTestADCCheck(); + pressuresSelfTestState = PRESSURE_TEST_STATE_COMPLETE; + 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_TEMPERATURE_SENSORS_INVALID_SELF_TEST_STATE, pressuresSelfTestState ); + break; + } + + return pressuresSelfTestResult; } /*********************************************************************//** @@ -182,40 +295,62 @@ measuredPressureReadingsSum[ PRESSURE_SENSOR_RO_PUMP_INLET ] += measuredPressureReadingsRaw[ PRESSURE_SENSOR_RO_PUMP_INLET ]; measuredPressureReadingsSum[ PRESSURE_SENSOR_RO_PUMP_OUTLET ] += measuredPressureReadingsRaw[ PRESSURE_SENSOR_RO_PUMP_OUTLET ]; measuredPressureReadingsSum[ PRESSURE_SENSOR_DRAIN_PUMP_INLET ] += measuredPressureReadingsRaw[ PRESSURE_SENSOR_DRAIN_PUMP_INLET ]; - measuredPressureReadingsSum[ PRESSURE_SENSOR_DRAIN_PUMP_OUTLET ] += measuredPressureReadingsRaw[ PRESSURE_SENSOR_DRAIN_PUMP_OUTLET ]; + measuredPressureReadingsSum[ PRESSURE_SENSOR_DRAIN_PUMP_OUTLET ] += measuredPressureReadingsRaw[ PRESSURE_SENSOR_DRAIN_PUMP_OUTLET ]; + + // Check if a new calibration is available + if ( TRUE == isNewCalibrationRecordAvailable() ) + { + // Get the new calibration data and check its validity + processCalibrationData(); + } // filter every 200ms if ( ++pressureFilterCounter >= PRESSURE_SAMPLES_TO_AVERAGE ) - { // calculate average pressures + { + U32 sensor; + F32 pressuresBeforeCal[ NUM_OF_PRESSURE_SENSORS ]; + + // Calculate average pressures F32 avgRoIn = (F32)measuredPressureReadingsSum[ PRESSURE_SENSOR_RO_PUMP_INLET ] * PRESSURE_AVERAGE_MULTIPLIER; F32 avgRoOut = (F32)measuredPressureReadingsSum[ PRESSURE_SENSOR_RO_PUMP_OUTLET ] * PRESSURE_AVERAGE_MULTIPLIER; F32 avgDrnIn = (F32)measuredPressureReadingsSum[ PRESSURE_SENSOR_DRAIN_PUMP_INLET ] * PRESSURE_AVERAGE_MULTIPLIER; - F32 avgDrnOut = (F32)measuredPressureReadingsSum[ PRESSURE_SENSOR_DRAIN_PUMP_OUTLET ] * PRESSURE_AVERAGE_MULTIPLIER; + F32 avgDrnOut = (F32)measuredPressureReadingsSum[ PRESSURE_SENSOR_DRAIN_PUMP_OUTLET ] * PRESSURE_AVERAGE_MULTIPLIER; + + // Convert average pressure readings to PSI + pressuresBeforeCal[ PRESSURE_SENSOR_RO_PUMP_INLET ] = avgRoIn * PUMP_PRESSURE_PSIA_PER_COUNT - PUMP_PRESSURE_PSIA_TO_PSI_OFFSET; + pressuresBeforeCal[ PRESSURE_SENSOR_RO_PUMP_OUTLET ] = avgRoOut * PUMP_PRESSURE_PSIA_PER_COUNT - PUMP_PRESSURE_PSIA_TO_PSI_OFFSET; + pressuresBeforeCal[ PRESSURE_SENSOR_DRAIN_PUMP_INLET ] = avgDrnIn * PUMP_PRESSURE_PSIA_PER_COUNT - PUMP_PRESSURE_PSIA_TO_PSI_OFFSET; + pressuresBeforeCal[ PRESSURE_SENSOR_DRAIN_PUMP_OUTLET ] = avgDrnOut * PUMP_PRESSURE_PSIA_PER_COUNT - PUMP_PRESSURE_PSIA_TO_PSI_OFFSET; - // reset average counter - pressureFilterCounter = 0; + // Reset average counter + pressureFilterCounter = 0; + + // Apply calibration to the pressure values prior to storing them + for ( sensor = 0; sensor < NUM_OF_PRESSURE_SENSORS; sensor++ ) + { + pressures[ sensor ].data = pow(pressuresBeforeCal[ sensor ], 4) * pressuresCalRecord.pressureSensors[ sensor ].fourthOrderCoeff + + pow(pressuresBeforeCal[ sensor ], 3) * pressuresCalRecord.pressureSensors[ sensor ].thirdOrderCoeff + + pow(pressuresBeforeCal[ sensor ], 2) * pressuresCalRecord.pressureSensors[ sensor ].secondOrderCoeff + + pressuresBeforeCal[ sensor ] * pressuresCalRecord.pressureSensors[ sensor ].gain + + pressuresCalRecord.pressureSensors[ sensor ].offset; + } - // convert average pressure readings to PSI - pressures[ PRESSURE_SENSOR_RO_PUMP_INLET ].data = avgRoIn * PUMP_PRESSURE_PSIA_PER_COUNT - PUMP_PRESSURE_PSIA_TO_PSI_OFFSET; - pressures[ PRESSURE_SENSOR_RO_PUMP_OUTLET ].data = avgRoOut * PUMP_PRESSURE_PSIA_PER_COUNT - PUMP_PRESSURE_PSIA_TO_PSI_OFFSET; - pressures[ PRESSURE_SENSOR_DRAIN_PUMP_INLET ].data = avgDrnIn * PUMP_PRESSURE_PSIA_PER_COUNT - PUMP_PRESSURE_PSIA_TO_PSI_OFFSET; - pressures[ PRESSURE_SENSOR_DRAIN_PUMP_OUTLET ].data = avgDrnOut * PUMP_PRESSURE_PSIA_PER_COUNT - PUMP_PRESSURE_PSIA_TO_PSI_OFFSET; - // reset sums for next averaging measuredPressureReadingsSum[ PRESSURE_SENSOR_RO_PUMP_INLET ] = 0; measuredPressureReadingsSum[ PRESSURE_SENSOR_RO_PUMP_OUTLET ] = 0; measuredPressureReadingsSum[ PRESSURE_SENSOR_DRAIN_PUMP_INLET ] = 0; measuredPressureReadingsSum[ PRESSURE_SENSOR_DRAIN_PUMP_OUTLET ] = 0; - } - + } + // TODO - any other checks return result; } /*********************************************************************//** * @brief - * The getPublishPressuresDataInterval function gets the pressure data publish internval. + * The getPublishPressuresDataInterval function gets the pressure data + * publish interval. * @details Inputs: pressuresDataPublishInterval * @details Outputs: none * @return the current pressures data publication interval (in task intervals). @@ -230,75 +365,53 @@ } return result; -} +} /*********************************************************************//** * @brief - * The checkInletPressure 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 + * 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: loadCellsCalRecord + * @return TRUE if the calibration record is valid, otherwise FALSE *************************************************************************/ -void checkInletPressure( void ) +static BOOL processCalibrationData( void ) { -#ifndef DISABLE_WATER_QUALITY_CHECK - F32 const pressure = getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_INLET ); - BOOL const isPressureTooLow = ( pressure < MIN_INLET_WATER_PRESSURE ); + BOOL status = TRUE; + U32 sensor; - checkPersistentAlarm( ALARM_ID_INLET_WATER_LOW_PRESSURE, isPressureTooLow, pressure, MIN_INLET_WATER_PRESSURE ); + // Get the calibration record from NVDataMgmt + DG_PRES_SENSORS_CAL_RECORD_T calData = getDGPressureSensorsCalibrationRecord(); + + for ( sensor = 0; sensor < NUM_OF_CAL_DATA_PRES_SENSORS; sensor++ ) + { + // 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.pressureSensors[ sensor ].calibrationTime ) + { +#ifndef DISABLE_CAL_CHECK + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DG_PRESSURE_SENSORS_INVALID_CALIBRATION, (U32)sensor ); #endif -} + status = FALSE; + } + else + { + // The calibration data was valid, update the local copy + pressuresCalRecord.pressureSensors[ sensor ].fourthOrderCoeff = calData.pressureSensors[ sensor ].fourthOrderCoeff; + pressuresCalRecord.pressureSensors[ sensor ].thirdOrderCoeff = calData.pressureSensors[ sensor ].thirdOrderCoeff; + pressuresCalRecord.pressureSensors[ sensor ].secondOrderCoeff = calData.pressureSensors[ sensor ].secondOrderCoeff; + pressuresCalRecord.pressureSensors[ sensor ].gain = calData.pressureSensors[ sensor ].gain; + pressuresCalRecord.pressureSensors[ sensor ].offset = calData.pressureSensors[ sensor ].offset; + } + } -/*********************************************************************//** - * @brief - * The checkInletPressureFault function checks inlet water pressure value - * and triggers a machine fault when pressure value is out of allowed range. - * @details Inputs: RO pump inlet pressure sensor value - * @details Outputs: Triggers pressure fault persistent alarm - * @return none - *************************************************************************/ -void checkInletPressureFault( void ) -{ - F32 const pressure = getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_INLET ); - BOOL const isPressureTooLow = ( pressure < MIN_INLET_WATER_PRESSURE ); - - checkPersistentAlarm( ALARM_ID_INLET_WATER_PRESSURE_FAULT, isPressureTooLow, pressure, MIN_INLET_WATER_PRESSURE ); + return status; } /*********************************************************************//** * @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.0; - - if ( pressureID < NUM_OF_PRESSURE_SENSORS ) - { - if ( OVERRIDE_KEY == pressures[ pressureID ].override ) - { - result = pressures[ pressureID ].ovData; - } - else - { - result = pressures[ pressureID ].data; - } - } - else - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_PRESSURE_SENSOR_ID, pressureID ); - } - - return result; -} - -/*********************************************************************//** - * @brief * The publishPressuresData function publishes DG pressures data at a set interval. * @details Inputs: pressuresDataPublicationTimerCounter * @details Outputs: Pressures data are published to CAN bus @@ -319,39 +432,6 @@ } } -/*********************************************************************//** - * @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: - pressuresSelfTestState = PRESSURE_TEST_STATE_IN_PROGRESS; - pressuresSelfTestResult = SELF_TEST_STATUS_IN_PROGRESS; - break; - - case PRESSURE_TEST_STATE_IN_PROGRESS: - pressuresSelfTestResult = handleSelfTestADCCheck(); - pressuresSelfTestState = PRESSURE_TEST_STATE_COMPLETE; - 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_TEMPERATURE_SENSORS_INVALID_SELF_TEST_STATE, pressuresSelfTestState ); - break; - } - - return pressuresSelfTestResult; -} - /*********************************************************************//** * @brief * The handleSelfTestADCCheck function checks whether the ADC reads and @@ -366,7 +446,7 @@ SELF_TEST_STATUS_T result = SELF_TEST_STATUS_PASSED; U16 const inletPressureADCReading = getIntADCReading( INT_ADC_RO_PUMP_INLET_PRESSURE ); - if ( ( inletPressureADCReading == 0 ) || ( inletPressureADCReading >= INT_ADC_FULL_SCALE_BITS ) ) + if ( ( 0 == inletPressureADCReading ) || ( inletPressureADCReading >= INT_ADC_FULL_SCALE_BITS ) ) { result = SELF_TEST_STATUS_FAILED; SET_ALARM_WITH_1_U32_DATA( ALARM_ID_PRESSURE_SENSOR_FAULT, inletPressureADCReading );