/************************************************************************** * * Copyright (c) 2024-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 Conductivity.c * * @author (last) Sean Nash * @date (last) 09-Nov-2024 * * @author (original) Sean Nash * @date (original) 09-Nov-2024 * ***************************************************************************/ #include // Used for calculating the polynomial calibration equation. #include // For memcpy #include "Conductivity.h" #include "ConductivitySensor.h" #include "MessageSupport.h" #include "Messaging.h" #include "OperationModes.h" #include "TaskPriority.h" #include "Utilities.h" /** * @addtogroup Conductivity * @{ */ // ********** 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 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; // ********** private data ********** 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 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 ); /*********************************************************************//** * @brief * The initConductivity function initializes the Conductivity unit. * @details \b Inputs: none * @details \b Outputs: Conductivity unit variables initialized * @return none *************************************************************************/ void initConductivity( void ) { 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 = 0F; } conductivityDataPublishInterval.data = COND_SENSOR_REPORT_PERIOD; conductivityDataPublishInterval.ovData = COND_SENSOR_REPORT_PERIOD; conductivityDataPublishInterval.ovInitData = 0; conductivityDataPublishInterval.override = OVERRIDE_RESET; } /*********************************************************************//** * @brief * The execConductivity function gets conductivity sensors' latest * readings from FPGA and publishes them over CAN. * @details \b Inputs: none * @details \b Outputs: Conductivity sensor latest reading is updated and * published. * @return none *************************************************************************/ void execConductivity( void ) { //read conductivity sensors raw value readConductivitySensors(); //control conductivity sensor // TODO : need more clarity on why and when to execute following control. handleConductivitySensorsReset(); handleConductivitySensorsInitProcedure(); execConductivitySensorWrite(); execConductivitySensorRead(); filterConductivitySensors(); // publish conductivity sensors publishConductivitySensorsData(); } /*********************************************************************//** * @brief * The filterConductivitySensors function gets averages the raw conductivity. * @details \b Inputs: conductivity readings from FPGA * @details \b Outputs: filteredConductivityReadings[] * @return none *************************************************************************/ static void filterConductivitySensors( void ) { //Filter conductivity sensor reading filterConductivitySensorReadings(); } /*********************************************************************//** * @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 rawFlow = (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 ] = rawFlow; filteredConductivityReadings[sensor].conductivityReadingsTotal += rawFlow; 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 publishConductivitySensorsData function publishes RO 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. * @return none *************************************************************************/ static void publishConductivitySensorsData( void ) { // publish pressure/occlusion data on interval if ( ++conductivityPublishTimerCounter >= getU32OverrideValue( &conductivityDataPublishInterval ) ) { CONDUCTIVITY_DATA_T data; data.p9Conductivity = getConductivityValue( P9_COND ); data.p18Conductivity = getConductivityValue( P18_COND ); conductivityPublishTimerCounter = 0; broadcastData( MSG_ID_FP_CONDUCTIVITY_DATA, COMM_BUFFER_OUT_CAN_FP_BROADCAST, (U08*)&data, sizeof( CONDUCTIVITY_DATA_T ) ); } } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testConductivitySensorDataPublishIntervalOverride function overrides the * conductivity sensor data publish interval. * @details \b Inputs: none * @details \b Outputs: conductivityDataPublishInterval * @param message Override message from Dialin which includes the value * that override valves states publish interval with (in ms) * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testConductivitySensorDataPublishIntervalOverride( MESSAGE_T *message ) { BOOL result = u32BroadcastIntervalOverride( message, &conductivityDataPublishInterval, TASK_PRIORITY_INTERVAL ); 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; } /**@}*/