Index: firmware/App/Controllers/ConductivitySensors.c =================================================================== diff -u -ra8eecf939bc9baff3d5ff5e87013297b8fe20d0e -rac029c36127b916d68c0039a470c3e4c68879adf --- firmware/App/Controllers/ConductivitySensors.c (.../ConductivitySensors.c) (revision a8eecf939bc9baff3d5ff5e87013297b8fe20d0e) +++ firmware/App/Controllers/ConductivitySensors.c (.../ConductivitySensors.c) (revision ac029c36127b916d68c0039a470c3e4c68879adf) @@ -1,31 +1,35 @@ /************************************************************************** * -* Copyright (c) 2020-2022 Diality Inc. - All Rights Reserved. +* Copyright (c) 2020-2024 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 ConductivitySensors.c * * @author (last) Dara Navaei -* @date (last) 23-May-2022 +* @date (last) 05-Mar-2024 * * @author (original) Quang Nguyen * @date (original) 13-Jul-2020 * ***************************************************************************/ -#include // Used for calculating the polynomial calibration equation. +#include // Used for calculating the polynomial calibration equation. +#include // For memcpy #include "ConductivitySensors.h" #include "FPGA.h" #include "NVDataMgmt.h" #include "MessageSupport.h" +#include "ModeFill.h" +#include "OperationModes.h" #include "PersistentAlarm.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "TaskPriority.h" #include "TemperatureSensors.h" #include "Utilities.h" +#include "Valves.h" /** * @addtogroup ConductivitySensors @@ -39,84 +43,120 @@ #define COND_CPI_SENSOR_PROBE_TYPE 100 ///< 1 K cell constant conductivity probe. #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.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_DECIMAL_CONVERSION 100.0F ///< Conductivity value from FPGA has two decimal place. +#define COND_SENSOR_REFERENCE_TEMPERATURE 25.0F ///< Reference temperature for conductivity sensor. #define COND_SENSOR_REPORT_PERIOD ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Broadcast conductivity values message every second. -#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_HIGH_US_PER_CM 2000.0F ///< Maximum allowed high conductivity value in uS/cm. +#define MIN_COND_SENSOR_CPI_WARNING_HIGH_US_PER_CM 1990.0F ///< Minimum allowed high conductivity value in uS/cm. -#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_COND_SENSOR_CPI_WARNING_LOW_US_PER_CM 200.0F ///< Maximum allowed low conductivity value in uS/cm. +#define MIN_COND_SENSOR_CPI_WARNING_LOW_US_PER_CM 220.0F ///< Minimum allowed low conductivity value in uS/cm. +#define MAX_RO_ONLY_COND_SENSOR_CPI_HIGH_US_PER_CM 100.0F ///< Maximum RO only mode high conductivity value in uS/cm. +#define MIN_RO_ONLY_COND_SENSOR_CPI_HIGH_US_PER_CM 90.0F ///< Minimum RO only mode high conductivity value in uS/cm. + #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_FAILURES 2 ///< 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.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 INLET_WATER_COND_SENSOR_OUT_OF_RANGE_TIMEOUT_MS ( 30 * MS_PER_SECOND ) ///< Inlet water conductivity sensor out of range timeout in milliseconds. +#define INLET_WATER_COND_SENSOR_OUT_OF_RANGE_CLEAR_MS ( 1 * MS_PER_SECOND ) ///< Inlet water conductivity sensor out of range clear in milliseconds. -#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. +#define EMSTAT_PICO_MEASUREMENT_OFFSET 0x8000000 ///< Emstat measurement offset. +// The below Emstat status values come from the MethodScript-v1_2-1.pdf. See page 10 table 4 for further information +// The first hex value is the status ID meaning that all of these are the status of the sensor. The second hex value is the content. +#define EMSTAT_PICO_STATUS_OK 0x10 ///< Emstat measurement good status. +#define EMSTAT_PICO_STATUS_TIMING_NOT_MET 0x11 ///< Emstat measurement takes too long status. +#define EMSTAT_PICO_STATUS_95_PCT_OF_MAX_ADC 0x12 ///< Emstat measurement overload, >95% of max ADC value status. +#define EMSTAT_PICO_STATUS_2_PCT_OF_MAX_ADC 0x14 ///< Emstat measurement underload, <2% of max ADC value status. +#define EMSTAT_PICO_STATUS_80_PCT_OF_MAX_ADC 0x18 ///< Emstat measurement overload warning, >80% of max ADC value status. -#define EMSTAT_PICO_MEASUREMENT_OFFSET 0x8000000 ///< Measurement offset for emstat pico measurement data. -#define EMSTAT_PICO_GOOD_STATUS 0x10 ///< Measurement good status. -#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 EMSTAT_PICO_FIFO_EMPTY_MASK 0x8000 ///< Emstat buffer empty indication bit. +#define EMSTAT_NUM_OF_SENSORS_PER_BOARD 2 ///< Emstat Pico number of sensors per board. +#define EMSTAT_CPI_OR_CD1_INDEX 0 ///< Emstat board CPi index number. +#define EMSTAT_CPO_OR_CD2_INDEX 1 ///< Emstat board CPo index number. + +#define EMSTAT_PACKAGE_BUFFER_SIZE 50 ///< EmStat package buffer size +#define EMSTAT_RX_FIFO_COUNT_MASK 0x7FFF ///< EmStat Rx fifo count mask + #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. +#define COND_SENSORS_FPGA_ERROR_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Conductivity sensors FPGA error timeout in milliseconds. +#define COND_SENSORS_BAD_CHAR_TIME_OUT_MS ( 2 * MS_PER_SECOND ) ///< Conductivity sensor bad received character timeout in milliseconds. #pragma pack(push,1) /// Emstat pico measurement data package structure typedef struct { - U16 type; ///< Measurement variable type - U08 value[7]; ///< Measurement value - U08 prefix; ///< Prefix character for SI prefixes - U08 reserved1; ///< Comma separator - U16 status; ///< Status for measurement data package - U08 reserved2[4]; ///< Comma separator and index of current range + U16 type; ///< Measurement variable type. + U08 value[7]; ///< Measurement value. + U08 prefix; ///< Prefix character for SI prefixes. + U08 reserved1; ///< Comma separator. + U16 status; ///< Status for measurement data package. + U08 reserved2[4]; ///< Comma separator and index of current range. } EMSTAT_VARIABLE_T; + +/// Emstat conductivity sensor and its corresponding temperature sensor +typedef struct +{ + CONDUCTIVITY_SENSORS_T condSnsr; ///< Emstat conductivity sensor on the board. + TEMPERATURE_SENSORS_T condSnsrTempSnsr; ///< Emstat conductivity sensor temperature sensor. + ALARM_ID_T condSnsrHex2StrAlarm; ///< Emstat conductivity sensor hex to string alarm. +} EMSTAT_COND_SENSORS_T; + +/// Emstat board structure +typedef struct +{ + BOOL packageStarted; ///< Emstat package started flag. + U08 packageIndex; ///< Emstat package index number. + U08 package[ EMSTAT_PACKAGE_BUFFER_SIZE ]; ///< Emstat read buffer package. + EMSTAT_COND_SENSORS_T sensors[ EMSTAT_NUM_OF_SENSORS_PER_BOARD ]; ///< Emstat conductivity and corresponding temperature sensors. +} EMSTAT_READ_T; + +/// Conductivity sensors structure +typedef struct +{ + U08 readCount; ///< Conductivity sensor FPGA read count (For V3). + U32 internalErrorCount; ///< Conductivity sensor internal error count. + U32 badCharErrorCount; ///< Conductivity sensor bad char error count + OVERRIDE_F32_T compensatedCondValue; ///< Conductivity sensor compensated value + F32 rawCondValue; ///< Conductivity sensor raw value. + U32 sensorStatus; ///< Conductivity sensor status. + U32 rawEmstatCondValue; ///< Conductivity sensor from Emstat. +} COND_SENSOR_STATUS_T; #pragma pack(pop) // ********** private data ********** -/// Conductivity sensors' associated temperature sensors -static U32 associateTempSensor[ NUM_OF_CONDUCTIVITY_SENSORS ] = +/// Emstat boards for CPi/CPo and CD1/CD2 +typedef enum EmstatBoards { - TEMPSENSORS_INLET_PRIMARY_HEATER, ///< Inlet temperature sensor - TEMPSENSORS_OUTLET_PRIMARY_HEATER, ///< Outlet temperature sensor - TEMPSENSORS_CONDUCTIVITY_SENSOR_1, ///< Post-acid temperature sensor - TEMPSENSORS_CONDUCTIVITY_SENSOR_2, ///< Post-bicarbonate temperature sensor -}; + EMSTAT_CPI_CPO_BOARD = 0, ///< Emstat CPi/CPo board. + EMSTAT_CD1_CD2_BOARD, ///< Emstat CD1/CD2 board. + NUM_OF_EMSTAT_BOARDS ///< Number of Emstat boards. +} EMSTAT_BOARD_T; -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 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; ///< 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 F32 roRejectionRatio; ///< Latest RO rejection ratio. +static U32 condDataPublishCounter; ///< Conductivity sensors data publish timer counter. +static EMSTAT_READ_T emstatBoardRead[ NUM_OF_EMSTAT_BOARDS ]; ///< EMSTAT board read. +static COND_SENSOR_STATUS_T condSensorStatus[ NUM_OF_CONDUCTIVITY_SENSORS ]; ///< Conductivity sensors status. static DG_COND_SENSORS_CAL_RECORD_T condSensorsCalRecord; ///< Conductivity sensors' calibration record. +static DG_COND_SENSORS_TEMP_COMP_CAL_RECORD_T condSensorsTempCompCalRecord; ///< Conductivity sensors' temperature compensation calibration record. +static CAL_DATA_DG_COND_SENSORS_T condSensorCalTable[ NUM_OF_CONDUCTIVITY_SENSORS ]; ///< Conductivity sensors calibration table. // ********** private function prototypes ********** -static F32 calcCompensatedConductivity( F32 conductivity, F32 temperature ); +static F32 calcCompensatedConductivity( U32 sensorID, F32 conductivity, F32 temperature ); static void calcRORejectionRatio( void ); -static void processCPiCPoSensorRead( U32 sensorId, U32 fgpaRead, U08 fpgaReadCount, U08 fpgaErrorCount, U08 fpgaSensorFault ); +static void processCPiCPoSensorRead( U32 sensorId, U08 emstatBoardSensorIndex, U32 fgpaRead, U08 fpgaReadCount, U08 fpgaErrorCount, U08 fpgaSensorFault ); static U32 prefixStrToSIFactor( U08 prefix ); -static void processMeasurementDataPackage( U32 sensorId ); -static void processCD1CD2SensorRead( U16 fpgaReadCount, U08 fpgaErrorCount ); +static void processEmstatBoard( EMSTAT_BOARD_T board ); +static void processEmstatSensorRead( EMSTAT_READ_T* readPackage, U08 emstatByte ); +static void processEmstatMeasurementDataPackets( U08 boardSensorIndex, EMSTAT_READ_T* readPackage, EMSTAT_VARIABLE_T* receivedPackets ); static F32 getCalibrationAppliedConductivityValue( U32 sensorId, F32 compensatedValue ); /*********************************************************************//** @@ -128,36 +168,79 @@ *************************************************************************/ void initConductivitySensors( void ) { - U32 i; + U08 i; + roRejectionRatio = 0.0F; + condDataPublishCounter = DATA_PUBLISH_COUNTER_START_COUNT; - 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; - rawConductivityValues[ i ] = 0.0; + memset( &condSensorStatus[ i ], 0x0, sizeof( COND_SENSOR_STATUS_T ) ); + benignPolynomialCalRecord( &condSensorsCalRecord.condSensors[ i ] ); - compensatedConductivityValues[ i ].data = 0.0; - compensatedConductivityValues[ i ].ovData = 0.0; - compensatedConductivityValues[ i ].ovInitData = 0.0; - compensatedConductivityValues[ i ].override = OVERRIDE_RESET; + switch( i ) + { + case CONDUCTIVITYSENSORS_CPI_SENSOR: + condSensorCalTable[ i ] = CAL_DATA_CPI_COND_SENSOR; + break; - benignPolynomialCalRecord( &condSensorsCalRecord.condSensors[ i ] ); + case CONDUCTIVITYSENSORS_CPO_SENSOR: + condSensorCalTable[ i ] = CAL_DATA_CPO_COND_SENSOR; + break; + + case CONDUCTIVITYSENSORS_CD1_SENSOR: + condSensorCalTable[ i ] = CAL_DATA_CD1_COND_SENSOR; + break; + + case CONDUCTIVITYSENSORS_CD2_SENSOR: + condSensorCalTable[ i ] = CAL_DATA_CD2_COND_SENSOR; + break; + +#ifndef _VECTORCAST_ + default: + // This switch is in a for loop so VectorCAST cannot reach to default. + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_CONDUCTIVITY_SENSOR_ID, i ) + break; +#endif + } } + // Reset all the read packages of the Emstat boards + for ( i = 0; i < NUM_OF_EMSTAT_BOARDS; i++ ) + { + memset( &emstatBoardRead[ i ], 0x0, sizeof( EMSTAT_BOARD_T ) ); + } + + // Each Emstat board covers two conductivity sensors + // CPi/CPo Emstat board conductivity sensors and their corresponding temperature sensors + emstatBoardRead[ EMSTAT_CPI_CPO_BOARD ].sensors[ EMSTAT_CPI_OR_CD1_INDEX ].condSnsr = CONDUCTIVITYSENSORS_CPI_SENSOR; + emstatBoardRead[ EMSTAT_CPI_CPO_BOARD ].sensors[ EMSTAT_CPI_OR_CD1_INDEX ].condSnsrTempSnsr = TEMPSENSORS_INLET_PRIMARY_HEATER; + emstatBoardRead[ EMSTAT_CPI_CPO_BOARD ].sensors[ EMSTAT_CPI_OR_CD1_INDEX ].condSnsrHex2StrAlarm = ALARM_ID_DG_CPI_COND_SENSOR_INVALID_CHAR; + emstatBoardRead[ EMSTAT_CPI_CPO_BOARD ].sensors[ EMSTAT_CPO_OR_CD2_INDEX ].condSnsr = CONDUCTIVITYSENSORS_CPO_SENSOR; + emstatBoardRead[ EMSTAT_CPI_CPO_BOARD ].sensors[ EMSTAT_CPO_OR_CD2_INDEX ].condSnsrTempSnsr = TEMPSENSORS_OUTLET_PRIMARY_HEATER; + emstatBoardRead[ EMSTAT_CPI_CPO_BOARD ].sensors[ EMSTAT_CPO_OR_CD2_INDEX ].condSnsrHex2StrAlarm = ALARM_ID_DG_CPO_COND_SENSOR_INVALID_CHAR; + + // CD1/CD2 Emstat board conductivity sensors and their corresponding temperature sensors + // NOTE: For CD1, use TD2 temperature sensor for compensation since it is a more accurate temperature sensor + emstatBoardRead[ EMSTAT_CD1_CD2_BOARD ].sensors[ EMSTAT_CPI_OR_CD1_INDEX ].condSnsr = CONDUCTIVITYSENSORS_CD1_SENSOR; + emstatBoardRead[ EMSTAT_CD1_CD2_BOARD ].sensors[ EMSTAT_CPI_OR_CD1_INDEX ].condSnsrTempSnsr = TEMPSENSORS_CONDUCTIVITY_SENSOR_2; + emstatBoardRead[ EMSTAT_CD1_CD2_BOARD ].sensors[ EMSTAT_CPI_OR_CD1_INDEX ].condSnsrHex2StrAlarm = ALARM_ID_DG_CD1_COND_SENSOR_INVALID_CHAR; + emstatBoardRead[ EMSTAT_CD1_CD2_BOARD ].sensors[ EMSTAT_CPO_OR_CD2_INDEX ].condSnsr = CONDUCTIVITYSENSORS_CD2_SENSOR; + emstatBoardRead[ EMSTAT_CD1_CD2_BOARD ].sensors[ EMSTAT_CPO_OR_CD2_INDEX ].condSnsrTempSnsr = TEMPSENSORS_CONDUCTIVITY_SENSOR_2; + emstatBoardRead[ EMSTAT_CD1_CD2_BOARD ].sensors[ EMSTAT_CPO_OR_CD2_INDEX ].condSnsrHex2StrAlarm = ALARM_ID_DG_CD2_COND_SENSOR_INVALID_CHAR; + + // For V3 conductivity sensors 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_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 ); + initPersistentAlarm( ALARM_ID_DG_INLET_WATER_CONDUCTIVITY_IN_HIGH_RANGE, INLET_WATER_COND_SENSOR_OUT_OF_RANGE_CLEAR_MS, INLET_WATER_COND_SENSOR_OUT_OF_RANGE_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DG_INLET_WATER_CONDUCTIVITY_IN_LOW_RANGE, INLET_WATER_COND_SENSOR_OUT_OF_RANGE_CLEAR_MS, INLET_WATER_COND_SENSOR_OUT_OF_RANGE_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_COND_TOO_HIGH, 0, INLET_WATER_COND_SENSOR_OUT_OF_RANGE_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_COND_TOO_LOW, 0, INLET_WATER_COND_SENSOR_OUT_OF_RANGE_TIMEOUT_MS ); + + // Initialize the conductivity sensors' FPGA alarms + initFPGAPersistentAlarm( FPGA_PERS_ERROR_CPI_CPO_COND_SENSORS, ALARM_ID_DG_CPI_CPO_SENSORS_FPGA_FAULT, COND_SENSORS_FPGA_ERROR_TIMEOUT_MS, COND_SENSORS_FPGA_ERROR_TIMEOUT_MS ); + initFPGAPersistentAlarm( FPGA_PERS_ERROR_CD1_CD2_COND_SENSORS, ALARM_ID_DG_CD1_CD2_SENSORS_FPGA_FAULT, COND_SENSORS_FPGA_ERROR_TIMEOUT_MS, COND_SENSORS_FPGA_ERROR_TIMEOUT_MS ); } /*********************************************************************//** @@ -176,36 +259,43 @@ { getNVRecord2Driver( GET_CAL_CONDUCTIVITY_SENSORS, (U08*)&condSensorsCalRecord, sizeof( condSensorsCalRecord ), NUM_OF_CAL_DATA_COND_SENSORS, ALARM_ID_DG_COND_SENSORS_INVALID_CAL_RECORD ); + + getNVRecord2Driver( GET_CAL_CONDUCTIVITY_SENSORS_TEMP_COMP, (U08*)&condSensorsTempCompCalRecord, sizeof( DG_COND_SENSORS_TEMP_COMP_CAL_RECORD_T ), + NUM_OF_CAL_DATA_COND_SENSORS_TEMP_COMP, ALARM_ID_DG_COND_SENSORS_INVALID_TEMP_COMP_CAL_RECORD ); } - processCPiCPoSensorRead( CONDUCTIVITYSENSORS_CPI_SENSOR, getFPGACPi(), getFPGACPiReadCount(), getFPGACPiErrorCount(), getFPGACPiFault() ); - processCPiCPoSensorRead( CONDUCTIVITYSENSORS_CPO_SENSOR, getFPGACPo(), getFPGACPoReadCount(), getFPGACPoErrorCount(), getFPGACPoFault() ); - processCD1CD2SensorRead( getFPGAEmstatRxFifoCount(), getFPGAEmstatRxErrCount() ); +#ifndef _RELEASE_ + if ( HW_CONFIG_BETA == getHardwareConfigStatus() ) + { + processCPiCPoSensorRead( CONDUCTIVITYSENSORS_CPI_SENSOR, EMSTAT_CPI_OR_CD1_INDEX, getFPGACPi(), getFPGACPiReadCount(), getFPGACPiErrorCount(), getFPGACPiFault() ); + processCPiCPoSensorRead( CONDUCTIVITYSENSORS_CPO_SENSOR, EMSTAT_CPO_OR_CD2_INDEX, getFPGACPo(), getFPGACPoReadCount(), getFPGACPoErrorCount(), getFPGACPoFault() ); + } + else +#endif + { + processEmstatBoard( EMSTAT_CPI_CPO_BOARD ); + } + processEmstatBoard( EMSTAT_CD1_CD2_BOARD ); - if ( ++conductivityDataPublicationTimerCounter >= getU32OverrideValue( &conductivityDataPublishInterval ) ) + if ( ++condDataPublishCounter >= getU32OverrideValue( &conductivityDataPublishInterval ) ) { CONDUCTIVITY_DATA_T data; calcRORejectionRatio(); - - conductivityDataPublicationTimerCounter = 0; - data.roRejectionRatio = roRejectionRatio; - - data.cpi = getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ); - data.cpo = getConductivityValue( CONDUCTIVITYSENSORS_CPO_SENSOR ); - data.cd1 = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); - data.cd2 = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); - - data.cpiRaw = rawConductivityValues[ CONDUCTIVITYSENSORS_CPI_SENSOR ]; - data.cpoRaw = rawConductivityValues[ CONDUCTIVITYSENSORS_CPO_SENSOR ]; - 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 ]; - + data.roRejectionRatio = roRejectionRatio; + data.cpi = getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ); + data.cpo = getConductivityValue( CONDUCTIVITYSENSORS_CPO_SENSOR ); + data.cd1 = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); + data.cd2 = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); + data.cpiRaw = condSensorStatus[ CONDUCTIVITYSENSORS_CPI_SENSOR ].rawCondValue; + data.cpoRaw = condSensorStatus[ CONDUCTIVITYSENSORS_CPO_SENSOR ].rawCondValue; + data.cd1Raw = condSensorStatus[ CONDUCTIVITYSENSORS_CD1_SENSOR ].rawCondValue; + data.cd2Raw = condSensorStatus[ CONDUCTIVITYSENSORS_CD2_SENSOR ].rawCondValue; + data.cpiSensorStatus = condSensorStatus[ CONDUCTIVITYSENSORS_CPI_SENSOR ].sensorStatus; + data.cpoSensorStatus = condSensorStatus[ CONDUCTIVITYSENSORS_CPO_SENSOR ].sensorStatus; + data.cd1SensorStatus = condSensorStatus[ CONDUCTIVITYSENSORS_CD1_SENSOR ].sensorStatus; + data.cd2SensorStatus = condSensorStatus[ CONDUCTIVITYSENSORS_CD2_SENSOR ].sensorStatus; + condDataPublishCounter = 0; broadcastData( MSG_ID_DG_CONDUCTIVITY_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( CONDUCTIVITY_DATA_T ) ); } } @@ -221,18 +311,14 @@ SELF_TEST_STATUS_T execConductivitySensorsSelfTest( void ) { SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; + BOOL calStatus = FALSE; - BOOL calStatus = getNVRecord2Driver( GET_CAL_CONDUCTIVITY_SENSORS, (U08*)&condSensorsCalRecord, sizeof( condSensorsCalRecord ), - NUM_OF_CAL_DATA_COND_SENSORS, ALARM_ID_DG_COND_SENSORS_INVALID_CAL_RECORD ); + calStatus |= getNVRecord2Driver( GET_CAL_CONDUCTIVITY_SENSORS, (U08*)&condSensorsCalRecord, sizeof( DG_COND_SENSORS_CAL_RECORD_T ), + NUM_OF_CAL_DATA_COND_SENSORS, ALARM_ID_DG_COND_SENSORS_INVALID_CAL_RECORD ); + calStatus |= getNVRecord2Driver( GET_CAL_CONDUCTIVITY_SENSORS_TEMP_COMP, (U08*)&condSensorsTempCompCalRecord, sizeof( DG_COND_SENSORS_TEMP_COMP_CAL_RECORD_T ), + NUM_OF_CAL_DATA_COND_SENSORS_TEMP_COMP, ALARM_ID_DG_COND_SENSORS_INVALID_TEMP_COMP_CAL_RECORD ); - if ( TRUE == calStatus ) - { - result = SELF_TEST_STATUS_PASSED; - } - else - { - result = SELF_TEST_STATUS_FAILED; - } + result = ( TRUE == calStatus ? SELF_TEST_STATUS_PASSED : SELF_TEST_STATUS_FAILED ); return result; } @@ -249,61 +335,115 @@ *************************************************************************/ void checkInletWaterConductivity( void ) { + F32 conductivity = getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ); + + if ( VALVE_STATE_OPEN == getValveStateName( VPI ) ) + { #ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_WATER_QUALITY_CHECK ) != SW_CONFIG_ENABLE_VALUE ) + 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 ); - } + DG_OP_MODE_T opMode = getCurrentOperationMode(); + BOOL isConductTooLow = FALSE; + BOOL isConductTooHigh = FALSE; - // Warning per PRS 404 - if ( TRUE == isConductInWarningRange ) - { - checkPersistentAlarm( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_HIGH_RANGE, isConductInWarningRange, conductivity, MAX_COND_SENSOR_CPI_WARNING_HIGH ); + if ( FALSE == isROOnlyModeEnabled() ) + { + isConductTooLow = ( conductivity < MAX_COND_SENSOR_CPI_WARNING_LOW_US_PER_CM ? TRUE : FALSE ); + isConductTooHigh = ( conductivity > MAX_COND_SENSOR_CPI_WARNING_HIGH_US_PER_CM ? TRUE : FALSE ); + } + else + { + isConductTooLow = FALSE; + isConductTooHigh = ( conductivity > MAX_RO_ONLY_COND_SENSOR_CPI_HIGH_US_PER_CM ? 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_CONDUCTIVITY_IN_LOW_RANGE ) ) + { + isConductTooLow = ( conductivity >= MIN_COND_SENSOR_CPI_WARNING_LOW_US_PER_CM ? FALSE : TRUE ); + } + + // Per PRS 403 + checkPersistentAlarm( ALARM_ID_DG_INLET_WATER_CONDUCTIVITY_IN_LOW_RANGE, isConductTooLow, conductivity, MAX_COND_SENSOR_CPI_WARNING_LOW_US_PER_CM ); + + if ( TRUE == isAlarmActive( ALARM_ID_DG_INLET_WATER_CONDUCTIVITY_IN_HIGH_RANGE ) ) + { + if ( FALSE == isROOnlyModeEnabled() ) + { + isConductTooHigh = ( conductivity <= MIN_COND_SENSOR_CPI_WARNING_HIGH_US_PER_CM ? FALSE : TRUE ); + } + else + { + isConductTooHigh = ( conductivity <= MIN_RO_ONLY_COND_SENSOR_CPI_HIGH_US_PER_CM ? FALSE : TRUE ); + } + } + + // Per PRS 404 + checkPersistentAlarm( ALARM_ID_DG_INLET_WATER_CONDUCTIVITY_IN_HIGH_RANGE, isConductTooHigh, conductivity, MAX_COND_SENSOR_CPI_WARNING_HIGH_US_PER_CM ); + 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: + // Per PRS 403 + checkPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_COND_TOO_HIGH, isConductTooHigh, conductivity, MAX_COND_SENSOR_CPI_WARNING_HIGH_US_PER_CM ); + // Per PRS 404 + checkPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_COND_TOO_LOW, isConductTooLow, conductivity, MAX_COND_SENSOR_CPI_WARNING_LOW_US_PER_CM ); + break; + + default: + // NOTE: Do nothing for the rest of the modes + break; + } } - 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 ); - } } + else + { + // VPI is closed - clear all alarms + checkPersistentAlarm( ALARM_ID_DG_INLET_WATER_CONDUCTIVITY_IN_LOW_RANGE, FALSE, conductivity, MAX_COND_SENSOR_CPI_WARNING_LOW_US_PER_CM ); + checkPersistentAlarm( ALARM_ID_DG_INLET_WATER_CONDUCTIVITY_IN_HIGH_RANGE, FALSE, conductivity, MAX_COND_SENSOR_CPI_WARNING_HIGH_US_PER_CM ); + checkPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_COND_TOO_HIGH, FALSE, conductivity, MAX_COND_SENSOR_CPI_WARNING_HIGH_US_PER_CM ); + checkPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_COND_TOO_LOW, FALSE, conductivity, MAX_COND_SENSOR_CPI_WARNING_LOW_US_PER_CM ); + } } /*********************************************************************//** * @brief - * The checkRORejectionRatio function 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 - * @details Outputs: Triggered alarm + * The setCondcutivitySensorCalTable function sets the calibration table to + * be use of the corresponding conductivity sensor. + * @details Inputs: none + * @details Outputs: condSensorCalTable + * @param sensor the conductivity sensor ID to use the calibration table for + * @param calTable the calibration table to be used for the selected conductivity + * sensor * @return none *************************************************************************/ -void checkRORejectionRatio( void ) +void setCondcutivitySensorCalTable( CONDUCTIVITY_SENSORS_T sensor, CAL_DATA_DG_COND_SENSORS_T calTable ) { -#ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_RO_RATIO_CHECK ) != SW_CONFIG_ENABLE_VALUE ) -#endif + if ( sensor < NUM_OF_CONDUCTIVITY_SENSORS ) { - 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 ); + if ( calTable < NUM_OF_CAL_DATA_COND_SENSORS ) + { + condSensorCalTable[ sensor ] = calTable; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_DG_INVALID_COND_SNSNR_CAL_TABLE_SELECTED, calTable ) + } } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_CONDUCTIVITY_SENSOR_ID, sensor ) + } } /*********************************************************************//** @@ -317,11 +457,14 @@ *************************************************************************/ F32 getConductivityValue( U32 sensorId ) { - F32 result = 0.0; + F32 result = 0.0F; if ( sensorId < NUM_OF_CONDUCTIVITY_SENSORS ) { - result = getF32OverrideValue( &compensatedConductivityValues[ sensorId ] ); + // NOTE: the compensated value is set into a local variable and then passed to the override function + // to prevent memory failure + OVERRIDE_F32_T value = condSensorStatus[ sensorId ].compensatedCondValue; + result = getF32OverrideValue( &value ); } else { @@ -338,14 +481,19 @@ * reference temperature of 25 degree Celsius. * @details Inputs: conductivity, temperature * @details Outputs: none + * @param sensorID the ID of the conductivity sensor * @param conductivity conductivity value * @param temperature temperature to compensate conductivity with * @return compensated conductivity based on temperature *************************************************************************/ -static F32 calcCompensatedConductivity( F32 conductivity, F32 temperature ) +static F32 calcCompensatedConductivity( U32 sensorID, F32 conductivity, F32 temperature ) { - // EC = EC_25 * (1 + temp_coef * ( temperature - 25 )) - F32 const compensatedCoef = ( 1.0 + ( COND_SENSOR_TEMPERATURE_COEF * ( temperature - COND_SENSOR_REFERENCE_TEMPERATURE ) ) ); + F32 gain = condSensorsTempCompCalRecord.condSensorsTempComp[ (CAL_DATA_DG_COND_SENSORS_TEMP_COMP_T)sensorID ].gain; + F32 coeff = condSensorsTempCompCalRecord.condSensorsTempComp[ (CAL_DATA_DG_COND_SENSORS_TEMP_COMP_T)sensorID ].coefficient; + F32 offset = condSensorsTempCompCalRecord.condSensorsTempComp[ (CAL_DATA_DG_COND_SENSORS_TEMP_COMP_T)sensorID ].offset; + F32 compensation = ( gain * coeff ) + offset; + // EC = EC_25 * (1 + compensation * ( temperature - 25 )) + F32 compensatedCoef = ( 1.0F + ( compensation * ( temperature - COND_SENSOR_REFERENCE_TEMPERATURE ) ) ); return conductivity / compensatedCoef; } @@ -360,8 +508,8 @@ *************************************************************************/ static void calcRORejectionRatio( void ) { - F32 const cpi = getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ); - F32 const cpo = getConductivityValue( CONDUCTIVITYSENSORS_CPO_SENSOR ); + F32 cpi = getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ); + F32 cpo = getConductivityValue( CONDUCTIVITYSENSORS_CPO_SENSOR ); roRejectionRatio = RO_REJECTION_RATIO_OUT_OF_RANGE_VALUE; @@ -379,37 +527,39 @@ * @details Inputs: none * @details Outputs: none * @param sensorId Conductivity sensor id to process + * @param emstatBoardSensorIndex the sensor index number on an EMSTAT board * @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, U08 fpgaSensorFault ) +static void processCPiCPoSensorRead( U32 sensorId, U08 emstatBoardSensorIndex, U32 fgpaRead, U08 fpgaReadCount, U08 fpgaErrorCount, U08 fpgaSensorFault ) { if ( ( 0 == fpgaErrorCount ) && ( 0 == fpgaSensorFault ) ) { - if ( ( readCount[ sensorId ] != fpgaReadCount ) ) + if ( ( condSensorStatus[ sensorId ].readCount != fpgaReadCount ) ) { - F32 temperature = getTemperatureValue( associateTempSensor[ sensorId ] ); - F32 conductivity = ( (F32)( fgpaRead ) / COND_SENSOR_DECIMAL_CONVERSION ); - F32 compensatedCond = calcCompensatedConductivity( conductivity, temperature ); + // The corresponding temperature sensor of a conductivity sensor is maintained in the EMSTAT boards' structure since the + // EMSTAT sensors will be the permanent sensors from DVT onward. + F32 temperature = getTemperatureValue( emstatBoardRead[ EMSTAT_CPI_CPO_BOARD ].sensors[ emstatBoardSensorIndex ].condSnsrTempSnsr ); + F32 conductivity = ( (F32)( fgpaRead ) / COND_SENSOR_DECIMAL_CONVERSION ); + F32 compensatedCond = calcCompensatedConductivity( sensorId, conductivity, temperature ); - readCount[ sensorId ] = fpgaReadCount; - internalErrorCount[ sensorId ] = 0; - compensatedConductivityValues[ sensorId ].data = getCalibrationAppliedConductivityValue( sensorId, compensatedCond ); - rawConductivityValues[ sensorId ] = conductivity; // store raw conductivity data from CPi and CPo + condSensorStatus[ sensorId ].readCount = fpgaReadCount; + condSensorStatus[ sensorId ].internalErrorCount = 0; + condSensorStatus[ sensorId ].compensatedCondValue.data = getCalibrationAppliedConductivityValue( sensorId, compensatedCond ); + condSensorStatus[ sensorId ].rawCondValue = conductivity; // store raw conductivity data from CPi and CPo } else { - ++internalErrorCount[ sensorId ]; - if ( internalErrorCount[ sensorId ] > MAX_ALLOWED_UNCHANGED_CONDUCTIVITY_READS ) + if ( ++condSensorStatus[ sensorId ].internalErrorCount > MAX_ALLOWED_UNCHANGED_CONDUCTIVITY_READS ) { #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 ); + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DG_CONDUCTIVITY_SENSOR_FAULT, sensorId ); } } } @@ -422,7 +572,7 @@ 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 ); + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DG_CONDUCTIVITY_SENSOR_FAULT, sensorId ); } } } @@ -460,118 +610,157 @@ /*********************************************************************//** * @brief - * The processMeasurementDataPackage function processes incoming measurement data - * package variables from Emstat Pico and convert it to conductivity. The conductivity - * value is then compensated based on associating temperature sensor's value. - * @details Inputs: none - * @details Outputs: none - * @param sensorId Conductivity sensor id to process + * The processEmstatBoard function processes the Emsat boards + * @details Inputs: emstatBoardRead + * @details Outputs: emstatBoardRead + * @param board the enum of the Emstat board * @return none *************************************************************************/ -static void processMeasurementDataPackage( U32 sensorId ) +static void processEmstatBoard( EMSTAT_BOARD_T board ) { - EMSTAT_VARIABLE_T const * const measurementPtr = (EMSTAT_VARIABLE_T *)&package; - U32 status = hexStrToDec( (U08 *)&measurementPtr->status, sizeof( measurementPtr->status ) ); - sensorStatus[ sensorId ] = status; + U08 emstatByte = 0; + U16 rxFifoCount = 0; - if ( EMSTAT_PICO_GOOD_STATUS == status ) + switch ( board ) { - 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 ); + case EMSTAT_CPI_CPO_BOARD: + // Check for continuous incoming bytes + rxFifoCount = getFPGAEmstatCPiCPoRxFifoCount() & EMSTAT_RX_FIFO_COUNT_MASK; + checkFPGAPersistentAlarms( FPGA_PERS_ERROR_CPI_CPO_COND_SENSORS, rxFifoCount ); - internalErrorCount[ sensorId ] = 0; - compensatedConductivityValues[ sensorId ].data = getCalibrationAppliedConductivityValue( sensorId, compensatedCond ); - rawConductivityValues[ sensorId ] = conductivity; // store raw conductivity data from CD1 and CD2 + // Only process the sensor read if there is a new byte + if ( 0 != rxFifoCount ) + { + emstatByte = getFPGAEmstatCPiCPoByteOut(); + processEmstatSensorRead( &emstatBoardRead[ EMSTAT_CPI_CPO_BOARD ], emstatByte ); + } + break; - // Clear the alarm - checkPersistentAlarm( ALARM_ID_DG_CONDUCTIVITY_SENSOR_BAD_STATUS, FALSE, status, EMSTAT_PICO_GOOD_STATUS ); - } - else - { -#ifndef DISABLE_COND_STATUS_CHECK - checkPersistentAlarm( ALARM_ID_DG_CONDUCTIVITY_SENSOR_BAD_STATUS, TRUE, status, EMSTAT_PICO_GOOD_STATUS ); -#endif - } + case EMSTAT_CD1_CD2_BOARD: + // Check for continuous incoming bytes + rxFifoCount = getFPGAEmstatCD1CD2RxFifoCount() & EMSTAT_RX_FIFO_COUNT_MASK; + checkFPGAPersistentAlarms( FPGA_PERS_ERROR_CD1_CD2_COND_SENSORS, rxFifoCount ); - if ( EMSTAT_PICO_TIMING_NOT_MET_STATUS == status ) - { - if ( ++internalErrorCount[ sensorId ] > MAX_CONDUCTIVITY_SENSOR_FAILURES ) - { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_CONDUCTIVITY_SENSOR_FAULT, sensorId ); - } + // Only process the sensor read if there is a new byte + if ( 0 != rxFifoCount) + { + emstatByte = getFPGAEmstatCD1CD2OutByte(); + processEmstatSensorRead( &emstatBoardRead[ EMSTAT_CD1_CD2_BOARD ], emstatByte ); + } + break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_EMSTAT_CONDUCTIVITY_BOARD_SELECTED, board ); + break; } - else - { - internalErrorCount[ sensorId ] = 0; - } } /*********************************************************************//** * @brief - * The processCD1CD2SensorRead function checks if there is an error with Emstat - * conductivity sensors. If there is any error with the Emstat conductivity sensors, - * it raises an alarm. If the read count has changed, the new reading will be processed. + * The processEmstatSensorRead function processes the Emsat boards' data + * that is received from the boards * @details Inputs: none * @details Outputs: none - * @param fpgaReadCount FPGA read count for rx fifo - * @param fpgaErrorCount FPGA error count + * @param read package the structure of each Emstat board + * @param emstatByte the received byte from the sensor * @return none *************************************************************************/ -static void processCD1CD2SensorRead( U16 fpgaReadCount, U08 fpgaErrorCount ) +static void processEmstatSensorRead( EMSTAT_READ_T* readPackage, U08 emstatByte ) { - if ( fpgaErrorCount == 0 ) + switch ( emstatByte ) { - if ( ( fpgaReadCount > 0 ) && ( ( fpgaReadCount & EMSTAT_PICO_FIFO_EMPTY_MASK ) == 0 ) ) - { - U08 const emstatByte = getFPGAEmstatOutByte(); + case 'P': + readPackage->packageStarted = TRUE; + readPackage->packageIndex = 0; + break; - switch ( emstatByte ) + case ';': + if ( TRUE == readPackage->packageStarted ) { - case 'P': - packageStarted = TRUE; - packageIndex = 0; - break; + processEmstatMeasurementDataPackets( EMSTAT_CPI_OR_CD1_INDEX, readPackage, (EMSTAT_VARIABLE_T*)readPackage->package ); + readPackage->packageIndex = 0; + } + break; - case ';': - if ( packageStarted ) - { - processMeasurementDataPackage( CONDUCTIVITYSENSORS_CD1_SENSOR ); - packageIndex = 0; - } - break; + case '\n': + if ( TRUE == readPackage->packageStarted ) + { + processEmstatMeasurementDataPackets( EMSTAT_CPO_OR_CD2_INDEX, readPackage, (EMSTAT_VARIABLE_T*)readPackage->package ); + readPackage->packageStarted = FALSE; + } + break; - case '\n': - if ( packageStarted ) - { - processMeasurementDataPackage( CONDUCTIVITYSENSORS_CD2_SENSOR ); - packageStarted = FALSE; - } - break; - - default: - if ( packageStarted ) - { - package[ packageIndex++ ] = emstatByte; - } - break; + default: + if ( TRUE == readPackage->packageStarted ) + { + if ( readPackage->packageIndex < EMSTAT_PACKAGE_BUFFER_SIZE ) + { + readPackage->package[ readPackage->packageIndex++ ] = emstatByte; + } } + break; + } +} + +/*********************************************************************//** + * @brief + * The processEmstatMeasurementDataPackets function processes the Emsat boards' + * received data packets. + * @details Inputs: condSensorStatus, + * @details Outputs: condSensorStatus + * @param boardSenosrIndex the sensor index on each board (i.e CPi = 0 & CPo = 1 + * in EMSTAT_CPI_CPO_BOARD) + * @param read package the structure of each Emstat board + * @return none + *************************************************************************/ +static void processEmstatMeasurementDataPackets( U08 boardSensorIndex, EMSTAT_READ_T* readPackage, EMSTAT_VARIABLE_T* receivedPackets ) +{ + CONDUCTIVITY_SENSORS_T sensorId = readPackage->sensors[ boardSensorIndex ].condSnsr; + BOOL convStatus = hexStrToDec( (U08*)&receivedPackets->status, &condSensorStatus[ sensorId ].sensorStatus, sizeof( receivedPackets->status ) ); + BOOL isSensorStatusBad = ( EMSTAT_PICO_STATUS_TIMING_NOT_MET == condSensorStatus[ sensorId ].sensorStatus ? TRUE : FALSE ); + ALARM_ID_T badHexAlarm = readPackage->sensors[ boardSensorIndex ].condSnsrHex2StrAlarm; + BOOL isConvNotValid = FALSE; + + if ( FALSE == isSensorStatusBad ) + { + U32 prefix = prefixStrToSIFactor( receivedPackets->prefix ); + convStatus = hexStrToDec( receivedPackets->value, &condSensorStatus[ sensorId ].rawEmstatCondValue, sizeof( receivedPackets->value ) ); + + F32 resistance = ( ( F32 )( condSensorStatus[ sensorId ].rawEmstatCondValue - EMSTAT_PICO_MEASUREMENT_OFFSET ) / prefix ); + F32 temperature = getTemperatureValue( readPackage->sensors[ boardSensorIndex ].condSnsrTempSnsr ); + F32 conductivity = ( 1.0F / resistance ) * SIEMENS_TO_MICROSIEMENS_CONVERSION; + F32 compensatedCond = calcCompensatedConductivity( sensorId, conductivity, temperature ); + + condSensorStatus[ sensorId ].internalErrorCount = 0; + condSensorStatus[ sensorId ].compensatedCondValue.data = getCalibrationAppliedConductivityValue( sensorId, compensatedCond ); + condSensorStatus[ sensorId ].rawCondValue = conductivity; + } + + isConvNotValid = ( TRUE == convStatus ? FALSE : TRUE ); + // Check the conductivity sensors bad status alarm + if ( TRUE == isConvNotValid ) + { + if ( ++condSensorStatus[ sensorId ].badCharErrorCount > MAX_CONDUCTIVITY_SENSOR_FAILURES ) + { + SET_ALARM_WITH_1_U32_DATA( badHexAlarm, sensorId ); } } else { - if ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_FPGA_CONDUCTIVITY_SENSOR_ERROR ) ) + condSensorStatus[ sensorId ].badCharErrorCount = 0; + } + + if ( EMSTAT_PICO_STATUS_TIMING_NOT_MET == condSensorStatus[ sensorId ].sensorStatus ) + { + if ( ++condSensorStatus[ sensorId ].internalErrorCount > MAX_CONDUCTIVITY_SENSOR_FAILURES ) { -#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 ); - } + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_CONDUCTIVITY_SENSOR_FAULT, sensorId, condSensorStatus[ sensorId ].sensorStatus ); } } + else + { + condSensorStatus[ sensorId ].internalErrorCount = 0; + } } /*********************************************************************//** @@ -587,11 +776,15 @@ *************************************************************************/ static F32 getCalibrationAppliedConductivityValue( U32 sensorId, F32 compensatedValue ) { - F32 conductivity = pow(compensatedValue, 4) * condSensorsCalRecord.condSensors[ (CAL_DATA_DG_COND_SENSORS_T)sensorId ].fourthOrderCoeff + - pow(compensatedValue, 3) * condSensorsCalRecord.condSensors[ (CAL_DATA_DG_COND_SENSORS_T)sensorId ].thirdOrderCoeff + - pow(compensatedValue, 2) * condSensorsCalRecord.condSensors[ (CAL_DATA_DG_COND_SENSORS_T)sensorId ].secondOrderCoeff + - compensatedValue * condSensorsCalRecord.condSensors[ (CAL_DATA_DG_COND_SENSORS_T)sensorId ].gain + - condSensorsCalRecord.condSensors[ (CAL_DATA_DG_COND_SENSORS_T)sensorId ].offset; + CAL_DATA_DG_COND_SENSORS_T calTableId = condSensorCalTable[ sensorId ]; + F32 conductivity = 0.0F; + + conductivity = pow( compensatedValue, 4 ) * condSensorsCalRecord.condSensors[ calTableId ].fourthOrderCoeff + + pow( compensatedValue, 3 ) * condSensorsCalRecord.condSensors[ calTableId ].thirdOrderCoeff + + pow( compensatedValue, 2 ) * condSensorsCalRecord.condSensors[ calTableId ].secondOrderCoeff + + compensatedValue * condSensorsCalRecord.condSensors[ calTableId ].gain + + condSensorsCalRecord.condSensors[ calTableId ].offset; + return conductivity; } @@ -605,8 +798,8 @@ * @brief * The testSetConductivityOverride function overrides the compensated * conductivity value of given sensor id. - * @details Inputs: compensatedConductivityValues[] - * @details Outputs: compensatedConductivityValues[] + * @details Inputs: none + * @details Outputs: condSensorStatus * @param sensorId conductivity sensor id * @param value override compensated conductivity value * @return TRUE if override successful, FALSE if not @@ -617,11 +810,11 @@ if ( sensorId < NUM_OF_CONDUCTIVITY_SENSORS ) { - if ( isTestingActivated() ) + if ( TRUE == isTestingActivated() ) { - result = TRUE; - compensatedConductivityValues[ sensorId ].ovData = value; - compensatedConductivityValues[ sensorId ].override = OVERRIDE_KEY; + result = TRUE; + condSensorStatus[ sensorId ].compensatedCondValue.ovData = value; + condSensorStatus[ sensorId ].compensatedCondValue.override = OVERRIDE_KEY; } } @@ -632,8 +825,8 @@ * @brief * The testResetConductivityOverride function resets the override of the * conductivity sensor value. - * @details Inputs: compensatedConductivityValues[] - * @details Outputs: compensatedConductivityValues[] + * @details Inputs: none + * @details Outputs: condSensorStatus * @param sensorId conductivity sensor id * @return TRUE if reset successful, FALSE if not *************************************************************************/ @@ -643,11 +836,11 @@ if ( sensorId < NUM_OF_CONDUCTIVITY_SENSORS ) { - if ( isTestingActivated() ) + if ( TRUE == isTestingActivated() ) { - result = TRUE; - compensatedConductivityValues[ sensorId ].ovData = compensatedConductivityValues[ sensorId ].ovInitData; - compensatedConductivityValues[ sensorId ].override = OVERRIDE_RESET; + result = TRUE; + condSensorStatus[ sensorId ].compensatedCondValue.ovData = condSensorStatus[ sensorId ].compensatedCondValue.ovInitData; + condSensorStatus[ sensorId ].compensatedCondValue.override = OVERRIDE_RESET; } } @@ -667,9 +860,9 @@ { BOOL result = FALSE; - if ( isTestingActivated() ) + if ( TRUE == isTestingActivated() ) { - result = TRUE; + result = TRUE; conductivityDataPublishInterval.ovData = interval_ms / TASK_PRIORITY_INTERVAL; conductivityDataPublishInterval.override = OVERRIDE_KEY; } @@ -689,14 +882,78 @@ { BOOL result = FALSE; - if ( isTestingActivated() ) + if ( TRUE == isTestingActivated() ) { - result = TRUE; + result = TRUE; conductivityDataPublishInterval.ovData = conductivityDataPublishInterval.ovInitData; conductivityDataPublishInterval.override = OVERRIDE_RESET; } return result; } +/*********************************************************************//** + * @brief + * The testSetConductivitySensorCalibrationTable function sets the conductivity + * sensor's calibration table + * @details Inputs: none + * @details Outputs: none + * @param data pointer to the conductivity sensor calibration table data + * structure + * @return TRUE if set was successful otherwise, FALSE + *************************************************************************/ +BOOL testSetConductivitySensorCalibrationTable( CONDUCTIVITY_SENSOR_CAL_TABLE_T* data ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + CAL_DATA_DG_COND_SENSORS_T calTableId = (CAL_DATA_DG_COND_SENSORS_T)data->calTableId; + CONDUCTIVITY_SENSORS_T sensorId = (CONDUCTIVITY_SENSORS_T)data->sensorId; + + switch( sensorId ) + { + case CONDUCTIVITYSENSORS_CPI_SENSOR: + if ( CAL_DATA_CPI_COND_SENSOR == calTableId ) + { + setCondcutivitySensorCalTable( sensorId, calTableId ); + result = TRUE; + } + break; + + case CONDUCTIVITYSENSORS_CPO_SENSOR: + if ( CAL_DATA_CPO_COND_SENSOR == calTableId ) + { + setCondcutivitySensorCalTable( sensorId, calTableId ); + result = TRUE; + } + break; + + case CONDUCTIVITYSENSORS_CD1_SENSOR: + if ( CAL_DATA_CD1_COND_SENSOR == calTableId ) + { + setCondcutivitySensorCalTable( sensorId, calTableId ); + result = TRUE; + } + break; + + case CONDUCTIVITYSENSORS_CD2_SENSOR: + if ( ( CAL_DATA_CD2_COND_SENSOR == calTableId ) || + ( CAL_DATA_CD2_COND_SENSOR_CHEM_DISINFECT == calTableId ) || + ( CAL_DATA_CD2_COND_SENSOR_FILL_BICARB_TEST == calTableId ) ) + { + setCondcutivitySensorCalTable( sensorId, calTableId ); + result = TRUE; + } + break; + + default: + // Sensor ID out of range just reject with a FALSE + break; + } + } + + return result; +} + /**@}*/