Index: firmware/App/Controllers/ConductivitySensors.c =================================================================== diff -u -r92ec01cb48d91fe7315baa987e1aa051dd12df75 -r83b12013a84403fe4d7d6f70b516d623bfb2fcfd --- firmware/App/Controllers/ConductivitySensors.c (.../ConductivitySensors.c) (revision 92ec01cb48d91fe7315baa987e1aa051dd12df75) +++ firmware/App/Controllers/ConductivitySensors.c (.../ConductivitySensors.c) (revision 83b12013a84403fe4d7d6f70b516d623bfb2fcfd) @@ -1,28 +1,33 @@ /************************************************************************** * -* Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +* Copyright (c) 2020-2023 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * -* @file ConductivitySensors.c +* @file ConductivitySensors.c * -* @author (last) Quang Nguyen -* @date (last) 29-Jul-2020 +* @author (last) Dara Navaei +* @date (last) 02-Feb-2023 * -* @author (original) Quang Nguyen -* @date (original) 13-Jul-2020 +* @author (original) Quang Nguyen +* @date (original) 13-Jul-2020 * ***************************************************************************/ +#include // Used for calculating the polynomial calibration equation. #include "ConductivitySensors.h" #include "FPGA.h" +#include "NVDataMgmt.h" +#include "MessageSupport.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 @@ -31,422 +36,760 @@ // ********** 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 (MS_PER_SECOND / TASK_PRIORITY_INTERVAL) ///< Broadcast conductivity values message every second +#define SIEMENS_TO_MICROSIEMENS_CONVERSION 1000000 ///< Siemens to microSiemens conversion factor. -#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 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 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 COND_SENSOR_DECIMAL_CONVERSION 100.0F ///< 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.0F ///< Reference temperature for conductivity sensor. +#define COND_SENSOR_REPORT_PERIOD ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Broadcast conductivity values message every second. -#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 ///< 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 ///< 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 ro +#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. -// ********** private data ********** +#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. -/// 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 -}; +#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. -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 OVERRIDE_F32_T roRejectionRatio; ///< Latest RO rejection ratio +#define COND_SENSOR_PERSISTENCE_PERIOD ( 5 * MS_PER_SECOND ) ///< Persistence period for conductivity sensor out of range error. +#define INLET_WATER_COND_SENSOR_OUT_OF_RANGE_TIMEOUT_MS ( 5 * 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 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_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 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. +} 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. + U32 invalidCharCounter; +} 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. + U08 packetIndex; + U08 packetData[100]; +} EMSTAT_READ_T; + +/// Conductivity sensors structure +typedef struct +{ + U08 readCount; ///< Conductivity sensor FPGA read count (For V3). + U32 internalErrorCount; ///< Conductivity sensor internal 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 ********** + +/// Emstat boards for CPi/CPo and CD1/CD2 +typedef enum EmstatBoards +{ + 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 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 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. // ********** private function prototypes ********** -static void processCPiCPoSensorRead( U32 sensorId, U32 fgpaRead, U08 fpgaReadCount, U08 fpgaErrorCount ); -static F32 calcCompensatedConductivity( F32 conductivity, F32 temperature); +static F32 calcCompensatedConductivity( F32 conductivity, F32 temperature ); static void calcRORejectionRatio( void ); -static F32 getRORejectionRatio( void ); -static DATA_GET_PROTOTYPE( U32, getConductivityDataPublishInterval ); +static void processCPiCPoSensorRead( U32 sensorId, U08 emstatBoardSensorIndex, U32 fgpaRead, U08 fpgaReadCount, U08 fpgaErrorCount, U08 fpgaSensorFault ); -/************************************************************************* +static U32 prefixStrToSIFactor( U08 prefix ); +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 ); + +/*********************************************************************//** * @brief * The initConductivitySensors function initializes the ConductivitySensors module. - * @details - * Inputs : none - * Outputs : ConductivitySensors module initialized + * @details Inputs: none + * @details Outputs: ConductivitySensors module initialized * @return none *************************************************************************/ void initConductivitySensors( void ) { - U32 i; + U08 i; + roRejectionRatio = 0.0F; + condDataPublishCounter = DATA_PUBLISH_COUNTER_START_COUNT; for ( i = 0; i < NUM_OF_CONDUCTIVITY_SENSORS; i++ ) { - readCount[ i ] = 0; - internalErrorCount[ i ] = 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; - - // TODO: Ability to change probe type -// setFPGAConductivityProbeType( COND_SENSOR_PROBE_TYPE ); + // 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 ) ); } - roRejectionRatio.data = 0.0; - roRejectionRatio.ovData = 0.0; - roRejectionRatio.ovInitData = 0.0; - roRejectionRatio.override = OVERRIDE_RESET; + // 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_CPI_OR_CD1_INDEX ].invalidCharCounter = 0; + 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; + emstatBoardRead[ EMSTAT_CPI_CPO_BOARD ].sensors[ EMSTAT_CPO_OR_CD2_INDEX ].invalidCharCounter = 0; + + // CD1/CD2 Emstat board conductivity sensors and their corresponding temperature sensors + 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_1; + 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_CPI_OR_CD1_INDEX ].invalidCharCounter = 0; + 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; + emstatBoardRead[ EMSTAT_CD1_CD2_BOARD ].sensors[ EMSTAT_CPO_OR_CD2_INDEX ].invalidCharCounter = 0; + + // 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_HIGH_CONDUCTIVITY, ALARM_DATA_TYPE_F32, COND_SENSOR_PERSISTENCE_COUNT, COND_SENSOR_PERSISTENCE_COUNT ); - initPersistentAlarm( ALARM_ID_INLET_WATER_LOW_CONDUCTIVITY, ALARM_DATA_TYPE_F32, COND_SENSOR_PERSISTENCE_COUNT, COND_SENSOR_PERSISTENCE_COUNT ); - initPersistentAlarm( ALARM_ID_RO_REJECTION_RATIO_OUT_OF_RANGE, ALARM_DATA_TYPE_F32, RO_REJECTION_RATIO_PERSISTENCE_COUNT, RO_REJECTION_RATIO_PERSISTENCE_COUNT ); + initPersistentAlarm( ALARM_ID_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_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_CONDUCTIVITY_SENSOR_BAD_STATUS, COND_SENSOR_BAD_STATUS_PERSISTENCE_PERIOD, COND_SENSOR_BAD_STATUS_PERSISTENCE_PERIOD ); + initPersistentAlarm( ALARM_ID_DG_CPI_COND_SENSOR_INVALID_CHAR, COND_SENSORS_BAD_CHAR_TIME_OUT_MS, COND_SENSORS_BAD_CHAR_TIME_OUT_MS ); + initPersistentAlarm( ALARM_ID_DG_CPO_COND_SENSOR_INVALID_CHAR, COND_SENSORS_BAD_CHAR_TIME_OUT_MS, COND_SENSORS_BAD_CHAR_TIME_OUT_MS ); + initPersistentAlarm( ALARM_ID_DG_CD1_COND_SENSOR_INVALID_CHAR, COND_SENSORS_BAD_CHAR_TIME_OUT_MS, COND_SENSORS_BAD_CHAR_TIME_OUT_MS ); + initPersistentAlarm( ALARM_ID_DG_CD2_COND_SENSOR_INVALID_CHAR, COND_SENSORS_BAD_CHAR_TIME_OUT_MS, COND_SENSORS_BAD_CHAR_TIME_OUT_MS ); + initPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_COND_TOO_HIGH, COND_SENSOR_PERSISTENCE_PERIOD, COND_SENSOR_PERSISTENCE_PERIOD ); + initPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_COND_TOO_LOW, COND_SENSOR_PERSISTENCE_PERIOD, COND_SENSOR_PERSISTENCE_PERIOD ); + + // 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 ); } -/************************************************************************* +/*********************************************************************//** * @brief * The execConductivitySensors function gets conductivity sensors' latest * readings from FPGA and advertises them over CAN. - * @details - * Inputs : none - * Outputs : Conductivity sensors' latest reading is updated and advertised. + * @details Inputs: none + * @details Outputs: Conductivity sensors' latest reading is updated and + * advertised. * @return none *************************************************************************/ void execConductivitySensors( void ) { - processCPiCPoSensorRead( CONDUCTIVITYSENSORS_CPI_SENSOR, getFPGACPi(), getFPGACPiReadCount(), getFPGACPiErrorCount() ); - processCPiCPoSensorRead( CONDUCTIVITYSENSORS_CPO_SENSOR, getFPGACPo(), getFPGACPoReadCount(), getFPGACPoErrorCount() ); + // Check if a new calibration is available + if ( TRUE == isNewCalibrationRecordAvailable() ) + { + getNVRecord2Driver( GET_CAL_CONDUCTIVITY_SENSORS, (U08*)&condSensorsCalRecord, sizeof( condSensorsCalRecord ), + NUM_OF_CAL_DATA_COND_SENSORS, ALARM_ID_DG_COND_SENSORS_INVALID_CAL_RECORD ); + } - if ( ++conductivityDataPublicationTimerCounter >= getConductivityDataPublishInterval() ) +#ifndef _RELEASE_ + if ( HW_CONFIG_BETA == getHardwareConfigStatus() ) { - conductivityDataPublicationTimerCounter = 0; - calcRORejectionRatio(); - broadcastConductivityData( getRORejectionRatio(), getConductivityValue(CONDUCTIVITYSENSORS_CPI_SENSOR), - getConductivityValue(CONDUCTIVITYSENSORS_CPO_SENSOR) ); + 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 ( ++condDataPublishCounter >= getU32OverrideValue( &conductivityDataPublishInterval ) ) + { + CONDUCTIVITY_DATA_T data; + + calcRORejectionRatio(); + 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 ) ); + } } -/************************************************************************* +/*********************************************************************//** * @brief - * The checkInletWaterConductivity checks inlet water conductivity value - * and triggers an alarm when conductivity value is out of allowed range. - * @details - * Inputs : none - * Outputs : Trigger alarms when conductivity is out of allowed range - * @return none + * The execConductivitySensorsSelfTest function executes the conductivity + * sensors' self-test. + * @details Inputs: none + * @details Outputs: none + * @return PressuresSelfTestResult (SELF_TEST_STATUS_T) *************************************************************************/ -void checkInletWaterConductivity( void ) +SELF_TEST_STATUS_T execConductivitySensorsSelfTest( void ) { - 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 ); + 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 ); + SELF_TEST_STATUS_T result = ( TRUE == calStatus ? SELF_TEST_STATUS_PASSED : SELF_TEST_STATUS_FAILED ); - checkPersistentAlarm( ALARM_ID_INLET_WATER_HIGH_CONDUCTIVITY, isCondTooHigh, conductivity ); - checkPersistentAlarm( ALARM_ID_INLET_WATER_LOW_CONDUCTIVITY, isCondTooLow, conductivity ); + return result; } -/************************************************************************* +/*********************************************************************//** * @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 : none - * Outputs : Triggered alarm + * The checkInletWaterConductivity function checks inlet water conductivity value + * and triggers an alarm when conductivity value is not within the specified + * values. + * @details Inputs: CPi sensor conductivity + * @details Outputs: Trigger warning alarm if conductivity is in the warning + * range. Trigger alarm if conductivity is below minimum conductivity. * @return none *************************************************************************/ -void checkRORejectionRatio( void ) +void checkInletWaterConductivity( void ) { - F32 const roRejectionRatio = getRORejectionRatio(); - 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 ); +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_WATER_QUALITY_CHECK ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { + DG_OP_MODE_T opMode = getCurrentOperationMode(); + F32 conductivity = getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ); + BOOL isConductTooLow = ( conductivity < MAX_COND_SENSOR_CPI_WARNING_LOW_US_PER_CM ? TRUE : FALSE ); + BOOL isConductTooHigh = ( conductivity > MAX_COND_SENSOR_CPI_WARNING_HIGH_US_PER_CM ? TRUE : FALSE ); + + switch( opMode ) + { + case DG_MODE_GENE: + case DG_MODE_FILL: + case DG_MODE_DRAI: + if ( TRUE == isAlarmActive( ALARM_ID_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_INLET_WATER_CONDUCTIVITY_IN_LOW_RANGE, isConductTooLow, conductivity, MAX_COND_SENSOR_CPI_WARNING_LOW_US_PER_CM ); + + if ( TRUE == isAlarmActive( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_HIGH_RANGE ) ) + { + isConductTooHigh = ( conductivity <= MIN_COND_SENSOR_CPI_WARNING_HIGH_US_PER_CM ? FALSE : TRUE ); + } + + // Per PRS 404 + checkPersistentAlarm( ALARM_ID_INLET_WATER_CONDUCTIVITY_IN_HIGH_RANGE, isConductTooHigh, conductivity, MAX_COND_SENSOR_CPI_WARNING_HIGH_US_PER_CM ); + break; + + case DG_MODE_INIT: + case DG_MODE_STAN: + case DG_MODE_FLUS: + case DG_MODE_HEAT: + case DG_MODE_CHEM: + case DG_MODE_CHFL: + if ( VALVE_STATE_OPEN == getValveStateName( VPI ) ) + { + // 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; + } + } } -/************************************************************************* +/*********************************************************************//** * @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 + * @details Inputs: compensatedConductivityValues[] + * @details Outputs: none + * @param sensorId conductivity sensor id * @return compensated conductivity *************************************************************************/ F32 getConductivityValue( U32 sensorId ) { - F32 result = 0; + F32 result = 0.0F; if ( sensorId < NUM_OF_CONDUCTIVITY_SENSORS ) { - if ( OVERRIDE_KEY == compensatedConductivityValues[ sensorId ].override ) - { - result = compensatedConductivityValues[ sensorId ].ovData; - } - else - { - result = compensatedConductivityValues[ sensorId ].data; - } + // 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 { - activateAlarmNoData( ALARM_ID_DG_SOFTWARE_FAULT ); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_CONDUCTIVITY_SENSOR_ID, sensorId ); } 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 - * Outputs : none - * @param conductivity Conductivity value - * @param temperature Temperature to compensate conductivity with + * reference temperature of 25 degree Celsius. + * @details Inputs: conductivity, temperature + * @details Outputs: none + * @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( 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) ) ); + // EC = EC_25 * (1 + temp_coef * ( temperature - 25 )) + F32 compensatedCoef = ( 1.0F + ( COND_SENSOR_TEMPERATURE_COEF * ( temperature - COND_SENSOR_REFERENCE_TEMPERATURE ) ) ); - return conductivity * compensatedCoef; + return conductivity / compensatedCoef; } -/************************************************************************* +/*********************************************************************//** * @brief - * The getRORejectionRatio function gets the latest RO rejection ratio - * @details - * Inputs: roRejectionRatio - * Outputs: none - * @return RO rejection ratio - *************************************************************************/ -F32 getRORejectionRatio( void ) -{ - F32 result = roRejectionRatio.data; - - if ( OVERRIDE_KEY == roRejectionRatio.override ) - { - result = roRejectionRatio.ovData; - } - - return result; -} - -/************************************************************************* - * @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 and CPo sensor conductivity - * Outputs: RO rejection ratio + * the CPi sensor conductivity value and CPo sensor conductivity value. + * @details Inputs: CPi sensor conductivity, CPo sensor conductivity + * @details 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.data = RO_REJECTION_RATIO_OUT_OF_RANGE_VALUE; + F32 cpi = getConductivityValue( CONDUCTIVITYSENSORS_CPI_SENSOR ); + F32 cpo = getConductivityValue( CONDUCTIVITYSENSORS_CPO_SENSOR ); - if ( cpi > 0 ) + roRejectionRatio = RO_REJECTION_RATIO_OUT_OF_RANGE_VALUE; + + if ( fabs(cpi) >= NEARLY_ZERO ) { - roRejectionRatio.data = cpo / cpi; + 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 + * @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 ) +static void processCPiCPoSensorRead( U32 sensorId, U08 emstatBoardSensorIndex, U32 fgpaRead, U08 fpgaReadCount, U08 fpgaErrorCount, U08 fpgaSensorFault ) { - if ( fpgaErrorCount == 0 ) + if ( ( 0 == fpgaErrorCount ) && ( 0 == fpgaSensorFault ) ) { - if ( ( readCount[ sensorId ] != fpgaReadCount ) ) + if ( ( condSensorStatus[ sensorId ].readCount != fpgaReadCount ) ) { - F32 const temperature = getTemperatureValue( associateTempSensor[ sensorId ] ); - F32 const conductivity = ( (F32)( fgpaRead ) / COND_SENSOR_DECIMAL_CONVERSION ); - readCount[ sensorId ] = fpgaReadCount; - internalErrorCount[ sensorId ] = 0; - compensatedConductivityValues[ sensorId ].data = 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( conductivity, temperature ); + + 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 ) { - 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 ) ) { - 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 ); + } } } } -/************************************************************************* +/*********************************************************************//** * @brief - * The getConductivityDataPublishInterval function gets the conductivity - * data publication interval. - * @details - * Inputs : conductivityDataPublishInterval - * Outputs : none - * @return the current conductivity data publication interval (in ms/task interval). + * The prefixStrToSIFactor function returns SI factor based on a given ascii prefix. + * @details Inputs: none + * @details Outputs: none + * @param prefix ascii value of the prefix + * @return SI factor of the given ascii prefix *************************************************************************/ -static U32 getConductivityDataPublishInterval( void ) +static U32 prefixStrToSIFactor( U08 prefix ) { - U32 result = conductivityDataPublishInterval.data; + U32 result; - if ( OVERRIDE_KEY == conductivityDataPublishInterval.override ) + switch ( prefix ) { - result = conductivityDataPublishInterval.ovData; + case 'm': + result = 1000; + break; + + case 'u': + result = 1000000; + break; + + default: + result = 1; + break; } return result; } -/************************************************************************* - * TEST SUPPORT FUNCTIONS +/*********************************************************************//** + * @brief + * 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 processEmstatBoard( EMSTAT_BOARD_T board ) +{ + U08 emstatByte = 0; + U16 rxFifoCount = 0; + static U32 maxRxFifoCount = 0; + static U32 numRxFifoEmpty = 0; + static U32 numRxFifoCheck = 0; + switch ( board ) + { + // TODO should check Rx FIFO to see if a character exists? + case EMSTAT_CPI_CPO_BOARD: + // Check for continuous incoming bytes + rxFifoCount = getFPGAEmstatCPiCPoRxFifoCount() & 0x7FFF; + numRxFifoCheck++; + if (numRxFifoCheck == 10000) + { + maxRxFifoCount = 0; + numRxFifoEmpty = 0; + } + if (rxFifoCount > maxRxFifoCount) maxRxFifoCount = rxFifoCount; + if (rxFifoCount == 0) numRxFifoEmpty++; -/************************************************************************* + checkFPGAPersistentAlarms( FPGA_PERS_ERROR_CPI_CPO_COND_SENSORS, rxFifoCount ); + + // Only process the sensor read if there is a new byte + if ( 0 != rxFifoCount ) + { + emstatByte = getFPGAEmstatCPiCPoByteOut(); + processEmstatSensorRead( &emstatBoardRead[ EMSTAT_CPI_CPO_BOARD ], emstatByte ); + } + break; + + case EMSTAT_CD1_CD2_BOARD: + // Check for continuous incoming bytes + rxFifoCount = getFPGAEmstatCD1CD2RxFifoCount() & 0x7FFF;; + checkFPGAPersistentAlarms( FPGA_PERS_ERROR_CD1_CD2_COND_SENSORS, rxFifoCount ); + + // 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; + } +} + +/*********************************************************************//** * @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 - * @return TRUE if override successful, FALSE if not + * The processEmstatSensorRead function processes the Emsat boards' data + * that is received from the boards + * @details Inputs: none + * @details Outputs: none + * @param read package the structure of each Emstat board + * @param emstatByte the received byte from the sensor + * @return none *************************************************************************/ -BOOL testSetConductivityOverride( U32 sensorId, F32 value ) +static void processEmstatSensorRead( EMSTAT_READ_T* readPackage, U08 emstatByte ) { - BOOL result = FALSE; + switch ( emstatByte ) + { + case 'P': + if ( FALSE == readPackage->packageStarted) + { + readPackage->packageStarted = TRUE; + readPackage->packageIndex = 0; + readPackage->packetIndex = 0; + readPackage->packetData[readPackage->packetIndex++] = emstatByte; + } + break; - if ( sensorId < NUM_OF_CONDUCTIVITY_SENSORS ) + case ';': + if ( TRUE == readPackage->packageStarted ) + { + processEmstatMeasurementDataPackets( EMSTAT_CPI_OR_CD1_INDEX, readPackage, (EMSTAT_VARIABLE_T*)readPackage->package ); + readPackage->packageIndex = 0; + readPackage->packetData[readPackage->packetIndex++] = emstatByte; + } + break; + + case '\n': + if ( TRUE == readPackage->packageStarted ) + { + processEmstatMeasurementDataPackets( EMSTAT_CPO_OR_CD2_INDEX, readPackage, (EMSTAT_VARIABLE_T*)readPackage->package ); + readPackage->packageStarted = FALSE; + readPackage->packetData[readPackage->packetIndex++] = emstatByte; + } + break; + + default: + if ( TRUE == readPackage->packageStarted ) + { + readPackage->packetData[readPackage->packetIndex++] = emstatByte; + 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_OK == condSensorStatus[ sensorId ].sensorStatus ? FALSE : TRUE ); + ALARM_ID_T badHexAlarm = readPackage->sensors[ boardSensorIndex ].condSnsrHex2StrAlarm; + BOOL isConvNotValid = FALSE; + + if ( FALSE == isSensorStatusBad ) { - if ( isTestingActivated() ) + U32 prefix = prefixStrToSIFactor( receivedPackets->prefix ); + convStatus = hexStrToDec( receivedPackets->value, &condSensorStatus[ sensorId ].rawEmstatCondValue, sizeof( receivedPackets->value ) ); + if (FALSE == convStatus) { - result = TRUE; - compensatedConductivityValues[ sensorId ].ovData = value; - compensatedConductivityValues[ sensorId ].override = OVERRIDE_KEY; + readPackage->sensors[ boardSensorIndex ].invalidCharCounter++; } + 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( conductivity, temperature ); + + condSensorStatus[ sensorId ].internalErrorCount = 0; + condSensorStatus[ sensorId ].compensatedCondValue.data = getCalibrationAppliedConductivityValue( sensorId, compensatedCond ); + condSensorStatus[ sensorId ].rawCondValue = conductivity; } - return result; + isConvNotValid = ( TRUE == convStatus ? FALSE : TRUE ); + // Check the conductivity sensors bad status alarm + checkPersistentAlarm( badHexAlarm, isConvNotValid, isConvNotValid, COND_SENSORS_BAD_CHAR_TIME_OUT_MS ); + checkPersistentAlarm( ALARM_ID_DG_CONDUCTIVITY_SENSOR_BAD_STATUS, isSensorStatusBad, condSensorStatus[ sensorId ].sensorStatus, + EMSTAT_PICO_STATUS_TIMING_NOT_MET ); + + if ( EMSTAT_PICO_STATUS_OK != condSensorStatus[ sensorId ].sensorStatus ) + { + if ( ++condSensorStatus[ sensorId ].internalErrorCount > MAX_CONDUCTIVITY_SENSOR_FAILURES ) + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_CONDUCTIVITY_SENSOR_FAULT, sensorId, condSensorStatus[ sensorId ].sensorStatus ); + } + } + else + { + condSensorStatus[ sensorId ].internalErrorCount = 0; + } } -/************************************************************************* +/*********************************************************************//** * @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. - * @return TRUE if reset successful, FALSE if not + * The getCalibrationAppliedConductivityValue function gets the temperature + * compensated conductivity value and applies calibration to it. + * @details Inputs: condSensorsCalRecord + * @details Outputs: none + * @param sensorId which is the conductivity sensor ID + * @param compensatedValue which is the temperature compensated conductivity + * value of the conductivity sensor + * @return the calibration applied conductivity value *************************************************************************/ -BOOL testResetConductivityOverride( U32 sensorId ) +static F32 getCalibrationAppliedConductivityValue( U32 sensorId, F32 compensatedValue ) { - BOOL result = FALSE; + CAL_DATA_DG_COND_SENSORS_T id = (CAL_DATA_DG_COND_SENSORS_T)sensorId; + F32 conductivity = 0.0F; - if ( sensorId < NUM_OF_CONDUCTIVITY_SENSORS ) + if ( DG_MODE_CHEM == getCurrentOperationMode() ) { - if ( isTestingActivated() ) + // If the mode is in chemical disinfect, use the chemical disinfect calibration data for CD1 and CD2 + if ( CAL_DATA_CD1_COND_SENSOR == id ) { - result = TRUE; - compensatedConductivityValues[ sensorId ].ovData = compensatedConductivityValues[ sensorId ].ovInitData; - compensatedConductivityValues[ sensorId ].override = OVERRIDE_RESET; + id = CAL_DATA_CD1_CHEM_DIS_COND_SENSOR; } + else if ( CAL_DATA_CD2_COND_SENSOR == id ) + { + id = CAL_DATA_CD2_CHEM_DIS_COND_SENSOR; + } } - return result; + conductivity = pow( compensatedValue, 4 ) * condSensorsCalRecord.condSensors[ id ].fourthOrderCoeff + + pow( compensatedValue, 3 ) * condSensorsCalRecord.condSensors[ id ].thirdOrderCoeff + + pow( compensatedValue, 2 ) * condSensorsCalRecord.condSensors[ id ].secondOrderCoeff + + compensatedValue * condSensorsCalRecord.condSensors[ id ].gain + + condSensorsCalRecord.condSensors[ id ].offset; + return conductivity; } + /************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + + +/*********************************************************************//** * @brief - * The testSetRORejectionRatioOverride function overrides the RO Rejection ratio. - * @details - * Inputs : roRejectionRatio - * Outputs : roRejectionRatio - * @param value Override RO Rejection ratio value + * The testSetConductivityOverride function overrides the compensated + * conductivity value of given sensor id. + * @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 *************************************************************************/ -BOOL testSetRORejectionRatioOverride( F32 value ) +BOOL testSetConductivityOverride( U32 sensorId, F32 value ) { BOOL result = FALSE; - if ( isTestingActivated() ) + if ( sensorId < NUM_OF_CONDUCTIVITY_SENSORS ) { - result = TRUE; - roRejectionRatio.ovData = value; - roRejectionRatio.override = OVERRIDE_KEY; + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + condSensorStatus[ sensorId ].compensatedCondValue.ovData = value; + condSensorStatus[ sensorId ].compensatedCondValue.override = OVERRIDE_KEY; + } } return result; } -/************************************************************************* +/*********************************************************************//** * @brief - * The testResetRORejectionRatioOverride function resets the override of - * the RO Rejection ratio. - * @details - * Inputs : roRejectionRatio - * Outputs : roRejectionRatio + * The testResetConductivityOverride function resets the override of the + * conductivity sensor value. + * @details Inputs: none + * @details Outputs: condSensorStatus + * @param sensorId conductivity sensor id * @return TRUE if reset successful, FALSE if not *************************************************************************/ -BOOL testResetRORejectionRatioOverride( void ) +BOOL testResetConductivityOverride( U32 sensorId ) { BOOL result = FALSE; - if ( isTestingActivated() ) + if ( sensorId < NUM_OF_CONDUCTIVITY_SENSORS ) { - result = TRUE; - roRejectionRatio.ovData = roRejectionRatio.ovInitData; - roRejectionRatio.override = OVERRIDE_RESET; + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + condSensorStatus[ sensorId ].compensatedCondValue.ovData = condSensorStatus[ sensorId ].compensatedCondValue.ovInitData; + condSensorStatus[ sensorId ].compensatedCondValue.override = OVERRIDE_RESET; + } } 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) + * @details Inputs: conductivityDataPublishInterval + * @details Outputs: conductivityDataPublishInterval + * @param value override conductivity data publish interval with (in ms) * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetConductivityDataPublishIntervalOverride( U32 interval_ms ) @@ -463,13 +806,12 @@ return result; } -/************************************************************************* +/*********************************************************************//** * @brief * The testResetConductivityDataPublishIntervalOverride function resets * the override of the conductivity data publish interval. - * @details - * Inputs : conductivityDataPublishInterval - * Outputs : conductivityDataPublishInterval + * @details Inputs: conductivityDataPublishInterval + * @details Outputs: conductivityDataPublishInterval * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetConductivityDataPublishIntervalOverride( void )