Index: firmware/App/Drivers/FlowSensor.c =================================================================== diff -u --- firmware/App/Drivers/FlowSensor.c (revision 0) +++ firmware/App/Drivers/FlowSensor.c (revision 3edf8084a5028ee0d00a3fba496284e593e4254d) @@ -0,0 +1,187 @@ +/************************************************************************** +* +* 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 FlowSensor.c +* +* @author (last) Sean Nash +* @date (last) 21-Nov-2024 +* +* @author (original) Sean Nash +* @date (original) 21-Nov-2024 +* +***************************************************************************/ + +#include "AlarmMgmtRO.h" +#include "FlowSensor.h" +#include "FpgaRO.h" +#include "Messaging.h" +#include "PersistentAlarm.h" + +/** + * @addtogroup FlowSensor + * @{ + */ + +// ********** private definitions ********** + +#define FLOW_TEMPERATURE_DIVIDER 10.0F ///< Divider for converting flow readings to mL/min flow rates. + +// ********** private data ********** + +static OVERRIDE_F32_T currentFlowReadings[ NUM_OF_FLOW_SENSORS ]; ///< Current flow sensor pressure readings (overrideable). +static OVERRIDE_F32_T currentFlowTempReadings[ NUM_OF_FLOW_SENSORS ]; ///< Current flow sensor temperature readings (overrideable). + +// ********** private function prototypes ********** + +/*********************************************************************//** + * @brief + * The initFlowSensor function initializes the Flow Sensor unit. + * @details \b Inputs: none + * @details \b Outputs: Flow Sensor unit is initialized. + * @return none + *************************************************************************/ +void initFlowSensor( void ) +{ + FLOW_SENSORS_T sensor; + + // Initialize override structures for each pressure sensor + for ( sensor = FLOW_SENSOR_FIRST; sensor < NUM_OF_FLOW_SENSORS; sensor++ ) + { + currentFlowReadings[ sensor ].data = 0.0F; + currentFlowReadings[ sensor ].ovData = 0.0F; + currentFlowReadings[ sensor ].ovInitData = 0.0F; + currentFlowReadings[ sensor ].override = OVERRIDE_RESET; + + currentFlowTempReadings[ sensor ].data = 0.0F; + currentFlowTempReadings[ sensor ].ovData = 0.0F; + currentFlowTempReadings[ sensor ].ovInitData = 0.0F; + currentFlowTempReadings[ sensor ].override = OVERRIDE_RESET; + } +} + +/*********************************************************************//** + * @brief + * The readFlowSensors function gets the current flow rate reading + * for a all flow sensors from the FPGA. + * @note This function should be called periodically to maintain fresh + * sensor readings for all flow sensors. + * @details \b Inputs: FPGA + * @details \b Outputs: currentFlowReadings[], currentFlowTempReadings[] + * @return none + *************************************************************************/ +void readFlowSensors( void ) +{ + // Update and convert raw flow rates to mL/min + currentFlowReadings[ FLOW_SENSOR_RO_OUTLET ].data = (F32)( (S16)getFPGAFlowFMP() ); + //currentFlowReadings[ FLOW_SENSOR_WATER_INLET ].data = TBD; + + // Update and convert raw flow sensor temperatures to deg C + currentFlowTempReadings[ FLOW_SENSOR_RO_OUTLET ].data = (F32)( (S16)getFPGAFlowFMPTemp() ) / FLOW_TEMPERATURE_DIVIDER; + //currentFlowTempReadings[ FLOW_SENSOR_WATER_INLET ].data = TBD +} + +/*********************************************************************//** + * @brief + * The getFlowRate function gets the current pressure (in mmHg) for a given + * pressure sensor. + * @details \b Alarm: ALARM_ID_RO_SOFTWARE_FAULT if given flow sensor is invalid. + * @details \b Inputs: currentFlowReadings[] + * @details \b Outputs: none + * @param sensor ID of flow sensor to get flow rate for. + * @return The current flow rate (in mL/min) of the given flow sensor. + *************************************************************************/ +F32 getFlowRate( FLOW_SENSORS_T sensor ) +{ + F32 result = 0.0F; + + if ( sensor < NUM_OF_FLOW_SENSORS ) + { + result = currentFlowReadings[ sensor ].data; + if ( OVERRIDE_KEY == currentFlowReadings[ sensor ].override ) + { + result = currentFlowReadings[ sensor ].ovData; + } + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_RO_SOFTWARE_FAULT, SW_FAULT_ID_FLOW_SENSOR_INVALID_SENSOR1, (U32)sensor ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getFlowTemperature function gets the current flow sensor + * temperature (in deg C) for a given flow sensor. + * @details \b Alarm: ALARM_ID_RO_SOFTWARE_FAULT if given flow sensor is invalid. + * @details \b Inputs: currentFlowTempReadings + * @details \b Outputs: none + * @param sensor ID of flow sensor to get flow rate for. + * @return The current flow sensor temperature (in deg C) of the given flow sensor. + *************************************************************************/ +F32 getFlowTemperature( FLOW_SENSORS_T sensor ) +{ + F32 result = 0.0F; + + if ( sensor < NUM_OF_FLOW_SENSORS ) + { + result = currentFlowTempReadings[ sensor ].data; + if ( OVERRIDE_KEY == currentFlowTempReadings[ sensor ].override ) + { + result = currentFlowTempReadings[ sensor ].ovData; + } + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_RO_SOFTWARE_FAULT, SW_FAULT_ID_FLOW_SENSOR_INVALID_SENSOR2, (U32)sensor ) + } + + return result; +} + + +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + + +/*********************************************************************//** + * @brief + * The testFlowSensorReadingsOverride function overrides the value of + * the specified flow sensor with a given value. + * @details \b Inputs: none + * @details \b Outputs: currentFlowReadings[] + * @param message Override message from Dialin which includes a sensor + * ID and override value of the flow sensor. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testFlowSensorReadingsOverride( MESSAGE_T *message ) +{ + BOOL result = f32ArrayOverride( message, ¤tFlowReadings[0], NUM_OF_FLOW_SENSORS - 1 ); + + return result; +} + +/*********************************************************************//** + * @brief + * The testFlowSensorTemperatureReadingsOverride function overrides the + * value of the specified flow sensor temperature with a given value. + * @details \b Inputs: none + * @details \b Outputs: currentFlowTempReadings[] + * @param message Override message from Dialin which includes a sensor + * ID and override value of the flow sensor temperature. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testFlowSensorTemperatureReadingsOverride( MESSAGE_T *message ) +{ + BOOL result = f32ArrayOverride( message, ¤tFlowTempReadings[0], NUM_OF_FLOW_SENSORS - 1 ); + + return result; +} + +/**@}*/ Index: firmware/App/Drivers/FlowSensor.h =================================================================== diff -u --- firmware/App/Drivers/FlowSensor.h (revision 0) +++ firmware/App/Drivers/FlowSensor.h (revision 3edf8084a5028ee0d00a3fba496284e593e4254d) @@ -0,0 +1,55 @@ +/************************************************************************** +* +* 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 FlowSensor.h +* +* @author (last) Sean Nash +* @date (last) 21-Nov-2024 +* +* @author (original) Sean Nash +* @date (original) 21-Nov-2024 +* +***************************************************************************/ + +#ifndef __FLOW_SENSOR_H__ +#define __FLOW_SENSOR_H__ + +#include "ROCommon.h" + +/** + * @defgroup FlowSensor FlowSensor + * @brief Flow sensors driver unit. Reads the flow rates and temperatures + * from the various RO flow sensors. + * + * @addtogroup FlowSensor + * @{ + */ + +// ********** public definitions ********** + +/// Enumeration of flow sensors handled by this unit. +typedef enum FlowSensors +{ + FLOW_SENSOR_WATER_INLET = 0, ///< Water inlet flow sensor (FMS P7) + FLOW_SENSOR_FIRST = FLOW_SENSOR_WATER_INLET, ///< First flow + FLOW_SENSOR_RO_OUTLET, ///< RO outlet flow sensor (FMP P16) + NUM_OF_FLOW_SENSORS ///< Number of flow sensors +} FLOW_SENSORS_T; + +// ********** public function prototypes ********** + +void initFlowSensor( void ); +void readFlowSensors( void ); +F32 getFlowRate( FLOW_SENSORS_T sensor ); +F32 getFlowTemperature( FLOW_SENSORS_T sensor ); + +BOOL testFlowSensorReadingsOverride( MESSAGE_T *message ); +BOOL testFlowSensorTemperatureReadingsOverride( MESSAGE_T *message ); + +/**@}*/ + +#endif Index: firmware/App/Drivers/PressureSensor.c =================================================================== diff -u -rd4d21b42ee8bd292a6d9f7966fe37abe0271dfda -r3edf8084a5028ee0d00a3fba496284e593e4254d --- firmware/App/Drivers/PressureSensor.c (.../PressureSensor.c) (revision d4d21b42ee8bd292a6d9f7966fe37abe0271dfda) +++ firmware/App/Drivers/PressureSensor.c (.../PressureSensor.c) (revision 3edf8084a5028ee0d00a3fba496284e593e4254d) @@ -20,7 +20,6 @@ #include "Messaging.h" #include "PersistentAlarm.h" #include "PressureSensor.h" -#include "TemperatureSensors.h" /** * @addtogroup PressureSensor @@ -55,30 +54,30 @@ *************************************************************************/ void initPressureSensor( void ) { - U32 i; + PRESSURE_SENSORS_T sensor; // Initialize override structures for each pressure sensor - for ( i = (U32)PRESSURE_SENSOR_FIRST; i < (U32)NUM_OF_PRESSURE_SENSORS; i++ ) + for ( sensor = PRESSURE_SENSOR_FIRST; sensor < NUM_OF_PRESSURE_SENSORS; sensor++ ) { - currentPressureReadings[ i ].data = 0.0F; - currentPressureReadings[ i ].ovData = 0.0F; - currentPressureReadings[ i ].ovInitData = 0.0F; - currentPressureReadings[ i ].override = OVERRIDE_RESET; + currentPressureReadings[ sensor ].data = 0.0F; + currentPressureReadings[ sensor ].ovData = 0.0F; + currentPressureReadings[ sensor ].ovInitData = 0.0F; + currentPressureReadings[ sensor ].override = OVERRIDE_RESET; - currentPresTempReadings[ i ].data = 0.0F; - currentPresTempReadings[ i ].ovData = 0.0F; - currentPresTempReadings[ i ].ovInitData = 0.0F; - currentPresTempReadings[ i ].override = OVERRIDE_RESET; + currentPresTempReadings[ sensor ].data = 0.0F; + currentPresTempReadings[ sensor ].ovData = 0.0F; + currentPresTempReadings[ sensor ].ovInitData = 0.0F; + currentPresTempReadings[ sensor ].override = OVERRIDE_RESET; - lastPressureReadCounter[ i ].data = 0; - lastPressureReadCounter[ i ].ovData = 0; - lastPressureReadCounter[ i ].ovInitData = 0; - lastPressureReadCounter[ i ].override = OVERRIDE_RESET; + lastPressureReadCounter[ sensor ].data = 0; + lastPressureReadCounter[ sensor ].ovData = 0; + lastPressureReadCounter[ sensor ].ovInitData = 0; + lastPressureReadCounter[ sensor ].override = OVERRIDE_RESET; - lastPressureErrorCounter[ i ].data = 0; - lastPressureErrorCounter[ i ].ovData = 0; - lastPressureErrorCounter[ i ].ovInitData = 0; - lastPressureErrorCounter[ i ].override = OVERRIDE_RESET; + lastPressureErrorCounter[ sensor ].data = 0; + lastPressureErrorCounter[ sensor ].ovData = 0; + lastPressureErrorCounter[ sensor ].ovInitData = 0; + lastPressureErrorCounter[ sensor ].override = OVERRIDE_RESET; } // Initialize the FPGA persistent alarms @@ -222,7 +221,7 @@ } else { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_RO_SOFTWARE_FAULT, SW_FAULT_ID_PRESSURE_SENSOR_INVALID_SENSOR2, sensor ) + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_RO_SOFTWARE_FAULT, SW_FAULT_ID_PRESSURE_SENSOR_INVALID_SENSOR2, (U32)sensor ) } return result; Index: firmware/App/Monitors/Flow.c =================================================================== diff -u --- firmware/App/Monitors/Flow.c (revision 0) +++ firmware/App/Monitors/Flow.c (revision 3edf8084a5028ee0d00a3fba496284e593e4254d) @@ -0,0 +1,439 @@ +/************************************************************************** +* +* 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 Flow.c +* +* @author (last) Sean Nash +* @date (last) 21-Nov-2024 +* +* @author (original) Sean Nash +* @date (original) 21-Nov-2024 +* +***************************************************************************/ + +#include "AlarmMgmtRO.h" +#include "Flow.h" +#include "Messaging.h" +#include "PersistentAlarm.h" +#include "TaskPriority.h" + +/** + * @addtogroup Flow + * @{ + */ + +// ********** private definitions ********** + +#define FLOWS_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Interval (ms/task time) at which the flows data is published on the CAN bus. +#define DATA_PUBLISH_COUNTER_START_COUNT ( 5 ) ///< Data publish counter start count. +#define FLOW_SAMPLE_FILTER_MS ( 500 ) ///< Filter flow data for given time +#define FLOW_TEMP_SAMPLE_FILTER_MS ( 500 ) ///< Filter flow temperature data for given time +#define SIZE_OF_FLOW_ROLLING_AVG ( FLOW_SAMPLE_FILTER_MS / TASK_PRIORITY_INTERVAL ) ///< Filtered flow moving average sample count. +#define SIZE_OF_FLOW_TEMP_ROLLING_AVG ( FLOW_TEMP_SAMPLE_FILTER_MS / TASK_PRIORITY_INTERVAL ) ///< Filtered flow temprature moving average sample count. + +/// Defined states for the flow monitor state machine. +typedef enum FlowMonitor_States +{ + FLOW_INIT_STATE = 0, ///< Initialization state. + FLOW_CONTINUOUS_READ_STATE, ///< Continuous read flow sensors state. + NUM_OF_FLOW_STATES ///< Number of flow monitor states. +} FLOW_STATE_T; + +/// Filter flow readings record. +typedef struct +{ + F32 flowReadings[ SIZE_OF_FLOW_ROLLING_AVG ]; ///< Holds flow sample rolling average. + U32 flowReadingsIdx; ///< Index for next sample in rolling average array. + F32 flowReadingsTotal; ///< Rolling total - used to calc average. + U32 flowReadingsCount; ///< Number of samples in rolling average buffer +} FILTER_FLOW_READINGS_T; + +/// Filter flow temperature readings record. +typedef struct +{ + F32 flowTempReadings[ SIZE_OF_FLOW_TEMP_ROLLING_AVG ]; ///< Holds pressure temperature sample rolling average. + U32 flowTempReadingsIdx; ///< Index for next sample in rolling average array. + F32 flowTempReadingsTotal; ///< Rolling total - used to calc average. + U32 flowTempReadingsCount; ///< Number of samples in rolling average buffer +} FILTER_FLOW_TEMPERATURE_READINGS_T; + +// ********** private data ********** + +static OVERRIDE_F32_T filteredcurrentFlowReadings[ NUM_OF_FLOW_SENSORS ]; ///< filtered current flow sensor flow readings (overrideable). +static OVERRIDE_F32_T filteredcurrentFlowTempReadings[ NUM_OF_FLOW_SENSORS ]; ///< filtered current flow sensor temperature readings (overrideable). +//static RO_PRES_SENSORS_CAL_RECORD_T flowsCalRecord; ///< Flows calibration record. + +static FILTER_FLOW_READINGS_T filteredFlowReadings[NUM_OF_FLOW_SENSORS]; ///< Filtered flow reading for flow sensors. +static FILTER_FLOW_TEMPERATURE_READINGS_T filteredFlowTempReadings[NUM_OF_FLOW_SENSORS]; ///< Filtered temperature reading for flow sensors. +static FLOW_STATE_T flowsState; ///< current state of flow monitor state machine. +static U32 flowsDataPublicationTimerCounter; ///< used to schedule flow data publication to CAN bus. +static OVERRIDE_U32_T flowsDataPublishInterval; ///< Flow data publish interval. + +// ********** private function prototypes ********** + +static void filterFlowSensors( void ); +static void filterFlowSensorReadings( void ); +static void filterFlowSensorTemperatureReadings( void ); +//static F32 getCalibrationAppliedFlow( U08 sensorId, F32 flow ); +static FLOW_STATE_T handleFlowsInitState( void ); +static FLOW_STATE_T handleFlowsContReadState( void ); +static void publishFlowsData( void ); + +/*********************************************************************//** + * @brief + * The initFlow function initializes the Flow Monitor unit. + * @details \b Inputs: none + * @details \b Outputs: Flow monitor unit is initialized. + * @return none + *************************************************************************/ +void initFlow( void ) +{ + FLOW_SENSORS_T sensor; + + flowsState = FLOW_INIT_STATE; + flowsDataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; + + // Initialize flow sensors driver + initFlowSensor(); + + // Initialize override structures for each flow sensor + for ( sensor = FLOW_SENSOR_FIRST; sensor < NUM_OF_FLOW_SENSORS; sensor++ ) + { + filteredcurrentFlowReadings[ sensor ].data = 0.0F; + filteredcurrentFlowReadings[ sensor ].ovData = 0.0F; + filteredcurrentFlowReadings[ sensor ].ovInitData = 0.0F; + filteredcurrentFlowReadings[ sensor ].override = OVERRIDE_RESET; + + filteredcurrentFlowTempReadings[ sensor ].data = 0.0F; + filteredcurrentFlowTempReadings[ sensor ].ovData = 0.0F; + filteredcurrentFlowTempReadings[ sensor ].ovInitData = 0.0F; + filteredcurrentFlowTempReadings[ sensor ].override = OVERRIDE_RESET; + + filteredFlowReadings[ sensor ].flowReadingsCount = 0; + filteredFlowReadings[ sensor ].flowReadingsIdx = 0; + filteredFlowReadings[ sensor ].flowReadingsTotal = 0.0F; + + filteredFlowTempReadings[ sensor ].flowTempReadingsCount = 0; + filteredFlowTempReadings[ sensor ].flowTempReadingsIdx = 0; + filteredFlowTempReadings[ sensor ].flowTempReadingsTotal = 0.0F; + } + + flowsDataPublishInterval.data = FLOWS_DATA_PUB_INTERVAL; + flowsDataPublishInterval.ovData = FLOWS_DATA_PUB_INTERVAL; + flowsDataPublishInterval.ovInitData = 0; + flowsDataPublishInterval.override = OVERRIDE_RESET; +} + +/*********************************************************************//** + * @brief + * The filterFlowSensors function gets averages the raw flow and flow + * temperature readings. + * @details \b Inputs: flow and temperature readings from FPGA + * @details \b Outputs: filteredFlowReadings[], filteredFlowTempReadings[] + * @return none + *************************************************************************/ +static void filterFlowSensors( void ) +{ + //Filter pressure sensor reading + filterFlowSensorReadings(); + + //Filter pressure sensor temperature reading + filterFlowSensorTemperatureReadings(); +} + +/*********************************************************************//** + * @brief + * The getFilteredFlow function gets the filtered current flow (in mL/min) + * for a given flow sensor. + * @details \b Alarm: ALARM_ID_RO_SOFTWARE_FAULT if given sensor is invalid. + * @details \b Inputs: filteredcurrentFlowReadings[] + * @details \b Outputs: none + * @param sensor ID of flow sensor to get filtered flow reading for. + * @return The filtered current flow (in mL/min) of the given flow sensor. + *************************************************************************/ +F32 getFilteredFlow( FLOW_SENSORS_T sensor ) +{ + F32 result = 0.0F; + + if ( sensor < NUM_OF_FLOW_SENSORS ) + { + result = filteredcurrentFlowReadings[ sensor ].data; + if ( OVERRIDE_KEY == filteredcurrentFlowReadings[ sensor ].override ) + { + result = filteredcurrentFlowReadings[ sensor ].ovData; + } + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_RO_SOFTWARE_FAULT, SW_FAULT_ID_FLOW_SENSOR_INVALID_SENSOR3, (U32)sensor ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getFilteredFlowSensorTemperature function gets the filtered current + * flow sensor temperature (in deg C) for a given flow sensor. + * @details \b Alarm: ALARM_ID_RO_SOFTWARE_FAULT if given sensor is invalid. + * @details \b Inputs: currentFlowTempReadings + * @details \b Outputs: none + * @param sensor ID of flow sensor to get temperature reading for. + * @return The filtered current flow sensor temperature (in deg C) of the given flow sensor. + *************************************************************************/ +F32 getFilteredFlowSensorTemperature( FLOW_SENSORS_T sensor ) +{ + F32 result = 0.0F; + + if ( sensor < NUM_OF_FLOW_SENSORS ) + { + result = filteredcurrentFlowTempReadings[ sensor ].data; + if ( OVERRIDE_KEY == filteredcurrentFlowTempReadings[ sensor ].override ) + { + result = filteredcurrentFlowTempReadings[ sensor ].ovData; + } + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_RO_SOFTWARE_FAULT, SW_FAULT_ID_FLOW_SENSOR_INVALID_SENSOR4, (U32)sensor ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The execFlowMonitor function executes the flow monitor state machine + * and publishes flow data. + * @note This function should be called periodically to maintain monitoring + * of the flow sensors. + * @details \b Inputs: flowsState + * @details \b Outputs: flowsState + * @details \b Alarm: ALARM_ID_RO_SOFTWARE_FAULT if in invalid flow state + * @return none + *************************************************************************/ +void execFlowMonitor( void ) +{ + // state machine + switch ( flowsState ) + { + case FLOW_INIT_STATE: + flowsState = handleFlowsInitState(); + break; + + case FLOW_CONTINUOUS_READ_STATE: + flowsState = handleFlowsContReadState(); + break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_RO_SOFTWARE_FAULT, SW_FAULT_ID_FLOW_INVALID_EXEC_STATE, (U32)flowsState ) + flowsState = FLOW_INIT_STATE; + break; + } + + // publish flow data on interval + publishFlowsData(); +} + +/*********************************************************************//** + * @brief + * The filterFlowSensorReadings function filters the flow rates for + * defined interval to get average flow rates. + * @details \b Inputs: filteredFlowReadings[] + * @details \b Outputs: filteredFlowReadings[], filteredcurrentFlowReadings[] + * @return none + *************************************************************************/ +static void filterFlowSensorReadings( void ) +{ + FLOW_SENSORS_T sensor; + + for ( sensor = FLOW_SENSOR_FIRST; sensor < NUM_OF_FLOW_SENSORS; sensor++ ) + { + F32 rawFlow = getFlowRate( sensor ); + + // TODO - calibrate + + if ( filteredFlowReadings[sensor].flowReadingsCount >= SIZE_OF_FLOW_ROLLING_AVG ) + { + filteredFlowReadings[sensor].flowReadingsTotal -= filteredFlowReadings[sensor].flowReadings[ filteredFlowReadings[sensor].flowReadingsIdx ]; + } + filteredFlowReadings[sensor].flowReadings[ filteredFlowReadings[sensor].flowReadingsIdx ] = rawFlow; + filteredFlowReadings[sensor].flowReadingsTotal += rawFlow; + filteredFlowReadings[sensor].flowReadingsIdx = INC_WRAP( filteredFlowReadings[sensor].flowReadingsIdx, 0, SIZE_OF_FLOW_ROLLING_AVG - 1 ); + filteredFlowReadings[sensor].flowReadingsCount = INC_CAP( filteredFlowReadings[sensor].flowReadingsCount, SIZE_OF_FLOW_ROLLING_AVG ); + filteredcurrentFlowReadings[sensor].data = filteredFlowReadings[sensor].flowReadingsTotal / (F32)filteredFlowReadings[sensor].flowReadingsCount; + } +} + +/*********************************************************************//** + * @brief + * The filterPressureSensorTemperatureReadings function filters the flow sensor + * temperature for defined interval to get moving average temperature reading. + * @details \b Inputs: filteredFlowTempReadings[] + * @details \b Outputs: filteredFlowTempReadings[], filteredcurrentFlowTempReadings[] + * @return none + *************************************************************************/ +static void filterFlowSensorTemperatureReadings( void ) +{ + FLOW_SENSORS_T sensor; + + for ( sensor = FLOW_SENSOR_FIRST; sensor < NUM_OF_FLOW_SENSORS; sensor++ ) + { + F32 flowTemperature = getFlowTemperature( sensor ); + + // TODO - calibrate? + + if ( filteredFlowTempReadings[sensor].flowTempReadingsCount >= SIZE_OF_FLOW_TEMP_ROLLING_AVG ) + { + filteredFlowTempReadings[sensor].flowTempReadingsTotal -= filteredFlowTempReadings[sensor].flowTempReadings[ filteredFlowTempReadings[sensor].flowTempReadingsIdx ]; + } + filteredFlowTempReadings[sensor].flowTempReadings[ filteredFlowTempReadings[sensor].flowTempReadingsIdx ] = flowTemperature; + filteredFlowTempReadings[sensor].flowTempReadingsTotal += flowTemperature; + filteredFlowTempReadings[sensor].flowTempReadingsIdx = INC_WRAP( filteredFlowTempReadings[sensor].flowTempReadingsIdx, 0, SIZE_OF_FLOW_TEMP_ROLLING_AVG - 1 ); + filteredFlowTempReadings[sensor].flowTempReadingsCount = INC_CAP( filteredFlowTempReadings[sensor].flowTempReadingsCount, SIZE_OF_FLOW_TEMP_ROLLING_AVG ); + filteredcurrentFlowTempReadings[sensor].data = filteredFlowTempReadings[sensor].flowTempReadingsTotal / (F32)filteredFlowTempReadings[sensor].flowTempReadingsCount; + } +} + +/*********************************************************************//** + * @brief + * The getCalibrationAppliedFlow function applies the calibration values + * to a given flow sensor and filtered flow rate and returns a calibrated flow. + * @details \b Inputs: flowsCalRecord + * @details \b Outputs: none + * @param sensorId the ID of the flow sensor + * @param flow the flow rate before applying calibration to it + * @return calibration applied flow rate + *************************************************************************/ +//static F32 getCalibrationAppliedFlow( U08 sensorId, F32 pressure ) +//{ +// F32 calFlow = pow( pressure, 4 ) * flowsCalRecord.flowSensors[ (FLOW_SENSORS_T)sensorId ].fourthOrderCoeff + +// pow( pressure, 3 ) * flowsCalRecord.flowSensors[ (FLOW_SENSORS_T)sensorId ].thirdOrderCoeff + +// pow( pressure, 2 ) * flowsCalRecord.flowSensors[ (FLOW_SENSORS_T)sensorId ].secondOrderCoeff + +// pressure * flowsCalRecord.flowSensors[ (FLOW_SENSORS_T)sensorId ].gain + +// flowsCalRecord.flowSensors[ (FLOW_SENSORS_T)sensorId ].offset; +// return calFlow; +//} + +/*********************************************************************//** + * @brief + * The handleFlowsInitState function handles the flows initialize state + * of the flow monitor state machine. + * @details \b Inputs: none + * @details \b Outputs: none + * @return next state + *************************************************************************/ +static FLOW_STATE_T handleFlowsInitState( void ) +{ + return FLOW_CONTINUOUS_READ_STATE; +} + +/*********************************************************************//** + * @brief + * The handleFlowsContReadState function handles the continuous read state + * of the flows monitor state machine. Raw readings are read from driver + * and then filtered via moving average and calibrated. + * @details \b Inputs: raw readings from flow sensor driver + * @details \b Outputs: flow sensors are sampled, filtered and calibrated. + * @return next state + *************************************************************************/ +static FLOW_STATE_T handleFlowsContReadState( void ) +{ + FLOW_STATE_T result = FLOW_CONTINUOUS_READ_STATE; + + // Get raw flow readings + readFlowSensors(); + // filter raw flow readings + filterFlowSensors(); + + return result; +} + +/*********************************************************************//** + * @brief + * The publishFlowsData function publishes RO flow data at a set interval. + * @details \b Inputs: flowsDataPublicationTimerCounter + * @details \b Outputs: flowsDataPublicationTimerCounter + * @details \b Message \b Sent: MSG_ID_RO_FLOW_DATA to publish flow data. + * @return none + *************************************************************************/ +static void publishFlowsData( void ) +{ + // publish pressure/occlusion data on interval + if ( ++flowsDataPublicationTimerCounter >= getU32OverrideValue( &flowsDataPublishInterval ) ) + { + FLOW_TEMP_DATA_T data; + + data.FlowFMS = getFilteredFlow( FLOW_SENSOR_WATER_INLET ); + data.FlowFMP = getFilteredFlow( FLOW_SENSOR_RO_OUTLET ); + + data.TempFMS = getFilteredFlowSensorTemperature( FLOW_SENSOR_WATER_INLET ); + data.TempFMP = getFilteredFlowSensorTemperature( FLOW_SENSOR_RO_OUTLET ); + + broadcastData( MSG_ID_RO_FLOW_DATA, COMM_BUFFER_OUT_CAN_RO_BROADCAST, (U08*)&data, sizeof( FLOW_TEMP_DATA_T ) ); + flowsDataPublicationTimerCounter = 0; + } +} + + +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + + +/*********************************************************************//** + * @brief + * The testFlowSensorDataPublishIntervalOverride function overrides the + * flow sensor data publish interval. + * @details \b Inputs: none + * @details \b Outputs: flowsDataPublishInterval + * @param message Override message from Dialin which includes the value + * that override flow data publish interval with (in ms) + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testFlowSensorDataPublishIntervalOverride( MESSAGE_T *message ) +{ + BOOL result = u32BroadcastIntervalOverride( message, &flowsDataPublishInterval, TASK_PRIORITY_INTERVAL ); + + return result; +} + +/*********************************************************************//** + * @brief + * The testFlowSensorFilteredReadingsOverride function overrides the + * filtered value of the specified flow sensor with a given value. + * @details \b Inputs: none + * @details \b Outputs: filteredcurrentFlowReadings[] + * @param message Override message from Dialin which includes a sensor + * ID and override value of the flow rate for that sensor. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +//BOOL testFlowSensorFilteredReadingsOverride( MESSAGE_T *message ) +//{ +// BOOL result = f32ArrayOverride( message, &filteredcurrentFlowReadings[0], NUM_OF_FLOW_SENSORS - 1 ); +// +// return result; +//} + +/*********************************************************************//** + * @brief + * The testFlowSensorFilteredTemperatureReadingsOverride function overrides the + * value of the specified flow sensor filtered temperature with a given value. + * @details \b Inputs: none + * @details \b Outputs: filteredcurrentFlowTempReadings[] + * @param message Override message from Dialin which includes a sensor + * ID and override value of the flow sensor temperature. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +//BOOL testFlowSensorFilteredTemperatureReadingsOverride( MESSAGE_T *message ) +//{ +// BOOL result = f32ArrayOverride( message, &filteredcurrentFlowTempReadings[0], NUM_OF_FLOW_SENSORS - 1 ); +// +// return result; +//} + +/**@}*/ Index: firmware/App/Monitors/Flow.h =================================================================== diff -u --- firmware/App/Monitors/Flow.h (revision 0) +++ firmware/App/Monitors/Flow.h (revision 3edf8084a5028ee0d00a3fba496284e593e4254d) @@ -0,0 +1,58 @@ +/************************************************************************** +* +* 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 Flow.h +* +* @author (last) Sean Nash +* @date (last) 21-Nov-2024 +* +* @author (original) Sean Nash +* @date (original) 21-Nov-2024 +* +***************************************************************************/ + +#ifndef __FLOW_H__ +#define __FLOW_H__ + +#include "ROCommon.h" +#include "FlowSensor.h" + +/** + * @defgroup Flow Flow + * @brief Flow sensors monitor unit. Monitors the various RO flow + * sensors. + * + * @addtogroup Flow + * @{ + */ + +// ********** public definitions ********** + +/// Flow data record. +typedef struct +{ + F32 FlowFMS; ///< Flow rate at water inlet (P7 FMS) + F32 FlowFMP; ///< Flow rate at RO filter outlet (P16 FMP) + F32 TempFMS; ///< Temperature of fluid (P7 FMS) + F32 TempFMP; ///< Temperature of fluid (P16 FMP) +} FLOW_TEMP_DATA_T; + +// ********** public function prototypes ********** + +void initFlow( void ); +void execFlowMonitor( void ); + +F32 getFilteredFlow( FLOW_SENSORS_T sensor ); +F32 getFilteredFlowSensorTemperature( FLOW_SENSORS_T sensor ); + +BOOL testFlowSensorDataPublishIntervalOverride( MESSAGE_T *message ); +//BOOL testFlowSensorFilteredReadingsOverride( MESSAGE_T *message ); +//BOOL testFlowSensorFilteredTemperatureReadingsOverride( MESSAGE_T *message ); + +/**@}*/ + +#endif Index: firmware/App/Monitors/Pressure.c =================================================================== diff -u -rc9aa3971be05f25a7b0d7124e57cc60617c90ad7 -r3edf8084a5028ee0d00a3fba496284e593e4254d --- firmware/App/Monitors/Pressure.c (.../Pressure.c) (revision c9aa3971be05f25a7b0d7124e57cc60617c90ad7) +++ firmware/App/Monitors/Pressure.c (.../Pressure.c) (revision 3edf8084a5028ee0d00a3fba496284e593e4254d) @@ -79,7 +79,7 @@ static OVERRIDE_F32_T filteredcurrentPressureReadings[ NUM_OF_PRESSURE_SENSORS ]; ///< filtered current pressure sensor pressure readings (overrideable). static OVERRIDE_F32_T filteredcurrentPresTempReadings[ NUM_OF_PRESSURE_SENSORS ]; ///< filtered current pressure sensor temperature readings (overrideable). -//static DD_PRES_SENSORS_CAL_RECORD_T pressuresCalRecord; ///< Pressures calibration record. +//static RO_PRES_SENSORS_CAL_RECORD_T pressuresCalRecord; ///< Pressures calibration record. static FILTER_PRESSURE_READINGS_T filteredPressureReadings[NUM_OF_PRESSURE_SENSORS]; ///< Filtered pressure reading for pressure sensors. static FILTER_PRESSURE_TEMPERATURE_READINGS_T filteredPressureTempReadings[NUM_OF_PRESSURE_SENSORS]; ///< Filtered pressure reading for pressure sensors. @@ -191,7 +191,7 @@ } else { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_RO_SOFTWARE_FAULT, SW_FAULT_ID_PRESSURE_SENSOR_INVALID_SENSOR5, sensor ) + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_RO_SOFTWARE_FAULT, SW_FAULT_ID_PRESSURE_SENSOR_INVALID_SENSOR5, (U32)sensor ) } return result; @@ -221,7 +221,7 @@ } else { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_RO_SOFTWARE_FAULT, SW_FAULT_ID_PRESSURE_SENSOR_INVALID_SENSOR6, sensor ) + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_RO_SOFTWARE_FAULT, SW_FAULT_ID_PRESSURE_SENSOR_INVALID_SENSOR6, (U32)sensor ) } return result; @@ -513,7 +513,7 @@ * @details \b Inputs: none * @details \b Outputs: pressuresDataPublishInterval * @param message Override message from Dialin which includes the value - * that override valves states publish interval with (in ms) + * that override pressure data publish interval with (in ms) * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testPressureSensorDataPublishIntervalOverride( MESSAGE_T *message ) @@ -545,8 +545,8 @@ * The testPressureSensorFilteredTemperatureReadingsOverride function overrides the * value of the specified pressure sensor filtered temperature with a given value. * @details \b Inputs: none - * @details \b Outputs: currentPresTempReadings[] - * @param message Override message from Dialin which includes an sensor + * @details \b Outputs: filteredcurrentPresTempReadings[] + * @param message Override message from Dialin which includes a sensor * ID and override value of the pressure sensor temperature. * @return TRUE if override successful, FALSE if not *************************************************************************/ Index: firmware/App/Services/AlarmMgmtSWFaults.h =================================================================== diff -u -ra3988128df0950e1f03dcb4a5aa53336d8fb3a6f -r3edf8084a5028ee0d00a3fba496284e593e4254d --- firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision a3988128df0950e1f03dcb4a5aa53336d8fb3a6f) +++ firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision 3edf8084a5028ee0d00a3fba496284e593e4254d) @@ -107,6 +107,11 @@ SW_FAULT_ID_PRESSURE_SENSOR_INVALID_SENSOR5 = 90, SW_FAULT_ID_PRESSURE_SENSOR_INVALID_SENSOR6 = 91, SW_FAULT_ID_PRESSURE_INVALID_EXEC_STATE = 92, + SW_FAULT_ID_FLOW_SENSOR_INVALID_SENSOR1 = 93, + SW_FAULT_ID_FLOW_SENSOR_INVALID_SENSOR2 = 94, + SW_FAULT_ID_FLOW_SENSOR_INVALID_SENSOR3 = 95, + SW_FAULT_ID_FLOW_SENSOR_INVALID_SENSOR4 = 96, + SW_FAULT_ID_FLOW_INVALID_EXEC_STATE = 97, NUM_OF_SW_FAULT_IDS } SW_FAULT_ID_T; Index: firmware/App/Services/FpgaRO.c =================================================================== diff -u -rd4d21b42ee8bd292a6d9f7966fe37abe0271dfda -r3edf8084a5028ee0d00a3fba496284e593e4254d --- firmware/App/Services/FpgaRO.c (.../FpgaRO.c) (revision d4d21b42ee8bd292a6d9f7966fe37abe0271dfda) +++ firmware/App/Services/FpgaRO.c (.../FpgaRO.c) (revision 3edf8084a5028ee0d00a3fba496284e593e4254d) @@ -116,11 +116,11 @@ U16 conductSensor2Temp; ///< Reg 352. Conductivity sensor 2 temperature. U08 conductSensor2ReadCount; ///< Reg 354. Conductivity sensor 2 read counter. U08 conductSensor2ErrorCount; ///< Reg 355. Conductivity sensor 2 error counter. - U16 flowRateCountFmp; ///< Reg 356. FMP flow sensor pulse counter. - U16 flowTemp; ///< Reg 358. FMP flow sensor temperature. + U16 flowRateFmp; ///< Reg 356. FMP flow sensor rate. + U16 flowTempFmp; ///< Reg 358. FMP flow sensor temperature. U16 roPumpTachCount; ///< Reg 360. ROP tachometer counter. U16 dsPumpTachCount; ///< Reg 362. DSP tachometer counter. - U16 flowIntTemp; ///< Reg 364. FMP flow sensor internal temperature. + U16 flowIntTempFmp; ///< Reg 364. FMP flow sensor internal temperature. U08 valveControlReadback; ///< Reg 366. Valve control bits read back. U08 valvePWMEnableReadback; ///< Reg 367. Valve PWM enable read back. U16 roPumpPWMReadback; ///< Reg 368. ROP PWM read back. @@ -667,4 +667,29 @@ return fpgaSensorReadings.levelSwitch; } +/*********************************************************************//** + * @brief + * The getFPGAFlowFMP function gets the FMP flow rate (in mL/min). + * @details \b Inputs: fpgaSensorReadings.flowRateFmp + * @details \b Outputs: none + * @return FMP flow rate (in mL/min) + *************************************************************************/ +U16 getFPGAFlowFMP( void ) +{ + return fpgaSensorReadings.flowRateFmp; +} + +/*********************************************************************//** + * @brief + * The getFPGAFlowFMPTemp function gets the FMP flow sensor temperature, the + * temperature of the fluid flowing through the sensor. + * @details \b Inputs: fpgaSensorReadings.flowTempFmp + * @details \b Outputs: none + * @return FMP fluid temperature + *************************************************************************/ +U16 getFPGAFlowFMPTemp( void ) +{ + return fpgaSensorReadings.flowTempFmp; +} + /**@}*/ Index: firmware/App/Services/FpgaRO.h =================================================================== diff -u -rd4d21b42ee8bd292a6d9f7966fe37abe0271dfda -r3edf8084a5028ee0d00a3fba496284e593e4254d --- firmware/App/Services/FpgaRO.h (.../FpgaRO.h) (revision d4d21b42ee8bd292a6d9f7966fe37abe0271dfda) +++ firmware/App/Services/FpgaRO.h (.../FpgaRO.h) (revision 3edf8084a5028ee0d00a3fba496284e593e4254d) @@ -75,6 +75,11 @@ U08 getFPGAFloaterState( void ); +U16 getFPGAFlowFMP( void ); +U16 getFPGAFlowFMPTemp( void ); +//U16 getFPGAFlowFMS( void ); +//U16 getFPGAFlowFMSTemp( void ); + /**@}*/ #endif Index: firmware/App/Services/Messaging.c =================================================================== diff -u -rc9aa3971be05f25a7b0d7124e57cc60617c90ad7 -r3edf8084a5028ee0d00a3fba496284e593e4254d --- firmware/App/Services/Messaging.c (.../Messaging.c) (revision c9aa3971be05f25a7b0d7124e57cc60617c90ad7) +++ firmware/App/Services/Messaging.c (.../Messaging.c) (revision 3edf8084a5028ee0d00a3fba496284e593e4254d) @@ -3,12 +3,12 @@ #include "BoostPump.h" #include "Compatible.h" +#include "Flow.h" #include "Level.h" #include "Messaging.h" #include "OperationModes.h" #include "PAL.h" #include "Pressure.h" -//#include "PressureSensor.h" #include "ROPump.h" #include "SystemCommRO.h" #include "Utilities.h" @@ -71,7 +71,10 @@ MSG_ID_RO_PRESSURE_PUBLISH_INTERVAL_OVERRIDE_REQUEST, MSG_ID_RO_DEBUG_EVENT, MSG_ID_RO_LEVEL_PUBLISH_INTERVAL_OVERRIDE_REQUEST, - MSG_ID_RO_LEVEL_OVERRIDE_REQUEST + MSG_ID_RO_LEVEL_OVERRIDE_REQUEST, + MSG_ID_RO_FLOWS_PUBLISH_INTERVAL_OVERRIDE_REQUEST, + MSG_ID_RO_FLOW_RATE_OVERRIDE_REQUEST, + MSG_ID_RO_FLOW_TEMP_OVERRIDE_REQUEST }; /// Message handling function table @@ -93,7 +96,10 @@ &testPressureSensorDataPublishIntervalOverride, &handleUnhandledMsg, &testLevelsDataPublishIntervalOverride, - &testLevelStateOverride + &testLevelStateOverride, + &testFlowSensorDataPublishIntervalOverride, + &testFlowSensorReadingsOverride, + &testFlowSensorTemperatureReadingsOverride }; #define NUM_OF_FUNCTION_HANDLERS (sizeof(MSG_FUNCTION_HANDLERS) / sizeof(MsgFuncPtr))