Index: firmware/App/Controllers/TemperatureSensors.c =================================================================== diff -u -r08eb8944c4db804b373cf37a78a761b01f00e649 -r3377c195bbbae77b4a551d87f78bcfa5c7fd6213 --- firmware/App/Controllers/TemperatureSensors.c (.../TemperatureSensors.c) (revision 08eb8944c4db804b373cf37a78a761b01f00e649) +++ firmware/App/Controllers/TemperatureSensors.c (.../TemperatureSensors.c) (revision 3377c195bbbae77b4a551d87f78bcfa5c7fd6213) @@ -8,7 +8,7 @@ * @file TemperatureSensors.c * * @author (last) Dara Navaei -* @date (last) 13-Jun-2023 +* @date (last) 12-Jul-2023 * * @author (original) Dara Navaei * @date (original) 08-Apr-2020 @@ -17,6 +17,7 @@ #include // For temperature calculation #include // For memset() +#include "FlowSensors.h" #include "FPGA.h" #include "MessageSupport.h" #include "NVDataMgmt.h" @@ -95,9 +96,11 @@ #define BARO_SENSOR_REFERENCE_TEMP_C 2000 ///< Barometric sensor reference temperature in C. #define BARO_SENSOR_WAIT_FOR_COEFF_TIME_OUT_MS ( 20 * MS_PER_SECOND ) ///< Barometric sensor wait for coefficients timeout in milliseconds. -#define TDI_TRO_TEMP_SENSORS_MAX_DEVIATION_C 15.0F //1.0F TODO temporary change ///< Dialysate temperature sensors maximum allowed deviation in C. +#define TDI_TRO_TEMP_SENSORS_MAX_DEVIATION_C 3.0F ///< Dialysate temperature sensors maximum allowed deviation in C. #define DIALYSATE_TEMP_SNSRS_OUT_OF_RANGE_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Dialysate temperature sensors drift timeout in milliseconds. -#define TDI_TRO_TEMP_SENSORS_MAX_DEVIATION_IN_HEAT_DIS_C 15.0F // 3.0F TODO temporary change ///< Dialysate temperature sensors maximum allowed deviation in heat disinfect in C. +#define TDI_TRO_TEMP_SENSORS_MAX_DEVIATION_IN_HEAT_DIS_C 5.0F ///< Dialysate temperature sensors maximum allowed deviation in heat disinfect in C. +#define DIAL_TEMP_MOVING_AVG_NUM_OF_SAMPLES 30 ///< Dialysate temperature sensors moving average number of samples. +#define TDI_TRO_DATA_COLLECTION_TIME_MS ( 1 * MS_PER_SECOND ) ///< Dialysate temperature sensors data collection time in milliseconds. /// Temperature sensor exec states. typedef enum tempSensors_Exec_States @@ -107,6 +110,15 @@ NUM_OF_TEMPSENSORS_EXEC_STATES, ///< Total number of exec states } TEMPSENSORS_EXEC_STATES_T; +/// Dialysate temperature sensors enums +typedef enum Dial_Temps_Sensors +{ + DIAL_TEMP_TRO = 0, ///< Dialysate temperature TRo. + DIAL_TEMP_FIRST = DIAL_TEMP_TRO, ///< Dialysate temperature first. + DIAL_TEMP_TDI, ///< Dialysate temperature TDi. + NUM_OF_DIAL_TEMPS ///< Number of Dialysate temperature sensors. +} DIAL_TEMPERATURE_SENSORS_T; + /// Temperature sensor struct. typedef struct { @@ -147,6 +159,17 @@ U16 crc; ///< Barometric sensor CRC of the coefficients. } BARO_SENSORS_COEFFS_T; +/// Dialysate temperature moving average structure +typedef struct +{ + BOOL dialTempColHasTimerBeenSet; ///< Dialysate temperature has data collection timer started boolean flag. + U32 dialTempDataColStartTimeMS; ///< Dialysate temperature data collection start time in milliseconds. + F32 dialTempRunningSumC; ///< Dialysate temperature running sum in C. + F32 dialTempAvgC; ///< Dialysate temperature average in C. + F32 dialTempSamplesC[ DIAL_TEMP_MOVING_AVG_NUM_OF_SAMPLES ]; ///< Dialysate temperature samples array in C. + U32 dialTempSamplesNextIndex; ///< Dialysate temperature sample next index number. +} DIAL_TEMP_MOVING_AVG_DATA_T; + // ********** private data ********** static TEMPSENSORS_EXEC_STATES_T tempSensorsExecState; ///< TemperatureSensor exec state. @@ -158,6 +181,7 @@ static OVERRIDE_U32_T tempSensorsPublishInterval = { TEMP_SENSORS_DATA_PUBLISH_INTERVAL, TEMP_SENSORS_DATA_PUBLISH_INTERVAL, 0, 0 }; ///< Temperature sensors publish time interval override. static DG_TEMP_SENSORS_CAL_RECORD_T tempSensorCalRecord; ///< Temperature sensors calibration record. +static DIAL_TEMP_MOVING_AVG_DATA_T dialTempMovingAvgData[ NUM_OF_DIAL_TEMPS ]; ///< Dialysate temperature moving average data. static const F32 POSITIVE_TC_EXP_A0 = 0.118597600000E0; ///< K TC positive temperature exponent coefficient A0. static const F32 POSITIVE_TC_EXP_A1 = -0.118343200000E-3; ///< K TC positive temperature exponent coefficient A1. static const F32 POSITIVE_TC_EXP_A2 = 0.126968600000E3; ///< K TC positive temperature exponent coefficient A2. @@ -195,21 +219,23 @@ static void processADCRead( U32 sensorIndex, S32 adc ); static void publishTemperatureSensorsData( void ); static void monitorTemperatureSenors( void ); -static void checkBaroSensorCRC( void ); static void adjustTemperatureSensorsRefResistance( void ); +static void checkBaroSensorCRC( void ); +static void processDialTemperatureData( void ); /*********************************************************************//** * @brief * The initTemperatureSensors function initializes the module. * @details Inputs: none * @details Outputs: tempSensorsSelfTestState, tempSensorsExecState, * elapsedTime, internalHeatersConversionTimer, dataPublicationTimerCounter, - * tempSensors, baroConvConsts + * tempSensors, baroConvConsts, dialTempMovingAvgData * @return none *************************************************************************/ void initTemperatureSensors( void ) { U08 i; + DIAL_TEMPERATURE_SENSORS_T j; tempSensorsExecState = TEMPSENSORS_EXEC_STATE_START; elapsedTime = 0; @@ -236,6 +262,17 @@ // Initialize the barometric sensor's temperature conversion constants memset( &baroConvConsts, 0x0, sizeof( BARO_SENSOR_CONSTS_T ) ); + for ( j = DIAL_TEMP_FIRST; j < NUM_OF_DIAL_TEMPS; j++ ) + { + dialTempMovingAvgData[ j ].dialTempAvgC = 0.0F; + dialTempMovingAvgData[ j ].dialTempColHasTimerBeenSet = FALSE; + dialTempMovingAvgData[ j ].dialTempRunningSumC = 0.0F; + dialTempMovingAvgData[ j ].dialTempSamplesNextIndex = 0; + dialTempMovingAvgData[ j ].dialTempDataColStartTimeMS = getMSTimerCount(); + + memset( dialTempMovingAvgData[ j ].dialTempSamplesC, 0.0F, sizeof( F32 ) * DIAL_TEMP_MOVING_AVG_NUM_OF_SAMPLES ); + } + // Initialize TPi, THd, and TPo constants tempSensors[ TEMPSENSORS_INLET_PRIMARY_HEATER ].gain = PRIMARY_HEATER_EXT_TEMP_SENSORS_GAIN; tempSensors[ TEMPSENSORS_INLET_PRIMARY_HEATER ].refResistance = PRIMARY_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE; @@ -396,6 +433,9 @@ // Monitor the temperature values monitorTemperatureSenors(); + // Process the moving average of the dialysate temperature sensors (TDi and TRo) + processDialTemperatureData(); + // Check the TDi/TRo drift checkDialysateTemperatureSensors(); @@ -578,13 +618,16 @@ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_TEMPERATURE_SENSORS_ALARM ) != SW_CONFIG_ENABLE_VALUE ) #endif { - F32 TDi = getTemperatureValue( TEMPSENSORS_INLET_DIALYSATE ); - F32 TRo = getTemperatureValue( TEMPSENSORS_OUTLET_REDUNDANT ); - DG_OP_MODE_T op = getCurrentOperationMode(); - F32 driftC = ( DG_MODE_HEAT == op ? TDI_TRO_TEMP_SENSORS_MAX_DEVIATION_IN_HEAT_DIS_C : TDI_TRO_TEMP_SENSORS_MAX_DEVIATION_C ); - BOOL isDriftOut = ( fabs( TDi - TRo ) > driftC ? TRUE : FALSE ); + if ( getMeasuredRawFlowRateLPM( DIALYSATE_FLOW_SENSOR ) > NEARLY_ZERO ) + { + F32 TDi = dialTempMovingAvgData[ DIAL_TEMP_TDI ].dialTempAvgC; + F32 TRo = dialTempMovingAvgData[ DIAL_TEMP_TRO ].dialTempAvgC; + DG_OP_MODE_T op = getCurrentOperationMode(); + F32 driftC = ( DG_MODE_HEAT == op ? TDI_TRO_TEMP_SENSORS_MAX_DEVIATION_IN_HEAT_DIS_C : TDI_TRO_TEMP_SENSORS_MAX_DEVIATION_C ); + BOOL isDriftOut = ( fabs( TDi - TRo ) > driftC ? TRUE : FALSE ); - checkPersistentAlarm( ALARM_ID_DG_DIALYSATE_TEMPERATURE_SENSORS_OUT_OF_RANGE, isDriftOut, fabs( TDi - TRo ), driftC ); + checkPersistentAlarm( ALARM_ID_DG_DIALYSATE_TEMPERATURE_SENSORS_OUT_OF_RANGE, isDriftOut, fabs( TDi - TRo ), driftC ); + } } } @@ -739,8 +782,8 @@ { F32 temperature; F32 avgADCReads; - U32 index = tempSensors[ sensorIndex ].adcNextIndex; - S32 indexValue = tempSensors[ sensorIndex ].rawADCReads [ index ]; + U32 index = tempSensors[ sensorIndex ].adcNextIndex; + S32 indexValue = tempSensors[ sensorIndex ].rawADCReads[ index ]; // Update the temperature sensors' structure tempSensors[ sensorIndex ].rawADCReads[ index ] = adc; @@ -950,6 +993,8 @@ data.interalTHDRTD = getTemperatureValue( TEMPSENSORS_INTERNAL_THD_RTD ); data.internalCondSnsrTemp = getTemperatureValue( TEMPSENSORS_INTERNAL_COND_TEMP_SENSOR ); data.baroTempSensor = getTemperatureValue( TEMPSENSORS_BAROMETRIC_TEMP_SENSOR ); + data.dialysateInletMovingAvg = dialTempMovingAvgData[ DIAL_TEMP_TDI ].dialTempAvgC; + data.redundantOutletMovingAvg = dialTempMovingAvgData[ DIAL_TEMP_TRO ].dialTempAvgC; broadcastData( MSG_ID_DG_TEMPERATURE_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( TEMPERATURE_SENSORS_DATA_T ) ); dataPublicationTimerCounter = 0; @@ -1089,7 +1134,43 @@ } } +/*********************************************************************//** + * @brief + * The processDialTemperatureData function processes the moving average + * of the dialysate temperature sensors (TDi and TRo). + * @details Inputs: dialTempMovingAvgData + * @details Outputs: dialTempMovingAvgData + * @return: none + *************************************************************************/ +static void processDialTemperatureData( void ) +{ + DIAL_TEMPERATURE_SENSORS_T i; + for ( i = DIAL_TEMP_FIRST; i < NUM_OF_DIAL_TEMPS; i++ ) + { + if ( FALSE == dialTempMovingAvgData[ i ].dialTempColHasTimerBeenSet ) + { + dialTempMovingAvgData[ i ].dialTempDataColStartTimeMS = getMSTimerCount(); + dialTempMovingAvgData[ i ].dialTempColHasTimerBeenSet = TRUE; + } + else if ( TRUE == didTimeout( dialTempMovingAvgData[ i ].dialTempDataColStartTimeMS, TDI_TRO_DATA_COLLECTION_TIME_MS ) ) + { + TEMPERATURE_SENSORS_T sensor = ( DIAL_TEMP_TDI == i ? TEMPSENSORS_INLET_DIALYSATE : TEMPSENSORS_OUTLET_REDUNDANT ); + F32 temperatureC = getTemperatureValue( sensor ); + U32 currentIndex = dialTempMovingAvgData[ i ].dialTempSamplesNextIndex; + F32 prevSampleToRemoveC = dialTempMovingAvgData[ i ].dialTempSamplesC[ currentIndex ]; + + dialTempMovingAvgData[ i ].dialTempDataColStartTimeMS = getMSTimerCount(); + dialTempMovingAvgData[ i ].dialTempColHasTimerBeenSet = TRUE; + dialTempMovingAvgData[ i ].dialTempSamplesC[ currentIndex ] = temperatureC; + dialTempMovingAvgData[ i ].dialTempRunningSumC = dialTempMovingAvgData[ i ].dialTempRunningSumC + temperatureC - prevSampleToRemoveC; + dialTempMovingAvgData[ i ].dialTempSamplesNextIndex = INC_WRAP( dialTempMovingAvgData[ i ].dialTempSamplesNextIndex, 0, DIAL_TEMP_MOVING_AVG_NUM_OF_SAMPLES - 1 ); + dialTempMovingAvgData[ i ].dialTempAvgC = dialTempMovingAvgData[ i ].dialTempRunningSumC / (F32)DIAL_TEMP_MOVING_AVG_NUM_OF_SAMPLES; + } + } +} + + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/