Index: firmware/App/Controllers/ConductivitySensors.c =================================================================== diff -u -r8c3db9c2d3957a1a9d53ad5d20d9594a09bc21be -r2505e43eaab426e0de49f67ebb9b78efcfd13f55 --- firmware/App/Controllers/ConductivitySensors.c (.../ConductivitySensors.c) (revision 8c3db9c2d3957a1a9d53ad5d20d9594a09bc21be) +++ firmware/App/Controllers/ConductivitySensors.c (.../ConductivitySensors.c) (revision 2505e43eaab426e0de49f67ebb9b78efcfd13f55) @@ -16,8 +16,10 @@ ***************************************************************************/ #include "ConductivitySensors.h" -#include "SystemCommMessages.h" #include "FPGA.h" +#include "PersistentAlarm.h" +#include "SystemCommMessages.h" +#include "TaskGeneral.h" #include "TaskPriority.h" #include "TemperatureSensors.h" #include "Utilities.h" @@ -29,43 +31,53 @@ // ********** private definitions ********** -#define COND_SENSOR_PROBE_TYPE 100 ///< 1K 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_REFERENCE_TEMPERATURE 25 ///< Reference temperature for conductivity sensor -#define COND_SENSOR_REPORT_PERIOD (1000 / TASK_PRIORITY_INTERVAL) ///< Broadcast conductivity values message every 1000 ms. +#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_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_CPO_MAX_VALUE 2000 ///< Maximum inlet water conductivity -#define COND_SENSOR_CPI_CPO_MIN_VALUE 100 ///< Minimum inlet water conductivity +#define COND_SENSOR_CPI_CPO_MAX_VALUE 2000 ///< Maximum inlet water conductivity. +#define COND_SENSOR_CPI_CPO_MIN_VALUE 100 ///< Minimum inlet water conductivity. +#define COND_SENSOR_PERSISTENCE_COUNT (5 * MS_PER_SECOND / TASK_GENERAL_INTERVAL) ///< Number of persistence count for conductivity sensor out of range error. -#define MAX_ALLOWED_UNCHANGED_CONDUCTIVITY_READS 100 ///< New reading every 640 ms, expect to get 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 MAX_ALLOWED_UNCHANGED_CONDUCTIVITY_READS 100 ///< New reading every 640 ms, expect to get 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_REPORT_PERIOD (MS_PER_SECOND / TASK_PRIORITY_INTERVAL) ///< Broadcast RO rejection ratio message every second. +#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_PERSISTENCE_COUNT (10 * MS_PER_SECOND / TASK_GENERAL_INTERVAL) ///< Number of persistence count for RO rejection ratio. + // ********** private data ********** /// Conductivity sensors' associated temperature sensors -static U32 associateTempSensor[ NUM_OF_CONDUCTIVITY_SENSORS ] = { - TEMPSENSORS_INLET_PRIMARY_HEATER, ///< Inlet temperature sensor - TEMPSENSORS_OUTLET_PRIMARY_HEATER, ///< Outlet temperature sensor +static U32 associateTempSensor[ NUM_OF_CONDUCTIVITY_SENSORS ] = +{ + TEMPSENSORS_INLET_PRIMARY_HEATER, ///< Inlet temperature sensor + TEMPSENSORS_OUTLET_PRIMARY_HEATER, ///< Outlet temperature sensor }; -static U08 readCount[ NUM_OF_CONDUCTIVITY_SENSORS ]; ///< Read count for conductivity readings. -static U32 internalErrorCount[ NUM_OF_CONDUCTIVITY_SENSORS ]; ///< Internal error count for conductivity readings. -static OVERRIDE_F32_T compensatedConductivityValues[ NUM_OF_CONDUCTIVITY_SENSORS ]; ///< Latest compensated conductivity values. +static U08 readCount[ NUM_OF_CONDUCTIVITY_SENSORS ]; ///< Read count for conductivity readings. +static U32 internalErrorCount[ NUM_OF_CONDUCTIVITY_SENSORS ]; ///< Internal error count for conductivity readings. +static OVERRIDE_F32_T compensatedConductivityValues[ NUM_OF_CONDUCTIVITY_SENSORS ]; ///< Latest compensated conductivity values. +static F32 roRejectionRatio; ///< Latest RO rejection ratio. static OVERRIDE_U32_T conductivityDataPublishInterval = { COND_SENSOR_REPORT_PERIOD, - COND_SENSOR_REPORT_PERIOD, 0, 0 }; ///< Conductivity sensors publish time interval override -static U32 conductivityDataPublicationTimerCounter = 0; ///< Conductivity sensors data publish timer counter + COND_SENSOR_REPORT_PERIOD, 0, 0 }; ///< Conductivity sensors publish time interval override. +static U32 conductivityDataPublicationTimerCounter = 0; ///< Conductivity sensors data publish timer counter. // ********** private function prototypes ********** -static void processCPiCPoSensorRead( U32 sensorId, U32 fgpaRead, U08 fpgaReadCount, U08 fpgaErrorCount ); +static F32 getConductivityValue( U32 sensorId ); static F32 calcCompensatedConductivity( F32 conductivity, F32 temperature); +static void calcRORejectionRatio( void ); +static void processCPiCPoSensorRead( U32 sensorId, U32 fgpaRead, U08 fpgaReadCount, U08 fpgaErrorCount, U08 fpgaSensorFault ); +static U32 getConductivityDataPublishInterval( void ); -static DATA_GET_PROTOTYPE( U32, getConductivityDataPublishInterval ); - -/************************************************************************* +/*********************************************************************//** * @brief * The initConductivitySensors function initializes the ConductivitySensors module. * @details @@ -76,6 +88,7 @@ void initConductivitySensors( void ) { U32 i; + roRejectionRatio = 0.0; for ( i = 0; i < NUM_OF_CONDUCTIVITY_SENSORS; i++ ) { @@ -86,16 +99,20 @@ compensatedConductivityValues[ i ].ovData = 0.0; compensatedConductivityValues[ i ].ovInitData = 0.0; compensatedConductivityValues[ i ].override = OVERRIDE_RESET; - - // TODO: Ability to change probe type -// setFPGAConductivityProbeType( COND_SENSOR_PROBE_TYPE ); } - initTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_CONDUCTIVITY_SENSOR_ERROR, - MAX_CONDUCTIVITY_SENSOR_FAILURES, MAX_CONDUCTIVITY_SENSOR_FAILURE_WINDOW_MS ); + 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( PERSISTENT_ALARM_INLET_WATER_HIGH_CONDUCTIVITY, ALARM_ID_INLET_WATER_HIGH_CONDUCTIVITY, + TRUE, COND_SENSOR_PERSISTENCE_COUNT, COND_SENSOR_PERSISTENCE_COUNT ); + initPersistentAlarm( PERSISTENT_ALARM_INLET_WATER_LOW_CONDUCTIVITY, ALARM_ID_INLET_WATER_LOW_CONDUCTIVITY, + TRUE, COND_SENSOR_PERSISTENCE_COUNT, COND_SENSOR_PERSISTENCE_COUNT ); + initPersistentAlarm( PERSISTENT_ALARM_RO_REJECTION_RATIO_OUT_OF_RANGE, ALARM_ID_RO_REJECTION_RATIO_OUT_OF_RANGE, + TRUE, RO_REJECTION_RATIO_PERSISTENCE_COUNT, RO_REJECTION_RATIO_PERSISTENCE_COUNT ); } -/************************************************************************* +/*********************************************************************//** * @brief * The execConductivitySensors function gets conductivity sensors' latest * readings from FPGA and advertises them over CAN. @@ -106,54 +123,68 @@ *************************************************************************/ void execConductivitySensors( void ) { - processCPiCPoSensorRead( CONDUCTIVITYSENSORS_CPI_SENSOR, getFPGACPi(), getFPGACPiReadCount(), getFPGACPiErrorCount() ); - processCPiCPoSensorRead( CONDUCTIVITYSENSORS_CPO_SENSOR, getFPGACPi(), getFPGACPoReadCount(), getFPGACPoErrorCount() ); + processCPiCPoSensorRead( CONDUCTIVITYSENSORS_CPI_SENSOR, getFPGACPi(), getFPGACPiReadCount(), getFPGACPiErrorCount(), getFPGACPiFault() ); + processCPiCPoSensorRead( CONDUCTIVITYSENSORS_CPO_SENSOR, getFPGACPo(), getFPGACPoReadCount(), getFPGACPoErrorCount(), getFPGACPoFault() ); if ( ++conductivityDataPublicationTimerCounter >= getConductivityDataPublishInterval() ) { conductivityDataPublicationTimerCounter = 0; - broadcastConductivityData( getConductivityValue(CONDUCTIVITYSENSORS_CPI_SENSOR), + calcRORejectionRatio(); + broadcastConductivityData( roRejectionRatio, getConductivityValue(CONDUCTIVITYSENSORS_CPI_SENSOR), getConductivityValue(CONDUCTIVITYSENSORS_CPO_SENSOR) ); } + } -/************************************************************************* +/*********************************************************************//** * @brief * The checkInletWaterConductivity checks inlet water conductivity value * and triggers an alarm when conductivity value is out of allowed range. * @details - * Inputs : none + * Inputs : CPi sensor conductivity * Outputs : Trigger alarms when conductivity is out of allowed range - * @param state : Operational state of DG * @return none *************************************************************************/ -void checkInletWaterConductivity( U32 state ) +void checkInletWaterConductivity( void ) { - F32 const conductivity = getConductivityValue(CONDUCTIVITYSENSORS_CPI_SENSOR); - if ( conductivity > COND_SENSOR_CPI_CPO_MAX_VALUE ) - { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_INLET_WATER_HIGH_CONDUCTIVITY, conductivity, state ); - } + F32 const conductivity = getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ); + BOOL const isCondTooHigh = ( conductivity > COND_SENSOR_CPI_CPO_MAX_VALUE ); + BOOL const isCondTooLow = ( conductivity < COND_SENSOR_CPI_CPO_MIN_VALUE ); - if ( conductivity < COND_SENSOR_CPI_CPO_MIN_VALUE ) - { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_INLET_WATER_LOW_CONDUCTIVITY, conductivity, state ); - } + checkPersistentAlarm( PERSISTENT_ALARM_INLET_WATER_HIGH_CONDUCTIVITY, isCondTooHigh, conductivity ); + checkPersistentAlarm( PERSISTENT_ALARM_INLET_WATER_LOW_CONDUCTIVITY, isCondTooLow, conductivity ); } -/************************************************************************* +/*********************************************************************//** * @brief + * The checkRORejectionRatio checks RO rejection ratio and outlet water + * conductivity. The function triggers an alarm when RO rejection ratio or + * outlet water conductivity is out of allowed range for period of time. + * @details + * Inputs : roRejectionRatio, CPo sensor conductivity + * Outputs : Triggered alarm + * @return none + *************************************************************************/ +void checkRORejectionRatio( void ) +{ + F32 const cpo = getConductivityValue( CONDUCTIVITYSENSORS_CPO_SENSOR ); + BOOL const isRORejectionRatioOutOfRange = ( roRejectionRatio > MAX_RO_REJECTION_RATIO_ALLOW ) || ( cpo >= MAX_CPO_CONDUCTIVITY_ALLOW ); + checkPersistentAlarm( PERSISTENT_ALARM_RO_REJECTION_RATIO_OUT_OF_RANGE, isRORejectionRatioOutOfRange, roRejectionRatio ); +} + +/*********************************************************************//** + * @brief * The getConductivityValue function gets the compensated conductivity * value for a given conductivity sensor id. * @details * Inputs : compensatedConductivityValues[] * Outputs : none - * @param sensorId : Id of conductivity sensor to get conductivity value + * @param sensorId conductivity sensor id * @return compensated conductivity *************************************************************************/ -F32 getConductivityValue( U32 sensorId ) +static F32 getConductivityValue( U32 sensorId ) { - F32 result = 0; + F32 result = 0.0; if ( sensorId < NUM_OF_CONDUCTIVITY_SENSORS ) { @@ -174,45 +205,67 @@ return result; } -/************************************************************************* +/*********************************************************************//** * @brief * The calcCompensatedConductivity function calculates the compensated * conductivity based on given temperature and conductivity taken at * reference temperature of 25 Celcius. * @details - * Inputs : temperature + * Inputs : conductivity, temperature * Outputs : none - * @param conductivity : Conductivity value - * @param temperature : Temperature to compensate conductivity with + * @param conductivity conductivity value + * @param temperature temperature to compensate conductivity with * @return compensated conductivity based on temperature *************************************************************************/ static F32 calcCompensatedConductivity( F32 conductivity, F32 temperature) { // EC = EC_25 * (1 + temp_coef * (temperature - 25)) - F32 const compensatedCoef = ( 1 + ( COND_SENSOR_TEMPERATURE_COEF * (temperature - COND_SENSOR_REFERENCE_TEMPERATURE) ) ); + F32 const compensatedCoef = ( 1.0 + ( COND_SENSOR_TEMPERATURE_COEF * (temperature - COND_SENSOR_REFERENCE_TEMPERATURE) ) ); return conductivity * compensatedCoef; } -/************************************************************************* +/*********************************************************************//** * @brief + * The calcRORejectionRatio function calculates the RO rejection ratio using + * the CPi sensor conductivity value and CPo sensor conductivity value. + * @details + * Inputs: CPi sensor conductivity, CPo sensor conductivity + * Outputs: RO rejection ratio + * @return none + *************************************************************************/ +static void calcRORejectionRatio( void ) +{ + F32 const cpi = getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ); + F32 const cpo = getConductivityValue( CONDUCTIVITYSENSORS_CPO_SENSOR ); + roRejectionRatio = RO_REJECTION_RATIO_OUT_OF_RANGE_VALUE; + + if ( fabs(cpi) >= NEARLY_ZERO ) + { + roRejectionRatio = cpo / cpi; + } +} + +/*********************************************************************//** + * @brief * The processCPiCPoSensorRead function checks if there is an error in FPGA * and FPGA read count. If there is any error in the FPGA error, it raises an * alarm. If the read count has changed, the new reading will be processed. * @details * Inputs : none * Outputs : none - * @param sensorId : Conductivity sensor id to process - * @param fgpaRead : FPGA conductivity reading value - * @param fpgaReadCount : FPGA read count - * @param fpgaErrorCount : FPGA error count + * @param sensorId Conductivity sensor id to process + * @param fgpaRead FPGA conductivity reading value + * @param fpgaReadCount FPGA read count + * @param fpgaErrorCount FPGA error count + * @param fpgaSensorFault FPGA sensor fault * @return none *************************************************************************/ -static void processCPiCPoSensorRead( U32 sensorId, U32 fgpaRead, U08 fpgaReadCount, U08 fpgaErrorCount ) +static void processCPiCPoSensorRead( U32 sensorId, U32 fgpaRead, U08 fpgaReadCount, U08 fpgaErrorCount, U08 fpgaSensorFault ) { - if ( fpgaErrorCount == 0 ) + if ( ( fpgaErrorCount == 0 ) && ( fpgaSensorFault == 0 ) ) { - if ( (readCount[ sensorId ] != fpgaReadCount) ) + if ( ( readCount[ sensorId ] != fpgaReadCount ) ) { F32 const temperature = getTemperatureValue( associateTempSensor[ sensorId ] ); F32 const conductivity = ( (F32)( fgpaRead ) / COND_SENSOR_DECIMAL_CONVERSION ); @@ -238,7 +291,7 @@ } } -/************************************************************************* +/*********************************************************************//** * @brief * The getConductivityDataPublishInterval function gets the conductivity * data publication interval. @@ -265,15 +318,15 @@ *************************************************************************/ -/************************************************************************* +/*********************************************************************//** * @brief * The testSetConductivityOverride function overrides the compensated * conductivity value of given sensor id. * @details * Inputs : compensatedConductivityValues[] * Outputs : compensatedConductivityValues[] - * @param sensorId : Id of conductivity sensor to get conductivity value - * @param value : override compensated conductivity value + * @param sensorId conductivity sensor id + * @param value override compensated conductivity value * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetConductivityOverride( U32 sensorId, F32 value ) @@ -293,14 +346,14 @@ return result; } -/************************************************************************* +/*********************************************************************//** * @brief * The testResetConductivityOverride function resets the override of the \n * conductivity sensor value. * @details * Inputs : compensatedConductivityValues[] * Outputs : compensatedConductivityValues[] - * @param sensorId : Id of the conductivity sensor to override. + * @param sensorId conductivity sensor id * @return TRUE if reset successful, FALSE if not *************************************************************************/ BOOL testResetConductivityOverride( U32 sensorId ) @@ -320,14 +373,14 @@ return result; } -/************************************************************************* +/*********************************************************************//** * @brief * The testSetConductivityDataPublishIntervalOverride function overrides * the conductivity data publish interval. * @details * Inputs : conductivityDataPublishInterval * Outputs : conductivityDataPublishInterval - * @param value : override conductivity data publish interval with (in ms) + * @param value override conductivity data publish interval with (in ms) * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetConductivityDataPublishIntervalOverride( U32 interval_ms ) @@ -344,7 +397,7 @@ return result; } -/************************************************************************* +/*********************************************************************//** * @brief * The testResetConductivityDataPublishIntervalOverride function resets * the override of the conductivity data publish interval.