Index: firmware/App/Monitors/Conductivity.c =================================================================== diff -u -r99498a5bab0a1f4c706376feceadc66df6d1c22e -r2652d50bbc5e78ed6fe3ad9ccbca0be6f802f1ff --- firmware/App/Monitors/Conductivity.c (.../Conductivity.c) (revision 99498a5bab0a1f4c706376feceadc66df6d1c22e) +++ firmware/App/Monitors/Conductivity.c (.../Conductivity.c) (revision 2652d50bbc5e78ed6fe3ad9ccbca0be6f802f1ff) @@ -19,9 +19,9 @@ #include // For memcpy #include "Conductivity.h" +#include "ConductivitySensor.h" #include "MessageSupport.h" #include "Messaging.h" -#include "OperationModes.h" #include "TaskPriority.h" #include "Utilities.h" @@ -32,17 +32,46 @@ // ********** private definitions ********** -#define COND_SENSOR_REPORT_PERIOD ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Broadcast conductivity values message every second. -#define DATA_PUBLISH_COUNTER_START_COUNT 40 ///< Data publish counter start count. +#define COND_SENSOR_REPORT_PERIOD ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Broadcast conductivity values message every second. +#define DATA_PUBLISH_COUNTER_START_COUNT 40 ///< Data publish counter start count. +#define CONDUCTIVITY_SAMPLE_FILTER_MS ( 500 ) ///< Filter conductivity data for given time +#define CONDUCTIVITY_TEMP_SAMPLE_FILTER_MS ( 500 ) ///< Filter conductivity temperature data for given time +#define SIZE_OF_FLOW_ROLLING_AVG ( CONDUCTIVITY_SAMPLE_FILTER_MS / TASK_PRIORITY_INTERVAL ) ///< Filtered conductivity moving average sample count. +#define SIZE_OF_FLOW_TEMP_ROLLING_AVG ( CONDUCTIVITY_TEMP_SAMPLE_FILTER_MS / TASK_PRIORITY_INTERVAL ) ///< Filtered conductivity temprature moving average sample count. +/// Filter conductivity readings record. +typedef struct +{ + F32 conductivityReadings[ SIZE_OF_FLOW_ROLLING_AVG ]; ///< Holds conductivity sample rolling average. + U32 conductivityReadingsIdx; ///< Index for next sample in rolling average array. + F32 conductivityReadingsTotal; ///< Rolling total - used to calc average. + U32 conductivityReadingsCount; ///< Number of samples in rolling average buffer +} FILTER_CONDUCTIVITY_READINGS_T; + +/// Filter conductivity sensor temperature readings record. +typedef struct +{ + F32 conductivityTempReadings[ SIZE_OF_FLOW_ROLLING_AVG ]; ///< Holds conductivity sample rolling average. + U32 conductivityTempReadingsIdx; ///< Index for next sample in rolling average array. + F32 conductivityTempReadingsTotal; ///< Rolling total - used to calc average. + U32 conductivityTempReadingsCount; ///< Number of samples in rolling average buffer +} FILTER_CONDUCTIVITY_TEMPERATURE_READINGS_T; + // ********** private data ********** -static U32 conductivityPublishTimerCounter; ///< Conductivity data publication counter. -static OVERRIDE_U32_T conductivityDataPublishInterval; ///< Conductivity sensors publish time interval override. +static FILTER_CONDUCTIVITY_READINGS_T filteredConductivityReadings[NUM_OF_CONDUCTIVITY_SENSORS]; ///< Filtered conductivity reading for conductivity sensors. +static OVERRIDE_F32_T filteredcurrentConductivityReadings[ NUM_OF_CONDUCTIVITY_SENSORS ]; ///< filtered current conductivity sensor conductivity readings (overrideable). +static FILTER_CONDUCTIVITY_TEMPERATURE_READINGS_T filteredConductivityTemperatureReadings[NUM_OF_CONDUCTIVITY_SENSORS]; ///< Filtered temperature reading for conductivity sensors. +static OVERRIDE_F32_T filteredcurrentTemperatureReadings[ NUM_OF_CONDUCTIVITY_SENSORS ]; ///< filtered current conductivity sensor temperature readings (overrideable). +static U32 conductivityPublishTimerCounter; ///< Conductivity data publication counter. +static OVERRIDE_U32_T conductivityDataPublishInterval; ///< Conductivity sensors publish time interval override. // ********** private function prototypes ********** static void publishConductivitySensorsData( void ); +static void filterConductivitySensors( void ); +static void filterConductivitySensorReadings( void ); +static void filterConductivitySensorTemperatureReadings( void ); /*********************************************************************//** * @brief @@ -53,15 +82,39 @@ *************************************************************************/ void initConductivity( void ) { - conductivityPublishTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; + CONDUCTIVITY_SENSORS_T sensor; + // initialize conductivity sensors driver + initConductivitySensors(); + + conductivityPublishTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; + + // Initialize override structures for each conductivity sensor + for ( sensor = CONDUCTIVITYSENSORS_FIRST; sensor < NUM_OF_CONDUCTIVITY_SENSORS; sensor++ ) + { + filteredcurrentConductivityReadings[ sensor ].data = 0.0F; + filteredcurrentConductivityReadings[ sensor ].ovData = 0.0F; + filteredcurrentConductivityReadings[ sensor ].ovInitData = 0.0F; + filteredcurrentConductivityReadings[ sensor ].override = OVERRIDE_RESET; + + filteredConductivityReadings[ sensor ].conductivityReadingsIdx = 0; + filteredConductivityReadings[ sensor ].conductivityReadingsTotal = 0.0F; + filteredConductivityReadings[ sensor ].conductivityReadingsCount = 0; + + filteredcurrentTemperatureReadings[ sensor ].data = 0.0F; + filteredcurrentTemperatureReadings[ sensor ].ovData = 0.0F; + filteredcurrentTemperatureReadings[ sensor ].ovInitData = 0.0F; + filteredcurrentTemperatureReadings[ sensor ].override = OVERRIDE_RESET; + + filteredConductivityTemperatureReadings[ sensor ].conductivityTempReadingsIdx = 0; + filteredConductivityTemperatureReadings[ sensor ].conductivityTempReadingsTotal = 0.0F; + filteredConductivityTemperatureReadings[ sensor ].conductivityTempReadingsCount = 0; + } + conductivityDataPublishInterval.data = COND_SENSOR_REPORT_PERIOD; conductivityDataPublishInterval.ovData = COND_SENSOR_REPORT_PERIOD; conductivityDataPublishInterval.ovInitData = 0; conductivityDataPublishInterval.override = OVERRIDE_RESET; - - // initialize conductivity sensors driver - initConductivitySensors(); } /*********************************************************************//** @@ -85,17 +138,154 @@ execConductivitySensorWrite(); execConductivitySensorRead(); + filterConductivitySensors(); // publish conductivity sensors publishConductivitySensorsData(); } /*********************************************************************//** * @brief - * The publishConductivitySensorsData function publishes RO conductivity data + * The filterConductivitySensors function gets averages the raw conductivity + * and temperature from the conductivity sensor. + * @details \b Inputs: conductivity readings from FPGA + * @details \b Outputs: filteredConductivityReadings[], filterConductivitySensorTemperatureReadings[] + * @return none + *************************************************************************/ +static void filterConductivitySensors( void ) +{ + //Filter conductivity sensor reading + filterConductivitySensorReadings(); + //Filter conductivity sensor temperature + filterConductivitySensorTemperatureReadings(); +} + +/*********************************************************************//** + * @brief + * The getFilteredConductivity function gets the filtered current conductivity (in uS/cm) + * for a given conductivity sensor. + * @details \b Alarm: ALARM_ID_FP_SOFTWARE_FAULT if given sensor is invalid. + * @details \b Inputs: filteredcurrentConductivityReadings[] + * @details \b Outputs: none + * @param sensor ID of conductivity sensor to get filtered conductivity reading for. + * @return The filtered current conductivity (in uS/cm) for the given conductivity sensor + *************************************************************************/ +F32 getFilteredConductivity( CONDUCTIVITY_SENSORS_T sensor ) +{ + F32 result = 0.0F; + + if ( sensor < NUM_OF_CONDUCTIVITY_SENSORS ) + { + result = filteredcurrentConductivityReadings[ sensor ].data; + if ( OVERRIDE_KEY == filteredcurrentConductivityReadings[ sensor ].override ) + { + result = filteredcurrentConductivityReadings[ sensor ].ovData; + } + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_FP_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_FILTERED_CONDUCTIVITY_SENSOR_ID, (U32)sensor ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The filterConductivitySensorReadings function filters the conductivity rates for + * defined interval to get average conductivity rates. + * @details \b Inputs: filteredConductivityReadings[] + * @details \b Outputs: filteredConductivityReadings[], filteredcurrentConductivityReadings[] + * @return none + *************************************************************************/ +static void filterConductivitySensorReadings( void ) +{ + CONDUCTIVITY_SENSORS_T sensor; + + for ( sensor = CONDUCTIVITYSENSORS_FIRST; sensor < NUM_OF_CONDUCTIVITY_SENSORS; sensor++ ) + { + F32 rawCond = (F32)getConductivityValue( sensor ); + + // TODO - calibrate + + if ( filteredConductivityReadings[sensor].conductivityReadingsCount >= SIZE_OF_FLOW_ROLLING_AVG ) + { + filteredConductivityReadings[sensor].conductivityReadingsTotal -= filteredConductivityReadings[sensor].conductivityReadings[ filteredConductivityReadings[sensor].conductivityReadingsIdx ]; + } + filteredConductivityReadings[sensor].conductivityReadings[ filteredConductivityReadings[sensor].conductivityReadingsIdx ] = rawCond; + filteredConductivityReadings[sensor].conductivityReadingsTotal += rawCond; + filteredConductivityReadings[sensor].conductivityReadingsIdx = INC_WRAP( filteredConductivityReadings[sensor].conductivityReadingsIdx, 0, SIZE_OF_FLOW_ROLLING_AVG - 1 ); + filteredConductivityReadings[sensor].conductivityReadingsCount = INC_CAP( filteredConductivityReadings[sensor].conductivityReadingsCount, SIZE_OF_FLOW_ROLLING_AVG ); + filteredcurrentConductivityReadings[sensor].data = filteredConductivityReadings[sensor].conductivityReadingsTotal / (F32)filteredConductivityReadings[sensor].conductivityReadingsCount; + } +} + +/*********************************************************************//** + * @brief + * The getFilteredConductivitySensorTemperature function gets the filtered + * temperature (in C) for a given conductivity sensor. + * @details \b Alarm: ALARM_ID_FP_SOFTWARE_FAULT if given sensor is invalid. + * @details \b Inputs: filteredConductivityTemperatureReadings[] + * @details \b Outputs: none + * @param sensor ID of conductivity sensor to get filtered conductivity reading for. + * @return The filtered current temperature (in C) for the given conductivity sensor + *************************************************************************/ +F32 getFilteredConductivitySensorTemperature( CONDUCTIVITY_SENSORS_T sensor ) +{ + F32 result = 0.0F; + + if ( sensor < NUM_OF_CONDUCTIVITY_SENSORS ) + { + result = filteredcurrentTemperatureReadings[ sensor ].data; + if ( OVERRIDE_KEY == filteredcurrentTemperatureReadings[ sensor ].override ) + { + result = filteredcurrentTemperatureReadings[ sensor ].ovData; + } + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_FP_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_FILTERED_CONDUCTIVITY_SENSOR_ID, (U32)sensor ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The filterConductivitySensorTemperatureReadings function filters the temperature + * rates for defined interval to get average conductivity rates. + * @details \b Inputs: filteredConductivityTemperatureReadings[] + * @details \b Outputs: filteredConductivityTemperatureReadings[], filteredcurrentTemperatureReadings[] + * @return none + *************************************************************************/ +static void filterConductivitySensorTemperatureReadings( void ) +{ + CONDUCTIVITY_SENSORS_T sensor; + + for ( sensor = CONDUCTIVITYSENSORS_FIRST; sensor < NUM_OF_CONDUCTIVITY_SENSORS; sensor++ ) + { + F32 rawTemp = (F32)getConductivityTemperatureValue( sensor ); + + // TODO - calibrate + + if ( filteredConductivityTemperatureReadings[sensor].conductivityTempReadingsCount >= SIZE_OF_FLOW_ROLLING_AVG ) + { + filteredConductivityTemperatureReadings[sensor].conductivityTempReadingsTotal -= filteredConductivityTemperatureReadings[sensor].conductivityTempReadings[ filteredConductivityTemperatureReadings[sensor].conductivityTempReadingsIdx ]; + } + filteredConductivityTemperatureReadings[sensor].conductivityTempReadings[ filteredConductivityTemperatureReadings[sensor].conductivityTempReadingsIdx ] = rawTemp; + filteredConductivityTemperatureReadings[sensor].conductivityTempReadingsTotal += rawTemp; + filteredConductivityTemperatureReadings[sensor].conductivityTempReadingsIdx = INC_WRAP( filteredConductivityTemperatureReadings[sensor].conductivityTempReadingsIdx, 0, SIZE_OF_FLOW_ROLLING_AVG - 1 ); + filteredConductivityTemperatureReadings[sensor].conductivityTempReadingsCount = INC_CAP( filteredConductivityTemperatureReadings[sensor].conductivityTempReadingsCount, SIZE_OF_FLOW_ROLLING_AVG ); + filteredcurrentTemperatureReadings[sensor].data = filteredConductivityTemperatureReadings[sensor].conductivityTempReadingsTotal / (F32)filteredConductivityTemperatureReadings[sensor].conductivityTempReadingsCount; + } +} + +/*********************************************************************//** + * @brief + * The publishConductivitySensorsData function publishes FP conductivity data * at a set interval. * @details \b Inputs: conductivityPublishTimerCounter * @details \b Outputs: conductivityPublishTimerCounter - * @details \b Message \b Sent: MSG_ID_RO_CONDUCTIVITY_DATA to publish conductivity data. + * @details \b Message \b Sent: MSG_ID_FP_CONDUCTIVITY_DATA to publish conductivity data. * @return none *************************************************************************/ static void publishConductivitySensorsData( void ) @@ -105,11 +295,11 @@ { CONDUCTIVITY_DATA_T data; - data.p9Conductivity = getConductivityValue( P9_COND ); - data.p18Conductivity = getConductivityValue( P18_COND ); + data.p9Conductivity = getFilteredConductivity( P9_COND ); + data.p18Conductivity = getFilteredConductivity( P18_COND ); conductivityPublishTimerCounter = 0; - broadcastData( MSG_ID_FP_CONDUCTIVITY_DATA, COMM_BUFFER_OUT_CAN_RO_BROADCAST, (U08*)&data, sizeof( CONDUCTIVITY_DATA_T ) ); + broadcastData( MSG_ID_FP_CONDUCTIVITY_DATA, COMM_BUFFER_OUT_CAN_FP_BROADCAST, (U08*)&data, sizeof( CONDUCTIVITY_DATA_T ) ); } } @@ -136,4 +326,39 @@ return result; } +/*********************************************************************//** + * @brief + * The testConductivitySensorFilteredReadingsOverride function overrides the + * filtered value of the specified conductivity sensor with a given value. + * @details \b Inputs: none + * @details \b Outputs: filteredcurrentConductivityReadings[] + * @param message Override message from Dialin which includes a sensor + * ID and override value of the conductivity rate for that sensor. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testConductivitySensorFilteredReadingsOverride( MESSAGE_T *message ) +{ + BOOL result = f32ArrayOverride( message, &filteredcurrentConductivityReadings[0], NUM_OF_CONDUCTIVITY_SENSORS - 1 ); + + return result; +} + +/*********************************************************************//** + * @brief + * The testConductivitySensorFilteredTemperatureReadingsOverride function + * overrides the filtered value of the specified conductivity sensor + * with a given value. + * @details \b Inputs: none + * @details \b Outputs: filteredcurrentTemperatureReadings[] + * @param message Override message from Dialin which includes a sensor + * ID and override value of the conductivity rate for that sensor. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testConductivitySensorFilteredTemperatureReadingsOverride( MESSAGE_T *message ) +{ + BOOL result = f32ArrayOverride( message, &filteredcurrentTemperatureReadings[0], NUM_OF_CONDUCTIVITY_SENSORS - 1 ); + + return result; +} + /**@}*/