Index: firmware/App/Controllers/ConductivitySensors.c =================================================================== diff -u -ra9315539f527b92523b1598ff91e47db4d71dae2 -r0803f828b81e046166457564650acf6a9bbd3cc6 --- firmware/App/Controllers/ConductivitySensors.c (.../ConductivitySensors.c) (revision a9315539f527b92523b1598ff91e47db4d71dae2) +++ firmware/App/Controllers/ConductivitySensors.c (.../ConductivitySensors.c) (revision 0803f828b81e046166457564650acf6a9bbd3cc6) @@ -8,7 +8,7 @@ * @file ConductivitySensors.c * * @author (last) Dara Navaei -* @date (last) 02-Mar-2022 +* @date (last) 31-Mar-2022 * * @author (original) Quang Nguyen * @date (original) 13-Jul-2020 @@ -40,20 +40,23 @@ #define COND_CPO_SENSOR_PROBE_TYPE 10 ///< 0.1 K cell constant conductivity probe. #define COND_SENSOR_DECIMAL_CONVERSION 100 ///< Conductivity value from FPGA has two decimal place. -#define COND_SENSOR_TEMPERATURE_COEF 0.02 ///< Linear temperature coefficient of variation at 25 Celcius for fresh water. +#define COND_SENSOR_TEMPERATURE_COEF 0.02F ///< Linear temperature coefficient of variation at 25 Celcius for fresh water. #define COND_SENSOR_REFERENCE_TEMPERATURE 25 ///< Reference temperature for conductivity sensor. #define COND_SENSOR_REPORT_PERIOD ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Broadcast conductivity values message every second. -#define COND_SENSOR_CPI_MAX_VALUE 2000 ///< Maximum inlet water conductivity. -#define COND_SENSOR_CPI_MIN_VALUE 100 ///< Minimum inlet water conductivity. +#define MAX_COND_SENSOR_CPI_WARNING_HIGH 2000.0F ///< Maximum allowed high conductivity value. +#define MIN_COND_SENSOR_CPI_WARNING_HIGH 1990.0F ///< Minimum allowed high conductivity value. +#define MAX_COND_SENSOR_CPI_WARNING_LOW 100.0F ///< Maximum allowed low conductivity value. +#define MIN_COND_SENSOR_CPI_WARNING_LOW 110.0F ///< Minimum allowed low conductivity value. + #define MAX_ALLOWED_UNCHANGED_CONDUCTIVITY_READS ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< New reading every 800 ms, expect to get valid new reading in 1s. #define MAX_CONDUCTIVITY_SENSOR_FAILURES 5 ///< maximum number of conductivity sensor errors within window period before alarm. #define MAX_CONDUCTIVITY_SENSOR_FAILURE_WINDOW_MS ( 60 * MS_PER_SECOND ) ///< Conductivity sensor error window. -#define RO_REJECTION_RATIO_OUT_OF_RANGE_VALUE 1.0 ///< Out of range value for RO rejection ratio when CPi conductivity is zero. -#define MAX_RO_REJECTION_RATIO_ALLOW 0.1 ///< Maximum RO rejection ratio. -#define MAX_CPO_CONDUCTIVITY_ALLOW 15.0 ///< Maximum CPo sensor conductivity value. +#define RO_REJECTION_RATIO_OUT_OF_RANGE_VALUE 1.0F ///< Out of range value for RO rejection ratio when CPi conductivity is zero. +#define MAX_RO_REJECTION_RATIO_ALLOW 0.10F ///< Maximum RO rejection ratio. +#define MAX_CPO_CONDUCTIVITY_ALLOW 30.0 ///< Maximum CPo sensor conductivity value. #define COND_SENSOR_PERSISTENCE_PERIOD ( 5 * MS_PER_SECOND ) ///< Persistence period for conductivity sensor out of range error. #define RO_REJECTION_RATIO_PERSISTENCE_PERIOD ( 10 * MS_PER_SECOND ) ///< Persistence period for RO rejection ratio. @@ -63,6 +66,7 @@ #define EMSTAT_PICO_TIMING_NOT_MET_STATUS 0x11 ///< Measurement takes too long status. #define EMSTAT_PICO_FIFO_EMPTY_MASK 0x8000 ///< Emstat Pico buffer empty indication bit. #define DATA_PUBLISH_COUNTER_START_COUNT 40 ///< Data publish counter start count. +#define COND_SENSOR_BAD_STATUS_PERSISTENCE_PERIOD ( 1 * MS_PER_SECOND ) ///< Conductivity sensor bad status persistence period. #pragma pack(push,1) /// Emstat pico measurement data package structure @@ -93,12 +97,13 @@ static OVERRIDE_F32_T compensatedConductivityValues[ NUM_OF_CONDUCTIVITY_SENSORS ]; ///< Latest compensated conductivity values. static F32 rawConductivityValues[ NUM_OF_CONDUCTIVITY_SENSORS ]; ///< Latest raw conductivity values. static F32 roRejectionRatio; ///< Latest RO rejection ratio. +static U32 sensorStatus[ NUM_OF_CONDUCTIVITY_SENSORS ]; ///< Latest sensor hardware status. static OVERRIDE_U32_T conductivityDataPublishInterval = { COND_SENSOR_REPORT_PERIOD, COND_SENSOR_REPORT_PERIOD, 0, 0 }; ///< Conductivity sensors publish time interval override. static U32 conductivityDataPublicationTimerCounter; ///< Conductivity sensors data publish timer counter. -static BOOL packageStarted = FALSE; ///< Flag to indicate the start of a package measurement data. +static BOOL packageStarted; ///< Flag to indicate the start of a package measurement data. static U08 packageIndex; ///< Current package measurement data bytes index. static U08 package[ 50 ]; ///< Storage of package bytes until ready to process. static DG_COND_SENSORS_CAL_RECORD_T condSensorsCalRecord; ///< Conductivity sensors' calibration record. @@ -124,30 +129,36 @@ void initConductivitySensors( void ) { U32 i; + roRejectionRatio = 0.0; packageIndex = 0U; + packageStarted = FALSE; conductivityDataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; for ( i = 0; i < NUM_OF_CONDUCTIVITY_SENSORS; i++ ) { - readCount[ i ] = 0; - internalErrorCount[ i ] = 0; + readCount[ i ] = 0; + internalErrorCount[ i ] = 0; + rawConductivityValues[ i ] = 0.0; - compensatedConductivityValues[ i ].data = 0.0; - compensatedConductivityValues[ i ].ovData = 0.0; + compensatedConductivityValues[ i ].data = 0.0; + compensatedConductivityValues[ i ].ovData = 0.0; compensatedConductivityValues[ i ].ovInitData = 0.0; - compensatedConductivityValues[ i ].override = OVERRIDE_RESET; + compensatedConductivityValues[ i ].override = OVERRIDE_RESET; - rawConductivityValues[ i ] = 0.0; + benignPolynomialCalRecord( &condSensorsCalRecord.condSensors[ i ] ); } setFPGACPiProbeType( COND_CPI_SENSOR_PROBE_TYPE ); setFPGACPoProbeType( COND_CPO_SENSOR_PROBE_TYPE ); initTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_CONDUCTIVITY_SENSOR_ERROR, MAX_CONDUCTIVITY_SENSOR_FAILURES, MAX_CONDUCTIVITY_SENSOR_FAILURE_WINDOW_MS ); initPersistentAlarm( ALARM_ID_INLET_WATER_HIGH_CONDUCTIVITY, COND_SENSOR_PERSISTENCE_PERIOD, COND_SENSOR_PERSISTENCE_PERIOD ); - initPersistentAlarm( ALARM_ID_INLET_WATER_LOW_CONDUCTIVITY, COND_SENSOR_PERSISTENCE_PERIOD, COND_SENSOR_PERSISTENCE_PERIOD ); + initPersistentAlarm( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_HIGH_RANGE, COND_SENSOR_PERSISTENCE_PERIOD, COND_SENSOR_PERSISTENCE_PERIOD ); + initPersistentAlarm( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_LOW_RANGE, COND_SENSOR_PERSISTENCE_PERIOD, COND_SENSOR_PERSISTENCE_PERIOD ); initPersistentAlarm( ALARM_ID_RO_REJECTION_RATIO_OUT_OF_RANGE, RO_REJECTION_RATIO_PERSISTENCE_PERIOD, RO_REJECTION_RATIO_PERSISTENCE_PERIOD ); + initPersistentAlarm( ALARM_ID_DG_CONDUCTIVITY_SENSOR_BAD_STATUS, COND_SENSOR_BAD_STATUS_PERSISTENCE_PERIOD, COND_SENSOR_BAD_STATUS_PERSISTENCE_PERIOD ); + initPersistentAlarm( ALARM_ID_DG_OUTLET_PRIMARY_CONDUCTIVITY_OUT_OF_RANGE, COND_SENSOR_PERSISTENCE_PERIOD, COND_SENSOR_PERSISTENCE_PERIOD ); } /*********************************************************************//** @@ -191,6 +202,11 @@ data.cd1Raw = rawConductivityValues[ CONDUCTIVITYSENSORS_CD1_SENSOR ]; data.cd2Raw = rawConductivityValues[ CONDUCTIVITYSENSORS_CD2_SENSOR ]; + data.cpiSensorStatus = sensorStatus[ CONDUCTIVITYSENSORS_CPI_SENSOR ]; + data.cpoSensorStatus = sensorStatus[ CONDUCTIVITYSENSORS_CPO_SENSOR ]; + data.cd1SensorStatus = sensorStatus[ CONDUCTIVITYSENSORS_CD1_SENSOR ]; + data.cd2SensorStatus = sensorStatus[ CONDUCTIVITYSENSORS_CD2_SENSOR ]; + broadcastData( MSG_ID_DG_CONDUCTIVITY_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( CONDUCTIVITY_DATA_T ) ); } } @@ -225,21 +241,43 @@ /*********************************************************************//** * @brief * The checkInletWaterConductivity function checks inlet water conductivity value - * and triggers an alarm when conductivity value is out of allowed range. + * and triggers an alarm when conductivity value is not within the specified + * values. * @details Inputs: CPi sensor conductivity - * @details Outputs: Trigger alarms when conductivity is out of allowed range + * @details Outputs: Trigger warning alarm if conductivity is in the warning + * range. Trigger alarm if conductivity is below minimum conductivity. * @return none *************************************************************************/ void checkInletWaterConductivity( void ) { -#ifndef DISABLE_WATER_QUALITY_CHECK - F32 const conductivity = getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ); - BOOL const isCondTooHigh = ( conductivity > COND_SENSOR_CPI_MAX_VALUE ); - BOOL const isCondTooLow = ( conductivity < COND_SENSOR_CPI_MIN_VALUE ); - - checkPersistentAlarm( ALARM_ID_INLET_WATER_HIGH_CONDUCTIVITY, isCondTooHigh, conductivity, COND_SENSOR_CPI_MAX_VALUE ); - checkPersistentAlarm( ALARM_ID_INLET_WATER_LOW_CONDUCTIVITY, isCondTooLow, conductivity, COND_SENSOR_CPI_MIN_VALUE ); +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_WATER_QUALITY_CHECK ) != SW_CONFIG_ENABLE_VALUE ) #endif + { + F32 conductivity = getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ); + BOOL isConductTooLow = ( conductivity < MAX_COND_SENSOR_CPI_WARNING_LOW ? TRUE : FALSE ); + BOOL isConductInWarningRange = ( conductivity > MAX_COND_SENSOR_CPI_WARNING_HIGH ? TRUE : FALSE ); + + // Warning per PRS 403 + if ( TRUE == isConductTooLow ) + { + checkPersistentAlarm( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_LOW_RANGE, isConductTooLow, conductivity, MAX_COND_SENSOR_CPI_WARNING_LOW ); + } + else if ( conductivity >= MIN_COND_SENSOR_CPI_WARNING_LOW ) + { + checkPersistentAlarm( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_LOW_RANGE, FALSE, conductivity, MAX_COND_SENSOR_CPI_WARNING_LOW ); + } + + // Warning per PRS 404 + if ( TRUE == isConductInWarningRange ) + { + checkPersistentAlarm( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_HIGH_RANGE, isConductInWarningRange, conductivity, MAX_COND_SENSOR_CPI_WARNING_HIGH ); + } + else if ( conductivity <= MIN_COND_SENSOR_CPI_WARNING_HIGH ) + { + checkPersistentAlarm( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_HIGH_RANGE, FALSE, conductivity, MAX_COND_SENSOR_CPI_WARNING_HIGH ); + } + } } /*********************************************************************//** @@ -253,12 +291,20 @@ *************************************************************************/ void checkRORejectionRatio( void ) { -#ifndef DISABLE_RO_RATIO_CHECK - F32 const cpo = getConductivityValue( CONDUCTIVITYSENSORS_CPO_SENSOR ); - BOOL const isRORejectionRatioOutOfRange = ( roRejectionRatio > MAX_RO_REJECTION_RATIO_ALLOW ) || ( cpo >= MAX_CPO_CONDUCTIVITY_ALLOW ); - - checkPersistentAlarm( ALARM_ID_RO_REJECTION_RATIO_OUT_OF_RANGE, isRORejectionRatioOutOfRange, roRejectionRatio, MAX_RO_REJECTION_RATIO_ALLOW ); +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_RO_RATIO_CHECK ) != SW_CONFIG_ENABLE_VALUE ) #endif + { + F32 cpo = getConductivityValue( CONDUCTIVITYSENSORS_CPO_SENSOR ); + BOOL isRORectionOutOfRange = ( roRejectionRatio > MAX_RO_REJECTION_RATIO_ALLOW ? TRUE : FALSE ); + BOOL isCPoOutOfRange = ( cpo >= MAX_CPO_CONDUCTIVITY_ALLOW ? TRUE : FALSE ); + + // Fault alarm per PRS 483 + checkPersistentAlarm( ALARM_ID_DG_OUTLET_PRIMARY_CONDUCTIVITY_OUT_OF_RANGE, isCPoOutOfRange, cpo, MAX_CPO_CONDUCTIVITY_ALLOW ); + + // Fault alarm per PRS 483 + checkPersistentAlarm( ALARM_ID_RO_REJECTION_RATIO_OUT_OF_RANGE, isRORectionOutOfRange, roRejectionRatio, MAX_RO_REJECTION_RATIO_ALLOW ); + } } /*********************************************************************//** @@ -299,10 +345,10 @@ *************************************************************************/ static F32 calcCompensatedConductivity( F32 conductivity, F32 temperature ) { - // EC = EC_25 * (1 + temp_coef * ( 25 - temperature )) - F32 const compensatedCoef = ( 1.0 + ( COND_SENSOR_TEMPERATURE_COEF * ( COND_SENSOR_REFERENCE_TEMPERATURE - temperature ) ) ); + // EC = EC_25 * (1 + temp_coef * ( temperature - 25 )) + F32 const compensatedCoef = ( 1.0 + ( COND_SENSOR_TEMPERATURE_COEF * ( temperature - COND_SENSOR_REFERENCE_TEMPERATURE ) ) ); - return conductivity * compensatedCoef; + return conductivity / compensatedCoef; } /*********************************************************************//** @@ -346,9 +392,9 @@ { if ( ( readCount[ sensorId ] != fpgaReadCount ) ) { - F32 const temperature = getTemperatureValue( associateTempSensor[ sensorId ] ); - F32 const conductivity = ( (F32)( fgpaRead ) / COND_SENSOR_DECIMAL_CONVERSION ); - F32 const compensatedCond = calcCompensatedConductivity( conductivity, temperature ); + F32 temperature = getTemperatureValue( associateTempSensor[ sensorId ] ); + F32 conductivity = ( (F32)( fgpaRead ) / COND_SENSOR_DECIMAL_CONVERSION ); + F32 compensatedCond = calcCompensatedConductivity( conductivity, temperature ); readCount[ sensorId ] = fpgaReadCount; internalErrorCount[ sensorId ] = 0; @@ -360,19 +406,25 @@ ++internalErrorCount[ sensorId ]; if ( internalErrorCount[ sensorId ] > MAX_ALLOWED_UNCHANGED_CONDUCTIVITY_READS ) { -#ifndef DISABLE_COND_SENSOR_CHECK - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_CONDUCTIVITY_SENSOR_FAULT, sensorId ); +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_COND_SENSOR_CHECK ) != SW_CONFIG_ENABLE_VALUE ) #endif + { + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_CONDUCTIVITY_SENSOR_FAULT, sensorId ); + } } } } else { if ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_CONDUCTIVITY_SENSOR_ERROR ) ) { -#ifndef DISABLE_COND_SENSOR_CHECK - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_CONDUCTIVITY_SENSOR_FAULT, sensorId ); +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_COND_SENSOR_CHECK ) != SW_CONFIG_ENABLE_VALUE ) #endif + { + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_CONDUCTIVITY_SENSOR_FAULT, sensorId ); + } } } } @@ -420,31 +472,34 @@ static void processMeasurementDataPackage( U32 sensorId ) { EMSTAT_VARIABLE_T const * const measurementPtr = (EMSTAT_VARIABLE_T *)&package; - U32 const status = hexStrToDec( (U08 *)&measurementPtr->status, sizeof( measurementPtr->status ) ); + U32 status = hexStrToDec( (U08 *)&measurementPtr->status, sizeof( measurementPtr->status ) ); + sensorStatus[ sensorId ] = status; if ( EMSTAT_PICO_GOOD_STATUS == status ) { - U32 const prefix = prefixStrToSIFactor( measurementPtr->prefix ); - F32 const resistance = ( ( F32 )( hexStrToDec( measurementPtr->value, sizeof( measurementPtr->value ) ) - EMSTAT_PICO_MEASUREMENT_OFFSET ) / prefix ); - F32 const temperature = getTemperatureValue( associateTempSensor[ sensorId ] ); - F32 const conductivity = ( 1 / resistance * SIEMENS_TO_MICROSIEMENS_CONVERSION ); - F32 const compensatedCond = calcCompensatedConductivity( conductivity, temperature ); + U32 prefix = prefixStrToSIFactor( measurementPtr->prefix ); + F32 resistance = ( ( F32 )( hexStrToDec( measurementPtr->value, sizeof( measurementPtr->value ) ) - EMSTAT_PICO_MEASUREMENT_OFFSET ) / prefix ); + F32 temperature = getTemperatureValue( associateTempSensor[ sensorId ] ); + F32 conductivity = ( 1.0 / resistance * SIEMENS_TO_MICROSIEMENS_CONVERSION ); + F32 compensatedCond = calcCompensatedConductivity( conductivity, temperature ); - internalErrorCount[ sensorId ] = 0; + internalErrorCount[ sensorId ] = 0; compensatedConductivityValues[ sensorId ].data = getCalibrationAppliedConductivityValue( sensorId, compensatedCond ); - rawConductivityValues[ sensorId ] = conductivity; // store raw conductivity data from CD1 and CD2 + rawConductivityValues[ sensorId ] = conductivity; // store raw conductivity data from CD1 and CD2 + // Clear the alarm + checkPersistentAlarm( ALARM_ID_DG_CONDUCTIVITY_SENSOR_BAD_STATUS, FALSE, status, EMSTAT_PICO_GOOD_STATUS ); } else { - compensatedConductivityValues[ sensorId ].data = 0.0; - rawConductivityValues[ sensorId ] = 0.0; +#ifndef DISABLE_COND_STATUS_CHECK + checkPersistentAlarm( ALARM_ID_DG_CONDUCTIVITY_SENSOR_BAD_STATUS, TRUE, status, EMSTAT_PICO_GOOD_STATUS ); +#endif } if ( EMSTAT_PICO_TIMING_NOT_MET_STATUS == status ) { - ++internalErrorCount[ sensorId ]; - if ( internalErrorCount[ sensorId ] > MAX_CONDUCTIVITY_SENSOR_FAILURES ) + if ( ++internalErrorCount[ sensorId ] > MAX_CONDUCTIVITY_SENSOR_FAILURES ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_CONDUCTIVITY_SENSOR_FAULT, sensorId ); } @@ -510,9 +565,12 @@ { if ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_CONDUCTIVITY_SENSOR_ERROR ) ) { -#ifndef DISABLE_COND_SENSOR_CHECK - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_CONDUCTIVITY_SENSOR_FAULT, CONDUCTIVITYSENSORS_CD1_SENSOR, CONDUCTIVITYSENSORS_CD2_SENSOR ); +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_COND_SENSOR_CHECK ) != SW_CONFIG_ENABLE_VALUE ) #endif + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_CONDUCTIVITY_SENSOR_FAULT, CONDUCTIVITYSENSORS_CD1_SENSOR, CONDUCTIVITYSENSORS_CD2_SENSOR ); + } } } }