/************************************************************************** * * Copyright (c) 2020-2025 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 TemperatureSensors.c * * @author (last) Dara Navaei * @date (last) 10-Nov-2025 * * @author (original) Dara Navaei * @date (original) 08-Apr-2020 * ***************************************************************************/ #include // For temperature calculation #include // For memset() #include "FlowSensors.h" #include "FPGA.h" #include "MessageSupport.h" #include "NVDataMgmt.h" #include "OperationModes.h" #include "PersistentAlarm.h" #include "SystemCommMessages.h" #include "TemperatureSensors.h" #include "Timers.h" #include "TaskPriority.h" #include "TaskGeneral.h" #include "Utilities.h" #include "Valves.h" /** * @addtogroup TemperatureSensors * @{ */ // ********** private definitions ********** #define PRIMARY_HEATER_EXT_TEMP_SENSORS_GAIN 8U ///< Primary heater external temperature sensors gain. #define PRIMARY_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE 20000 ///< Primary heater external temperature sensors reference resistance. #define PRIMARY_HEATER_EXT_TEMP_SENSORS_0_DEGREE_RESISTANCE 1000U ///< Primary heater external temperature sensors zero degree resistance. #define PRIMARY_HEATER_EXT_TEMP_SENSORS_V3_REF_RESISTANCE 19600 ///< Primary heater external temperature sensors V3 reference resistance. #define V3_INTERNAL_THD_RTD 40.0F ///< Internal THD RTD not supported on V3. Specify nominal value #define COND_SENSORS_TEMP_SENSOR_GAIN 8U ///< Temperature sensor for conductivity gain. #define COND_SENSORS_TEMP_SENSOR_REF_RESISTANCE 20000 ///< Temperature sensor for conductivity reference resistance. #define COND_SENSORS_TEMP_SENSOR_0_DEGREE_RESISTANCE 1000U ///< Temperature sensor for conductivity zero degree resistance. #define COND_SENSORS_TEMP_SENSOR_V3_REF_RESISTANCE 19600 ///< Temperature sensor for conductivity V3 reference resistance. #define TRIMMER_HEATER_EXT_TEMP_SENSORS_GAIN 32U ///< Trimmer heater external temperature sensors gain. #define TRIMMER_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE 4990 ///< Trimmer heater external temperature sensors reference resistance. #define TRIMMER_HEATER_EXT_TEMP_SENSORS_0_DEGREE_RESISTANCE 100U ///< Trimmer heater external temperature sensors zero degree resistance. #define TRIMMER_HEATER_EXT_TEMP_SENSORS_V3_REF_RESISTANCE 5110 ///< Trimmer heater external temperature sensors V3 reference resistance. #define TEMP_SENSORS_ADC_BITS 24U ///< External temperature sensors ADC bits. #define ADC_FPGA_READ_DELAY 30U ///< Delay in ms before reading the ADC values from FPGA. #define MAX_NUM_OF_RAW_ADC_SAMPLES 4U ///< Number of ADC reads for moving average calculations. #define MAX_ALLOWED_TEMP_DELTA_BETWEEN_SENSORS 2U ///< Maximum allowed temperature delta between sensors. #define SHIFT_BITS_BY_2 2U ///< Shift bits by 2 to create a 4 for averaging 4 samples. #define SHIFT_BITS_BY_2_FOR_AVERAGING 2U ///< Shift the ADCs of the temperature sensors by 2 to average them. #define INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS ( 30 * MS_PER_SECOND ) ///< Inlet water temperature sensors timeout in milliseconds. #define INLET_WATER_TEMP_OUT_OF_RANGE_CLEAR_MS ( 1 * MS_PER_SECOND ) ///< Inlet water temperature sensors out of range clear in milliseconds. #define MIN_WATER_TEMPERATURE_WARNING_LOW_RANGE 24.0F ///< Low range minimum water input temperature. #define MAX_WATER_TEMPERATURE_WARNING_LOW_RANGE 26.0F ///< Low range maximum water input temperature. #define MIN_WATER_TEMPERATURE_WARNING_HIGH_RANGE 35.0F ///< High range minimum water input temperature. #define MAX_WATER_TEMPERATURE_WARNING_HIGH_RANGE 37.0F ///< High range maximum water input temperature. #define MAX_CLEANING_MODE_WATER_TEMPERATURE_WARNING_HIGH_RANGE 45.0F ///< High range maximum cleaning mode water input temperature. #define HEATERS_INTERNAL_TEMPERTURE_CALCULATION_INTERVAL 20U ///< Time interval that is used to calculate the heaters internal temperature. #define HEATERS_INTERNAL_TC_ADC_TO_TEMP_CONVERSION_COEFF 0.25F ///< Heaters internal temperature sensors ADC to temperature conversion coefficient. #define HEATERS_COLD_JUNCTION_ADC_TO_TEMP_CONVERSION_COEFF 0.0625F ///< Heaters cold junction temperature sensors ADC to temperature conversion coefficient. #define K_THERMOCOUPLE_TEMP_2_MILLI_VOLT_CONVERSION_COEFF 0.041276F ///< K thermocouple temperature to millivolt conversion coefficient. #define SIZE_OF_THERMOCOUPLE_COEFFICIENTS 10U ///< Size of the thermocouple coefficients. #define CELSIUS_TO_KELVIN_CONVERSION 273.15F ///< Celsius to Kelvin temperature conversion. #define ADC_BOARD_TEMP_SENSORS_CONVERSION_CONST 272.5F ///< ADC board temperature sensors conversion constant. #define ADC_BOARD_TEMP_SENSORS_CONST 0x800000 ///< ADC board temperature sensors constant. #define EXTERNAL_TEMP_SENSORS_ERROR_VALUE 0x80 ///< External temperature sensors error value. #define HEATERS_INTERNAL_TEMP_SENSOR_FAULT 0x01 ///< Heaters internal temperature sensor fault. #define TEMP_SENSORS_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Temperature sensors publish data time interval. #define TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Temperature sensors FPGA error timeout in milliseconds. #define TEMP_SENSORS_MIN_ALLOWED_DEGREE_C 0.0F ///< Temperature sensors minimum allowed temperature in C. #define TEMP_SENSORS_MAX_ALLOWED_DEGREE_C 120.0F ///< Temperature sensors maximum allowed temperature in C. #define HEATERS_INTERNAL_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C 200.0F ///< Heaters' internal temperature sensors maximum allowed temperature in C. #define NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C 80.0F ///< Non fluid temperature sensors path maximum allowed temperature in C. #define TEMP_SENSORS_OUT_OF_RANGE_TIME_OUT_MS ( 5 * MS_PER_SECOND ) ///< Temperature sensor out of range persistent period in milliseconds. #define DATA_PUBLISH_COUNTER_START_COUNT 30 ///< Data publish counter start count. #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 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 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 { TEMPSENSORS_EXEC_STATE_START = 0, ///< Temperature sensors exec start TEMPSENSORS_EXEC_STATE_GET_ADC_VALUES, ///< Temperature sensors exec get ADC values 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 { F32 gain; ///< ADC gain F32 refResistance; ///< ADC reference resistance F32 conversionCoeff; ///< ADC conversion coefficient F32 zeroDegreeResistance; ///< ADC zero degree resistance S32 rawADCReads[ MAX_NUM_OF_RAW_ADC_SAMPLES ]; ///< Raw ADC reads array S32 adcNextIndex; ///< Next ADC read index S32 adcRunningSum; ///< ADC running sum OVERRIDE_F32_T temperatureValues; ///< Temperature values with override F32 maxAllowedTemp; ///< Maximum allowed temperature of the sensor U32 alarmStartTime; ///< Alarm start time BOOL fpgaErrorStatus; ///< Temperature sensor FPGA error status S32 baroTempSnsrDiff; ///< Barometric sensor temperature difference } TEMP_SENSOR_T; /// Barometric sensor temperature conversion typedef struct { U16 refTemperature; ///< Barometric sensor reference temperature. U16 temperatureCoeff; ///< Barometric sensor temperature coefficient. OVERRIDE_U32_T coeffsCRC; ///< Barometric sensor coefficients CRC. U32 waitForCoeffStartTimeMS; ///< Barometric sensor wait for coefficients start time in milliseconds. BOOL hasCRCBeenChecked; ///< Barometric sensor has CRC been checked flag. BOOL hasCRCCheckBeenRequested; ///< Barometric sensor has CRC check been requested flag. } BARO_SENSOR_CONSTS_T; /// Barometric sensor coefficients typedef struct { U16 mfgInfo; ///< Barometric sensor manufacturing info. U16 pressSensitivity; ///< Barometric sensor pressure sensitivity. U16 pressOffset; ///< Barometric sensor pressure offset. U16 tempCoeffOfPressSens; ///< Barometric sensor temperature coefficient of pressure sensor. U16 tempCoeffPressOffset; ///< Barometric sensor temperature coefficient of pressure offset. U16 referenceTemp; ///< Barometric sensor reference temperature. U16 tempCoeffOfTemp; ///< Barometric sensor temperature coefficient of Temperature sensor. 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. static TEMP_SENSOR_T tempSensors [ NUM_OF_TEMPERATURE_SENSORS ]; ///< Temperature sensors' data structure. static U32 elapsedTime; ///< Elapsed time variable. static U32 internalHeatersConversionTimer; ///< Conversion timer variable to calculate the heaters internal temperature. static BARO_SENSOR_CONSTS_T baroConvConsts; ///< Barometric sensor conversion constants. static U32 dataPublicationTimerCounter; ///< Temperature sensors data publish timer counter. 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 BOOL tempDriftEventCheck; ///< Temperature sensor drift event boolean. 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. static const F32 POSITIVE_TC_COEFFS [ SIZE_OF_THERMOCOUPLE_COEFFICIENTS ] = { -0.176004136860E-1, 0.389212049750E-1, 0.185587700320E-4, -0.994575928740E-7, 0.318409457190E-9, -0.560728448890E-12, 0.560750590590E-15,-0.320207200030E-18, 0.971511471520E-22,-0.121047212750E-25 }; ///< Thermocouple correction coefficients for positive cold junction temperature. static const F32 POSITIVE_TC_INVERSER_COEFFS [ SIZE_OF_THERMOCOUPLE_COEFFICIENTS ] = { 0.0, 2.508355E1, 7.860106E-2, -2.503131E-1, 8.315270E-2, -1.228034E-2, 9.804036E-4, -4.413030E-5, 1.057734E-6, -1.052755E-8 }; ///< Thermocouple inverse coefficient for positive cold junction temperature. static const U32 TEMP_EQUATION_RESISTOR_CALC = 1 << ( TEMP_SENSORS_ADC_BITS - 1 ); ///< Temperature sensors resistor calculation (2^(24 - 1)). static const F32 TEMP_EQUATION_COEFF_A = 3.9083E-3; ///< ADC to temperature conversion coefficient A. static const F32 TEMP_EQUATION_COEFF_B = -5.775E-7; ///< ADC to temperature conversion coefficient B. static const U32 TWO_TO_POWER_OF_8 = ( 1 << 8 ); ///< 2^8. static const U32 TWO_TO_POWER_OF_23 = ( 1 << 23 ); ///< 2^23. // ********** private function prototypes ********** static TEMPSENSORS_EXEC_STATES_T handleExecStart( void ); static TEMPSENSORS_EXEC_STATES_T handleExecGetADCValues( void ); static F32 getADC2TempConversion( F32 avgADC, U32 gain, U32 refResistance, U32 zeroDegResistance, F32 adcConversionCoeff ); static void getHeaterInternalTemp( U32 TCIndex, U32 CJIndex ); static void processTempSnsrsADCRead( U32 sensorIndex, U32 adc ); static void processHtrsTempSnsrsADCRead( U32 sensorIndex, U16 adc ); static void processADCRead( U32 sensorIndex, S32 adc ); static void publishTemperatureSensorsData( void ); static void monitorTemperatureSenors( void ); static void adjustTemperatureSensorsRefResistance( void ); static void checkBaroSensorCRC( void ); static void processDialTemperatureData( void ); static void getCalibrationAppliedTemperatureValue( U32 sesnorIndex, F32* temperature ); /*********************************************************************//** * @brief * The initTemperatureSensors function initializes the module. * @details Inputs: none * @details Outputs: tempSensorsSelfTestState, tempSensorsExecState, * elapsedTime, internalHeatersConversionTimer, dataPublicationTimerCounter, * tempSensors, baroConvConsts, dialTempMovingAvgData * @return none *************************************************************************/ void initTemperatureSensors( void ) { U08 i; DIAL_TEMPERATURE_SENSORS_T j; tempSensorsExecState = TEMPSENSORS_EXEC_STATE_START; elapsedTime = 0; internalHeatersConversionTimer = 0; dataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; baroConvConsts.coeffsCRC.data = 0; baroConvConsts.hasCRCBeenChecked = FALSE; baroConvConsts.waitForCoeffStartTimeMS = 0; tempDriftEventCheck = FALSE; /* NOTE: The temperature sensors do not have conversion coefficient. * The conversion coefficients are used for the heaters internal temperature sensors and * the temperature will be calculated using a quadratic equation * The internal thermocouple has 0.25 conversion coefficient * The heaters cold junction sensor has 0.0625 conversion coefficient * The conversion coefficient will be set to 0 for the temperature sensors */ for ( i = 0; i < NUM_OF_TEMPERATURE_SENSORS; ++i ) { memset( &tempSensors[ i ], 0x0, sizeof( TEMP_SENSOR_T ) ); benignPolynomialCalRecord( &tempSensorCalRecord.tempSensors[ i ] ); } // 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; tempSensors[ TEMPSENSORS_INLET_PRIMARY_HEATER ].zeroDegreeResistance = PRIMARY_HEATER_EXT_TEMP_SENSORS_0_DEGREE_RESISTANCE; tempSensors[ TEMPSENSORS_INLET_PRIMARY_HEATER ].maxAllowedTemp = TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; tempSensors[ TEMPSENSORS_HEAT_DISINFECT ].gain = TRIMMER_HEATER_EXT_TEMP_SENSORS_GAIN; tempSensors[ TEMPSENSORS_HEAT_DISINFECT ].refResistance = TRIMMER_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE; tempSensors[ TEMPSENSORS_HEAT_DISINFECT ].zeroDegreeResistance = TRIMMER_HEATER_EXT_TEMP_SENSORS_0_DEGREE_RESISTANCE; tempSensors[ TEMPSENSORS_HEAT_DISINFECT ].maxAllowedTemp = TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; tempSensors[ TEMPSENSORS_OUTLET_PRIMARY_HEATER ].gain = PRIMARY_HEATER_EXT_TEMP_SENSORS_GAIN; tempSensors[ TEMPSENSORS_OUTLET_PRIMARY_HEATER ].refResistance = PRIMARY_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE; tempSensors[ TEMPSENSORS_OUTLET_PRIMARY_HEATER ].zeroDegreeResistance = PRIMARY_HEATER_EXT_TEMP_SENSORS_0_DEGREE_RESISTANCE; tempSensors[ TEMPSENSORS_OUTLET_PRIMARY_HEATER ].maxAllowedTemp = TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; // Initialize TD1 and TD2 constants tempSensors[ TEMPSENSORS_CONDUCTIVITY_SENSOR_1 ].gain = COND_SENSORS_TEMP_SENSOR_GAIN; tempSensors[ TEMPSENSORS_CONDUCTIVITY_SENSOR_1 ].refResistance = COND_SENSORS_TEMP_SENSOR_REF_RESISTANCE; tempSensors[ TEMPSENSORS_CONDUCTIVITY_SENSOR_1 ].zeroDegreeResistance = COND_SENSORS_TEMP_SENSOR_0_DEGREE_RESISTANCE; tempSensors[ TEMPSENSORS_CONDUCTIVITY_SENSOR_1 ].maxAllowedTemp = TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; tempSensors[ TEMPSENSORS_CONDUCTIVITY_SENSOR_2 ].gain = COND_SENSORS_TEMP_SENSOR_GAIN; tempSensors[ TEMPSENSORS_CONDUCTIVITY_SENSOR_2 ].refResistance = COND_SENSORS_TEMP_SENSOR_REF_RESISTANCE; tempSensors[ TEMPSENSORS_CONDUCTIVITY_SENSOR_2 ].zeroDegreeResistance = COND_SENSORS_TEMP_SENSOR_0_DEGREE_RESISTANCE; tempSensors[ TEMPSENSORS_CONDUCTIVITY_SENSOR_2 ].maxAllowedTemp = TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; // Initialize TRo and TDi constants tempSensors[ TEMPSENSORS_OUTLET_REDUNDANT ].gain = TRIMMER_HEATER_EXT_TEMP_SENSORS_GAIN; tempSensors[ TEMPSENSORS_OUTLET_REDUNDANT ].refResistance = TRIMMER_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE; tempSensors[ TEMPSENSORS_OUTLET_REDUNDANT ].zeroDegreeResistance = TRIMMER_HEATER_EXT_TEMP_SENSORS_0_DEGREE_RESISTANCE; tempSensors[ TEMPSENSORS_OUTLET_REDUNDANT ].maxAllowedTemp = TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; tempSensors[ TEMPSENSORS_INLET_DIALYSATE ].gain = TRIMMER_HEATER_EXT_TEMP_SENSORS_GAIN; tempSensors[ TEMPSENSORS_INLET_DIALYSATE ].refResistance = TRIMMER_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE; tempSensors[ TEMPSENSORS_INLET_DIALYSATE ].zeroDegreeResistance = TRIMMER_HEATER_EXT_TEMP_SENSORS_0_DEGREE_RESISTANCE; tempSensors[ TEMPSENSORS_INLET_DIALYSATE ].maxAllowedTemp = TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; // Initialize the heaters internal thermocouples constants tempSensors[ TEMPSENSORS_PRIMARY_HEATER_THERMO_COUPLE ].conversionCoeff = HEATERS_INTERNAL_TC_ADC_TO_TEMP_CONVERSION_COEFF; tempSensors[ TEMPSENSORS_PRIMARY_HEATER_THERMO_COUPLE ].maxAllowedTemp = HEATERS_INTERNAL_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; tempSensors[ TEMPSENSORS_TRIMMER_HEATER_THERMO_COUPLE ].conversionCoeff = HEATERS_INTERNAL_TC_ADC_TO_TEMP_CONVERSION_COEFF; tempSensors[ TEMPSENSORS_TRIMMER_HEATER_THERMO_COUPLE ].maxAllowedTemp = HEATERS_INTERNAL_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; // Initialize the heaters cold junction constants tempSensors[ TEMPSENSORS_PRIMARY_HEATER_COLD_JUNCTION ].conversionCoeff = HEATERS_COLD_JUNCTION_ADC_TO_TEMP_CONVERSION_COEFF; tempSensors[ TEMPSENSORS_PRIMARY_HEATER_COLD_JUNCTION ].maxAllowedTemp = TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; tempSensors[ TEMPSENSORS_TRIMMER_HEATER_COLD_JUNCTION ].conversionCoeff = HEATERS_COLD_JUNCTION_ADC_TO_TEMP_CONVERSION_COEFF; tempSensors[ TEMPSENSORS_TRIMMER_HEATER_COLD_JUNCTION ].maxAllowedTemp = TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; // Initialize the heaters internal temperature sensors tempSensors[ TEMPSENSORS_PRIMARY_HEATER_INTERNAL ].maxAllowedTemp = HEATERS_INTERNAL_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; tempSensors[ TEMPSENSORS_TRIMMER_HEATER_INTERNAL ].maxAllowedTemp = HEATERS_INTERNAL_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; // FPGA board temperature conversion coefficient tempSensors[ TEMPSENSORS_FPGA_BOARD_SENSOR ].conversionCoeff = 503.975F / (F32)BITS_12_FULL_SCALE; tempSensors[ TEMPSENSORS_FPGA_BOARD_SENSOR ].maxAllowedTemp = NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; F32 conversionCoeff = 1.0F / 13584.0F; // Board temperature sensors conversion coefficient tempSensors[ TEMPSENSORS_LOAD_CELL_A1_B1 ].conversionCoeff = conversionCoeff; tempSensors[ TEMPSENSORS_LOAD_CELL_A1_B1 ].maxAllowedTemp = NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; tempSensors[ TEMPSENSORS_LOAD_CELL_A2_B2 ].conversionCoeff = conversionCoeff; tempSensors[ TEMPSENSORS_LOAD_CELL_A2_B2 ].maxAllowedTemp = NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; tempSensors[ TEMPSENSORS_INTERNAL_TRO_RTD ].conversionCoeff = conversionCoeff; tempSensors[ TEMPSENSORS_INTERNAL_TRO_RTD ].maxAllowedTemp = NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; tempSensors[ TEMPSENSORS_INTERNAL_TDI_RTD ].conversionCoeff = conversionCoeff; tempSensors[ TEMPSENSORS_INTERNAL_TDI_RTD ].maxAllowedTemp = NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; tempSensors[ TEMPSENSORS_INTERNAL_THD_RTD ].conversionCoeff = conversionCoeff; tempSensors[ TEMPSENSORS_INTERNAL_THD_RTD ].maxAllowedTemp = NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; tempSensors[ TEMPSENSORS_INTERNAL_COND_TEMP_SENSOR ].conversionCoeff = conversionCoeff; tempSensors[ TEMPSENSORS_INTERNAL_COND_TEMP_SENSOR ].maxAllowedTemp = NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; tempSensors[ TEMPSENSORS_BAROMETRIC_TEMP_SENSOR ].maxAllowedTemp = NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; // Persistent alarms for inlet water high/low temperature initPersistentAlarm( ALARM_ID_DG_INLET_WATER_TEMPERATURE_IN_LOW_RANGE, INLET_WATER_TEMP_OUT_OF_RANGE_CLEAR_MS, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_DG_INLET_WATER_TEMPERATURE_IN_HIGH_RANGE, INLET_WATER_TEMP_OUT_OF_RANGE_CLEAR_MS, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_TEMP_TOO_HIGH, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_TEMP_TOO_LOW, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS, INLET_WATER_TEMP_OUT_OF_RANGE_TIMEOUT_MS ); // Persistent alarm for the temperature sensors range check initPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSOR_OUT_OF_RANGE, TEMP_SENSORS_OUT_OF_RANGE_TIME_OUT_MS, TEMP_SENSORS_OUT_OF_RANGE_TIME_OUT_MS ); // Persistent alarm for the temperature sensors range check initPersistentAlarm( ALARM_ID_DG_DIALYSATE_TEMPERATURE_SENSORS_OUT_OF_RANGE, 0, DIALYSATE_TEMP_SNSRS_OUT_OF_RANGE_TIMEOUT_MS ); // Initialize the FPGA persistent alarms initFPGAPersistentAlarm( FPGA_PERS_ERROR_TWO_WIRE_ADC_TEMP_SENSORS, ALARM_ID_DG_TWO_WIRE_SENSORS_FPGA_FAULT, TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS, TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS); initFPGAPersistentAlarm( FPGA_PERS_ERROR_THD_ADC_TEMP_SENSORS, ALARM_ID_DG_THD_SENSORS_FPGA_FAULT, TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS, TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS); initFPGAPersistentAlarm( FPGA_PERS_ERROR_TDI_ADC_TEMP_SENSORS, ALARM_ID_DG_TDI_SENSORS_FPGA_FAULT, TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS, TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS); initFPGAPersistentAlarm( FPGA_PERS_ERROR_TRO_ADC_TEMP_SENSORS, ALARM_ID_DG_TRO_SENSORS_FPGA_FAULT, TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS, TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS); initFPGAPersistentAlarm( FPGA_PERS_ERROR_BARO_SENSOR, ALARM_ID_DG_BARO_SENSOR_FPGA_FAULT, TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS, TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS); } /*********************************************************************//** * @brief * The execTemperatureSensorsSelfTest function runs the TemperatureSensors * POST during the self-test. * @details Inputs: none * @details Outputs: none * @return tempSensorsSelfTestState which is the status of the self test *************************************************************************/ SELF_TEST_STATUS_T execTemperatureSensorsSelfTest( void ) { SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; BOOL calStatus = getNVRecord2Driver( GET_CAL_TEMP_SENSORS, (U08*)&tempSensorCalRecord, sizeof( DG_TEMP_SENSORS_CAL_RECORD_T ), NUM_OF_CAL_DATA_TEMP_SENSORS, ALARM_ID_DG_TEMPERATURE_SENSORS_INVALID_CAL_RECORD ); if ( TRUE == calStatus ) { result = SELF_TEST_STATUS_PASSED; } else { result = SELF_TEST_STATUS_FAILED; } return result; } /*********************************************************************//** * @brief * The execTemperatureSensors function executes the temperature sensors' * state machine. * @details Inputs: tempSensorsExecState * @details Outputs: tempSensorsExecState * @return none *************************************************************************/ void execTemperatureSensors( void ) { // Check if a new calibration is available if ( TRUE == isNewCalibrationRecordAvailable() ) { getNVRecord2Driver( GET_CAL_TEMP_SENSORS, (U08*)&tempSensorCalRecord, sizeof( DG_TEMP_SENSORS_CAL_RECORD_T ), NUM_OF_CAL_DATA_TEMP_SENSORS, ALARM_ID_DG_TEMPERATURE_SENSORS_INVALID_CAL_RECORD ); } // Check the status of the software configuration adjustTemperatureSensorsRefResistance(); // Read the sensors all the time switch ( tempSensorsExecState ) { case TEMPSENSORS_EXEC_STATE_START: tempSensorsExecState = handleExecStart(); break; case TEMPSENSORS_EXEC_STATE_GET_ADC_VALUES: tempSensorsExecState = handleExecGetADCValues(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_TEMPERATURE_SENSORS_EXEC_INVALID_STATE, tempSensorsExecState ); tempSensorsExecState = TEMPSENSORS_EXEC_STATE_GET_ADC_VALUES; break; } // Monitor the temperature values monitorTemperatureSenors(); // Process the moving average of the dialysate temperature sensors (TDi and TRo) processDialTemperatureData(); // Check the TDi/TRo drift checkDialysateTemperatureSensors(); // Publish the data publishTemperatureSensorsData(); } /*********************************************************************//** * @brief * The checkInletWaterTemperature function checks inlet water temperature value * and triggers an alarm when temperature value is out of allowed range. * @details Inputs: none * @details Outputs: none * @return none *************************************************************************/ void checkInletWaterTemperature( void ) { F32 temperature = getTemperatureValue( TEMPSENSORS_INLET_PRIMARY_HEATER ); if ( VALVE_STATE_OPEN == getValveStateName( VPI ) ) { #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_WATER_QUALITY_CHECK ) != SW_CONFIG_ENABLE_VALUE ) #endif { if ( getTestConfigStatus( TEST_CONFIG_DISABLE_INLET_WATER_TEMP_CHECK ) != TRUE ) { DG_OP_MODE_T opMode = getCurrentOperationMode(); BOOL isWaterTempInHighRange = ( temperature > MAX_WATER_TEMPERATURE_WARNING_HIGH_RANGE ? TRUE : FALSE ); BOOL isWaterTempInLowRange = ( temperature < MIN_WATER_TEMPERATURE_WARNING_LOW_RANGE ? TRUE : FALSE ); switch( opMode ) { case DG_MODE_GENE: case DG_MODE_FILL: case DG_MODE_DRAI: case DG_MODE_STAN: if ( TRUE == isAlarmActive( ALARM_ID_DG_INLET_WATER_TEMPERATURE_IN_HIGH_RANGE ) ) { isWaterTempInHighRange = ( temperature <= MIN_WATER_TEMPERATURE_WARNING_HIGH_RANGE ? FALSE : TRUE ); } // Per PRS 406 checkPersistentAlarm( ALARM_ID_DG_INLET_WATER_TEMPERATURE_IN_HIGH_RANGE, isWaterTempInHighRange, temperature, MAX_WATER_TEMPERATURE_WARNING_HIGH_RANGE ); if ( TRUE == isAlarmActive( ALARM_ID_DG_INLET_WATER_TEMPERATURE_IN_LOW_RANGE ) ) { isWaterTempInLowRange = ( temperature >= MAX_WATER_TEMPERATURE_WARNING_LOW_RANGE ? FALSE : TRUE ); } // Per PRS 405 checkPersistentAlarm( ALARM_ID_DG_INLET_WATER_TEMPERATURE_IN_LOW_RANGE, isWaterTempInLowRange, temperature, MIN_WATER_TEMPERATURE_WARNING_LOW_RANGE ); break; case DG_MODE_FLUS: case DG_MODE_HEAT: case DG_MODE_HCOL: case DG_MODE_CHEM: case DG_MODE_CHFL: case DG_MODE_ROPS: isWaterTempInHighRange = ( temperature > MAX_CLEANING_MODE_WATER_TEMPERATURE_WARNING_HIGH_RANGE ? TRUE : FALSE ); // Per PRS 557 checkPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_TEMP_TOO_HIGH, isWaterTempInHighRange, temperature, MAX_WATER_TEMPERATURE_WARNING_HIGH_RANGE ); checkPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_TEMP_TOO_LOW, isWaterTempInLowRange, temperature, MAX_WATER_TEMPERATURE_WARNING_LOW_RANGE ); break; default: // NOTE: Do nothing in the rest of the modes break; } } } } else { // VPI is closed - clear all alarms checkPersistentAlarm( ALARM_ID_DG_INLET_WATER_TEMPERATURE_IN_HIGH_RANGE, FALSE, temperature, MAX_WATER_TEMPERATURE_WARNING_HIGH_RANGE ); checkPersistentAlarm( ALARM_ID_DG_INLET_WATER_TEMPERATURE_IN_LOW_RANGE, FALSE, temperature, MIN_WATER_TEMPERATURE_WARNING_LOW_RANGE ); checkPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_TEMP_TOO_HIGH, FALSE, temperature, MAX_WATER_TEMPERATURE_WARNING_HIGH_RANGE ); checkPersistentAlarm( ALARM_ID_DG_CLEANING_MODE_INLET_WATER_TEMP_TOO_LOW, FALSE, temperature, MAX_WATER_TEMPERATURE_WARNING_LOW_RANGE ); } } /*********************************************************************//** * @brief * The getTemperatureValue function gets the temperature of the requested * sensor. * @details Inputs: tempSensors * @details Outputs: none * @param sensorIndex which is the temperature sensor index * @return temperature of the requested sensor *************************************************************************/ F32 getTemperatureValue( U32 sensorIndex ) { F32 temperature = 0.0F; if ( sensorIndex < NUM_OF_TEMPERATURE_SENSORS ) { temperature = getF32OverrideValue( &tempSensors[ sensorIndex ].temperatureValues ); #ifndef _RELEASE_ // If the system is V3 and THd or its ADC internal temperature is requested, return TRo instead. V3 does not have // the electrical connection of THd sensor. if ( HW_CONFIG_BETA == getHardwareConfigStatus() ) { if ( TEMPSENSORS_HEAT_DISINFECT == sensorIndex ) { if ( OVERRIDE_KEY == tempSensors[ TEMPSENSORS_HEAT_DISINFECT ].temperatureValues.override ) { temperature = getF32OverrideValue( &tempSensors[ TEMPSENSORS_HEAT_DISINFECT ].temperatureValues ); } else { temperature = getF32OverrideValue( &tempSensors[ TEMPSENSORS_OUTLET_REDUNDANT ].temperatureValues ); } } if ( TEMPSENSORS_INTERNAL_THD_RTD == sensorIndex ) { temperature = V3_INTERNAL_THD_RTD; } if ( TEMPSENSORS_OUTLET_REDUNDANT == sensorIndex ) { if ( OVERRIDE_KEY == tempSensors[ TEMPSENSORS_OUTLET_REDUNDANT ].temperatureValues.override ) { temperature = getF32OverrideValue( &tempSensors[ TEMPSENSORS_OUTLET_REDUNDANT ].temperatureValues ); } else { temperature = getF32OverrideValue( &tempSensors[ TEMPSENSORS_INLET_DIALYSATE ].temperatureValues ); } } } #endif } else { // Wrong sensor was called, raise an alarm SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_TEMPERATURE_SENSOR_SELECTED, sensorIndex ); } return temperature; } /*********************************************************************//** * @brief * The getBaroSensorTemperatureDiff function returns the barometric pressure * sensor's temperature difference. * @details Inputs: tempSensors * @details Outputs: none * @return barometric pressure sensor temperature difference *************************************************************************/ S32 getBaroSensorTemperatureDiff( void ) { return tempSensors[ TEMPSENSORS_BAROMETRIC_TEMP_SENSOR ].baroTempSnsrDiff; } /*********************************************************************//** * @brief * The checkDialysateTemperatureSensors function checks whether the * dialysate temperature sensors have drifted. If they are drifted, it raises * an alarm. * @details Inputs: none * @details Outputs: None * @return none *************************************************************************/ void checkDialysateTemperatureSensors( void ) { #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_TEMPERATURE_SENSORS_ALARM ) != SW_CONFIG_ENABLE_VALUE ) #endif { DG_OP_MODE_T op = getCurrentOperationMode(); switch ( op ) { case DG_MODE_GENE: case DG_MODE_FILL: case DG_MODE_DRAI: case DG_MODE_HEAT: case DG_MODE_CHEM: if ( getMeasuredRawFlowRateLPM( DIALYSATE_FLOW_SENSOR ) > NEARLY_ZERO ) { F32 TDi = dialTempMovingAvgData[ DIAL_TEMP_TDI ].dialTempAvgC; F32 TRo = dialTempMovingAvgData[ DIAL_TEMP_TRO ].dialTempAvgC; 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 ); if ( ( FALSE == tempDriftEventCheck ) && ( TRUE == isDriftOut ) ) { // Send event only condition trigger, not continuously. tempDriftEventCheck = TRUE; SEND_EVENT_WITH_2_U32_DATA(DG_EVENT_TEMPERATURE_DRIFT, TDi, TRo) } if ( ( TRUE == tempDriftEventCheck ) && ( FALSE == isDriftOut ) ) { tempDriftEventCheck = FALSE; } } break; default: // Do not raise alarm (ALARM_ID_DG_DIALYSATE_TEMPERATURE_SENSORS_OUT_OF_RANGE) in other modes. break; } } } /*********************************************************************//** * @brief * The requestBaroSensorMFGInfoCheck function requests the baro sensor manufacturing * information be checked. * @details Inputs: none * @details Outputs: baroConvConsts.hasCRCCheckBeenRequested * @return none *************************************************************************/ void requestBaroSensorMFGInfoCheck( void ) { baroConvConsts.hasCRCCheckBeenRequested = TRUE; } /*********************************************************************//** * @brief * The getADC2TempConversion function calculates the temperature from the * moving average ADC samples. * @details Inputs: tempEquationCoeffA, tempEquationCoeffB * @details Outputs: none * @param avgADC moving average ADC * @param gain ADC gain * @param refResistance ADC reference resistance * @param zeroDegResistance ADC zero degree resistance * @param adcConversionCoeff ADC conversion coefficient * @return calculated temperature *************************************************************************/ static F32 getADC2TempConversion( F32 avgADC, U32 gain, U32 refResistance, U32 zeroDegResistance, F32 adcConversionCoeff ) { F32 temperature = 0.0F; if ( fabs( adcConversionCoeff ) <= NEARLY_ZERO ) { // R(RTD) = R(ref) * ( adc – 2^(N - 1) ) / ( G * 2^(N - 1) ); F32 resistance = ( refResistance * ( avgADC - TEMP_EQUATION_RESISTOR_CALC ) ) / ( gain * TEMP_EQUATION_RESISTOR_CALC ); // T = (-A + √( A^2 - 4B * ( 1 - R_T / R_0 ) ) ) / 2B F32 secondSqrtPart = 4 * TEMP_EQUATION_COEFF_B * ( 1 - ( resistance / zeroDegResistance ) ); temperature = ( -TEMP_EQUATION_COEFF_A + sqrt( pow( TEMP_EQUATION_COEFF_A, 2 ) - secondSqrtPart ) ) / ( 2 * TEMP_EQUATION_COEFF_B ); } else { temperature = avgADC * adcConversionCoeff; } return temperature; } /*********************************************************************//** * @brief * The getHeaterInternalTemp function calculates the heaters' internal * temperature. * @details Inputs: tempSensors * @details Outputs: tempSensors * @param TCIndex thermocouple index * @param CJIndex cold junction index * @return none *************************************************************************/ static void getHeaterInternalTemp( U32 TCIndex, U32 CJIndex ) { /* voltage = 0.041276 * ( cold junction temp - thermo-couple temp ) * E = Ci * T^i + a0 * exp( a1 * ( T - a2 ) ^ 2 ) * i is the positive thermo-couple coefficients * a0 is the positive thermo-couple coefficient * a1 is the positive thermo-couple coefficient * a2 is the positive thermo-couple coefficient * E = voltage + E (E is the corrected voltage) * Temperature = di * E^i * d is positive inverse thermo-couple coefficient * E is corrected voltage */ F32 temperature = 0.0; F32 equiVoltage = 0.0; F32 correctedVoltage = 0.0; F32 TCTemp = tempSensors[ TCIndex ].temperatureValues.data; F32 CJTemp = tempSensors[ CJIndex ].temperatureValues.data; // Value in mV F32 rawVoltage = ( TCTemp - CJTemp ) * K_THERMOCOUPLE_TEMP_2_MILLI_VOLT_CONVERSION_COEFF; U08 i; // Check if cold junction is positive if ( CJTemp > 0 ) { for ( i = 0; i < SIZE_OF_THERMOCOUPLE_COEFFICIENTS; i++ ) { equiVoltage = equiVoltage + ( POSITIVE_TC_COEFFS[ i ] * pow( CJTemp, i ) ); } equiVoltage = equiVoltage + ( POSITIVE_TC_EXP_A0 * ( exp( POSITIVE_TC_EXP_A1 * pow( ( CJTemp - POSITIVE_TC_EXP_A2 ), 2 ) ) ) ); correctedVoltage = rawVoltage + equiVoltage; for ( i = 0; i < SIZE_OF_THERMOCOUPLE_COEFFICIENTS; i++ ) { temperature = temperature + ( POSITIVE_TC_INVERSER_COEFFS[ i ] * pow( correctedVoltage, i ) ); } } // Check which heater's internal temperature is being calculated if ( TEMPSENSORS_PRIMARY_HEATER_THERMO_COUPLE == TCIndex ) { tempSensors[ TEMPSENSORS_PRIMARY_HEATER_INTERNAL ].temperatureValues.data = temperature; } else { tempSensors[ TEMPSENSORS_TRIMMER_HEATER_INTERNAL ].temperatureValues.data = temperature; } } /*********************************************************************//** * @brief * The processTemperatureSensorsADCRead function masks the MSB of the ADC * read from FPGA and converts it to an S32. Then it calls another function * to check if the read ADC is valid or not and if it is, it calls another * function to process the ADC value and covert it to temperature. * @details Inputs: none * @details Outputs: none * @param sensorIndex ID of temperature sensor to process * @param adc ADC value for the temperature sensor * @return none *************************************************************************/ static void processTempSnsrsADCRead( U32 sensorIndex, U32 adc ) { S32 convertedADC = (S32)( adc & MASK_OFF_U32_MSB ); // Make sure the error bit is not true before processADCRead( sensorIndex, convertedADC ); } /*********************************************************************//** * @brief * The processHeatersInternalSensorsADCRead function checks whether the provided * sensor is the heaters thermocouple or cold junction sensors and performs * different bit shifts on them accordingly. Then it call another function to * check if the read ADC is valid and if it is, the function calls another function * process the ADC and convert it to temperature. * @details Inputs: none * @details Outputs: none * @param sensorIndex ID of temperature sensor to process * @param adc reported ADC value for temperature sensor * @return none *************************************************************************/ static void processHtrsTempSnsrsADCRead( U32 sensorIndex, U16 adc ) { S16 convert = (S16)adc; processADCRead( sensorIndex, (S32)convert ); } /*********************************************************************//** * @brief * The processADCRead function receives the ADC value and the sensor * index and calculates the running sum and the moving average of the ADCs * The temperatureSensorsADCRead and tempSensorsAvgADCValues are updated. * @details Inputs: tempSensors * @details Outputs: tempSensors * @param sensorIndex Temperature sensor index * @param adc adc reading from FPGA * @return none *************************************************************************/ static void processADCRead( U32 sensorIndex, S32 adc ) { F32 temperature; F32 avgADCReads; U32 index = tempSensors[ sensorIndex ].adcNextIndex; S32 indexValue = tempSensors[ sensorIndex ].rawADCReads[ index ]; // Update the temperature sensors' structure tempSensors[ sensorIndex ].rawADCReads[ index ] = adc; tempSensors[ sensorIndex ].adcNextIndex = INC_WRAP( index, 0, MAX_NUM_OF_RAW_ADC_SAMPLES - 1 ); tempSensors[ sensorIndex ].adcRunningSum = tempSensors[ sensorIndex ].adcRunningSum - indexValue + adc; avgADCReads = tempSensors[ sensorIndex ].adcRunningSum >> SHIFT_BITS_BY_2_FOR_AVERAGING; // Calculate the average // Different sensors have different ADC to temperature conversion methods switch( sensorIndex ) { case TEMPSENSORS_INLET_PRIMARY_HEATER: case TEMPSENSORS_OUTLET_PRIMARY_HEATER: case TEMPSENSORS_CONDUCTIVITY_SENSOR_1: case TEMPSENSORS_CONDUCTIVITY_SENSOR_2: case TEMPSENSORS_OUTLET_REDUNDANT: case TEMPSENSORS_INLET_DIALYSATE: case TEMPSENSORS_PRIMARY_HEATER_THERMO_COUPLE: case TEMPSENSORS_TRIMMER_HEATER_THERMO_COUPLE: case TEMPSENSORS_PRIMARY_HEATER_COLD_JUNCTION: case TEMPSENSORS_TRIMMER_HEATER_COLD_JUNCTION: case TEMPSENSORS_HEAT_DISINFECT: temperature = getADC2TempConversion( avgADCReads, (U32)tempSensors [ sensorIndex ].gain, (U32)tempSensors [ sensorIndex ].refResistance, (U32)tempSensors [ sensorIndex ].zeroDegreeResistance, tempSensors [ sensorIndex ].conversionCoeff ); break; case TEMPSENSORS_FPGA_BOARD_SENSOR: // Temperature(C) = ((ADC x 503.975) / 4096) - 273.15 // The value of 503.975/4096 has been calculated and stored in the conversion coefficient variable of the structure temperature = ( avgADCReads * tempSensors[ sensorIndex ].conversionCoeff ) - CELSIUS_TO_KELVIN_CONVERSION; break; case TEMPSENSORS_LOAD_CELL_A1_B1: case TEMPSENSORS_LOAD_CELL_A2_B2: case TEMPSENSORS_INTERNAL_TRO_RTD: case TEMPSENSORS_INTERNAL_TDI_RTD: case TEMPSENSORS_INTERNAL_THD_RTD: case TEMPSENSORS_INTERNAL_COND_TEMP_SENSOR: // Temperature(C) = ((ADC - 0x800000)/13584) - 272.5 // The value 1/13584 has been calculated and stored in the conversion coefficient variable of the structure temperature = ( ( avgADCReads - ADC_BOARD_TEMP_SENSORS_CONST ) * tempSensors[ sensorIndex ].conversionCoeff ) - ADC_BOARD_TEMP_SENSORS_CONVERSION_CONST; break; case TEMPSENSORS_BAROMETRIC_TEMP_SENSOR: { S32 baroTempSensorsDiff = (S32)avgADCReads - ( baroConvConsts.refTemperature * TWO_TO_POWER_OF_8 ); S64 differenceTimesCoefficient = (S64)baroTempSensorsDiff * (S64)baroConvConsts.temperatureCoeff; S64 baroSnsrTemperature = BARO_SENSOR_REFERENCE_TEMP_C + ( differenceTimesCoefficient / TWO_TO_POWER_OF_23 ); temperature = (F32)( baroSnsrTemperature / 100.0F ); tempSensors[ sensorIndex ].baroTempSnsrDiff = baroTempSensorsDiff; } break; default: // Wrong sensor was called, raise an alarm SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_TEMPERATURE_SENSOR_SELECTED, sensorIndex ); // Wrong sensor, return temperature to be -1 temperature = -1.0F; break; } getCalibrationAppliedTemperatureValue( sensorIndex, &temperature ); // Update the temperature tempSensors[ sensorIndex ].temperatureValues.data = temperature; } /*********************************************************************//** * @brief * The handleExecStart function waits for a period of time and switches to * the state that reads the ADC values from FPGA. * @details Inputs: elapsedTime * @details Outputs: elapsedTime, baroCoeffsWaitToRcvStartTime * @return the next state of the state machine *************************************************************************/ static TEMPSENSORS_EXEC_STATES_T handleExecStart( void ) { TEMPSENSORS_EXEC_STATES_T state = TEMPSENSORS_EXEC_STATE_START; if ( 0 == elapsedTime ) { elapsedTime = getMSTimerCount(); } // A delay to let FPGA to boot up else if ( TRUE == didTimeout( elapsedTime, ADC_FPGA_READ_DELAY ) ) { elapsedTime = 0; baroConvConsts.waitForCoeffStartTimeMS = getMSTimerCount(); state = TEMPSENSORS_EXEC_STATE_GET_ADC_VALUES; } return state; } /*********************************************************************//** * @brief * The handleExecGetADCValues function reads the ADC values from FPGA and * at the specified time intervals and calls other functions to calculate * the internal temperature of the heaters. * @details Inputs: internalHeatersConversionTimer * @details Outputs: internalHeatersConversionTimer * @return the next state of the state machine *************************************************************************/ static TEMPSENSORS_EXEC_STATES_T handleExecGetADCValues( void ) { U32 readCount = 0; readCount = (U32)getFPGARTDReadCount(); checkFPGAPersistentAlarms( FPGA_PERS_ERROR_TWO_WIRE_ADC_TEMP_SENSORS, readCount ); processTempSnsrsADCRead( TEMPSENSORS_INLET_PRIMARY_HEATER, getFPGATPiTemp() ); processTempSnsrsADCRead( TEMPSENSORS_OUTLET_PRIMARY_HEATER, getFPGATPoTemp() ); processTempSnsrsADCRead( TEMPSENSORS_CONDUCTIVITY_SENSOR_1, getFPGACD1Temp() ); processTempSnsrsADCRead( TEMPSENSORS_CONDUCTIVITY_SENSOR_2, getFPGACD2Temp() ); processTempSnsrsADCRead( TEMPSENSORS_INTERNAL_COND_TEMP_SENSOR, getFPGACondSnsrInternalTemp() ); if ( getCurrentOperationMode() != DG_MODE_INIT ) { readCount = (U32)getFPGATHdReadCount(); checkFPGAPersistentAlarms( FPGA_PERS_ERROR_THD_ADC_TEMP_SENSORS, readCount ); processTempSnsrsADCRead( TEMPSENSORS_HEAT_DISINFECT, getFPGATHdTemp() ); // Make sure the baro sensor coefficients are not corrupted checkBaroSensorCRC(); processTempSnsrsADCRead( TEMPSENSORS_INTERNAL_THD_RTD, getFPGATHdInternalTemp() ); baroConvConsts.refTemperature = getFPGABaroReferenceTemperature(); baroConvConsts.temperatureCoeff = getFPGABaroTempCoeffOfTemperature(); readCount = getFPGABaroReadCount(); checkFPGAPersistentAlarms( FPGA_PERS_ERROR_BARO_SENSOR, readCount ); processTempSnsrsADCRead( TEMPSENSORS_BAROMETRIC_TEMP_SENSOR, getFPGABaroTemperature() ); } readCount = (U32)getFPGATRoReadCount(); checkFPGAPersistentAlarms( FPGA_PERS_ERROR_TRO_ADC_TEMP_SENSORS, readCount ); processTempSnsrsADCRead( TEMPSENSORS_OUTLET_REDUNDANT, getFPGATRoTemp() ); processTempSnsrsADCRead( TEMPSENSORS_INTERNAL_TRO_RTD, getFPGATRoInternalTemp() ); readCount = (U32)getFPGATDiReadCount(); checkFPGAPersistentAlarms( FPGA_PERS_ERROR_TDI_ADC_TEMP_SENSORS, readCount ); processTempSnsrsADCRead( TEMPSENSORS_INLET_DIALYSATE, getFPGATDiTemp() ); processTempSnsrsADCRead( TEMPSENSORS_INTERNAL_TDI_RTD, getFPGATDiInternalTemp() ); // The heaters' temperature sensors have read and error counts but the heaters' internal sensors are only updated for information // and no alarm shall be raised on them including the read and error counts processHtrsTempSnsrsADCRead( TEMPSENSORS_PRIMARY_HEATER_THERMO_COUPLE, getFPGAPrimaryHeaterTemp() ); processHtrsTempSnsrsADCRead( TEMPSENSORS_PRIMARY_HEATER_COLD_JUNCTION, getFPGAPrimaryColdJunctionTemp() ); processHtrsTempSnsrsADCRead( TEMPSENSORS_TRIMMER_HEATER_THERMO_COUPLE, getFPGATrimmerHeaterTemp() ); processHtrsTempSnsrsADCRead( TEMPSENSORS_TRIMMER_HEATER_COLD_JUNCTION, getFPGATrimmerColdJunctionTemp() ); // The FPGA board sensor does not have read and error count. // The load cells' temperature sensors are not read and a constant value is reported to firmware by FPGA processTempSnsrsADCRead( TEMPSENSORS_FPGA_BOARD_SENSOR, getFPGABoardTemp() ); processTempSnsrsADCRead( TEMPSENSORS_LOAD_CELL_A1_B1, getFPGALoadCellsA1B1Temp() ); processTempSnsrsADCRead( TEMPSENSORS_LOAD_CELL_A2_B2, getFPGALoadCellsA2B2Temp() ); // Check if time has elapsed to calculate the internal temperature of the heaters if ( ++internalHeatersConversionTimer >= HEATERS_INTERNAL_TEMPERTURE_CALCULATION_INTERVAL ) { getHeaterInternalTemp( TEMPSENSORS_PRIMARY_HEATER_THERMO_COUPLE, TEMPSENSORS_PRIMARY_HEATER_COLD_JUNCTION ); getHeaterInternalTemp( TEMPSENSORS_TRIMMER_HEATER_THERMO_COUPLE, TEMPSENSORS_TRIMMER_HEATER_COLD_JUNCTION ); internalHeatersConversionTimer = 0; } return TEMPSENSORS_EXEC_STATE_GET_ADC_VALUES; } /*********************************************************************//** * @brief * The publishTemperatureSensorsData function broadcasts the temperature * sensors data at the publication interval. * @details Inputs: dataPublicationTimerCounter, tempValuesForPublication * @details Outputs: dataPublicationTimerCounter, tempValuesForPublication * @return none *************************************************************************/ static void publishTemperatureSensorsData( void ) { if ( ++dataPublicationTimerCounter >= getU32OverrideValue( &tempSensorsPublishInterval ) ) { TEMPERATURE_SENSORS_DATA_T data; data.inletPrimaryHeater = getTemperatureValue( TEMPSENSORS_INLET_PRIMARY_HEATER ); data.heatDisinfect = getTemperatureValue( TEMPSENSORS_HEAT_DISINFECT ); data.outletPrimaryHeater = getTemperatureValue( TEMPSENSORS_OUTLET_PRIMARY_HEATER ); data.conductivitySensor1 = getTemperatureValue( TEMPSENSORS_CONDUCTIVITY_SENSOR_1 ); data.conductivitySensor2 = getTemperatureValue( TEMPSENSORS_CONDUCTIVITY_SENSOR_2 ); data.outletRedundant = getTemperatureValue( TEMPSENSORS_OUTLET_REDUNDANT ); data.inletDialysate = getTemperatureValue( TEMPSENSORS_INLET_DIALYSATE ); data.primaryHeaterThermocouple = getTemperatureValue( TEMPSENSORS_PRIMARY_HEATER_THERMO_COUPLE ); data.trimmerHeaterThermocouple = getTemperatureValue( TEMPSENSORS_TRIMMER_HEATER_THERMO_COUPLE ); data.priamyHeaterColdjunction = getTemperatureValue( TEMPSENSORS_PRIMARY_HEATER_COLD_JUNCTION ); data.trimmerHeaterColdjunction = getTemperatureValue( TEMPSENSORS_TRIMMER_HEATER_COLD_JUNCTION ); data.primaryHeaterInternal = getTemperatureValue( TEMPSENSORS_PRIMARY_HEATER_INTERNAL ); data.trimmerHeaterInternal = getTemperatureValue( TEMPSENSORS_TRIMMER_HEATER_INTERNAL ); data.fpgaBoard = getTemperatureValue( TEMPSENSORS_FPGA_BOARD_SENSOR ); data.loadCellA1B1 = getTemperatureValue( TEMPSENSORS_LOAD_CELL_A1_B1 ); data.loadCellA2B2 = getTemperatureValue( TEMPSENSORS_LOAD_CELL_A2_B2 ); data.internalTHDORTD = getTemperatureValue( TEMPSENSORS_INTERNAL_TRO_RTD ); data.internalTDIRTD = getTemperatureValue( TEMPSENSORS_INTERNAL_TDI_RTD ); 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; } } /*********************************************************************//** * @brief * The monitorTemperatureSnsrs function monitors the temperature sensors' * temperature value and raises an alarm if any of them are out of range * for more than the specified time. * @details Inputs: tempSensors * @details Outputs: tempSensors * @return none *************************************************************************/ static void monitorTemperatureSenors( void ) { #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_TEMPERATURE_SENSORS_ALARM ) != SW_CONFIG_ENABLE_VALUE ) #endif { TEMPERATURE_SENSORS_T sensorId; TEMPERATURE_SENSORS_T sensorInAlarm = TEMPSENSORS_FIRST; F32 temperature = 0.0F; BOOL isTemperatureOutOfRange = FALSE; F32 alarmTemperature = 0.0F; for ( sensorId = TEMPSENSORS_FIRST; sensorId < NUM_OF_TEMPERATURE_SENSORS; sensorId++ ) { switch ( sensorId ) { case TEMPSENSORS_INLET_PRIMARY_HEATER: case TEMPSENSORS_HEAT_DISINFECT: case TEMPSENSORS_OUTLET_PRIMARY_HEATER: case TEMPSENSORS_CONDUCTIVITY_SENSOR_1: case TEMPSENSORS_CONDUCTIVITY_SENSOR_2: case TEMPSENSORS_OUTLET_REDUNDANT: case TEMPSENSORS_INLET_DIALYSATE: case TEMPSENSORS_FPGA_BOARD_SENSOR: case TEMPSENSORS_BAROMETRIC_TEMP_SENSOR: // All other temperature sensors are only broadcast for logging/dialin purposes. temperature = getTemperatureValue( sensorId ); // Check both temperature and to be in range if ( ( ( temperature < TEMP_SENSORS_MIN_ALLOWED_DEGREE_C ) || ( temperature > tempSensors[ sensorId ].maxAllowedTemp ) ) && ( getCurrentOperationMode() != DG_MODE_INIT ) ) { isTemperatureOutOfRange |= TRUE; sensorInAlarm = sensorId; alarmTemperature = temperature; } break; default: // Ignore the rest of the sensors break; } } checkPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSOR_OUT_OF_RANGE, isTemperatureOutOfRange, sensorInAlarm, alarmTemperature ); } } /*********************************************************************//** * @brief * The adjustTemperatureSensorsRefResistance function adjusts the temperature * sensors V3 or DVT reference resistance values. * @details Inputs: tempSensors * @details Outputs: tempSensors * @return none *************************************************************************/ static void adjustTemperatureSensorsRefResistance( void ) { // The defaults are DVT values U32 primaryAndCondSensorsRefResistance = PRIMARY_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE; U32 externalTempSesnorsRefResitance = TRIMMER_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE; #ifndef _RELEASE_ if ( ( HW_CONFIG_BETA == getHardwareConfigStatus() ) && ( getCurrentOperationMode() != DG_MODE_INIT ) ) { primaryAndCondSensorsRefResistance = PRIMARY_HEATER_EXT_TEMP_SENSORS_V3_REF_RESISTANCE; externalTempSesnorsRefResitance = TRIMMER_HEATER_EXT_TEMP_SENSORS_V3_REF_RESISTANCE; } #endif tempSensors[ TEMPSENSORS_INLET_PRIMARY_HEATER ].refResistance = primaryAndCondSensorsRefResistance; tempSensors[ TEMPSENSORS_OUTLET_PRIMARY_HEATER ].refResistance = primaryAndCondSensorsRefResistance; tempSensors[ TEMPSENSORS_CONDUCTIVITY_SENSOR_1 ].refResistance = primaryAndCondSensorsRefResistance; tempSensors[ TEMPSENSORS_CONDUCTIVITY_SENSOR_2 ].refResistance = primaryAndCondSensorsRefResistance; tempSensors[ TEMPSENSORS_HEAT_DISINFECT ].refResistance = externalTempSesnorsRefResitance; tempSensors[ TEMPSENSORS_OUTLET_REDUNDANT ].refResistance = externalTempSesnorsRefResitance; tempSensors[ TEMPSENSORS_INLET_DIALYSATE ].refResistance = externalTempSesnorsRefResitance; } /*********************************************************************//** * @brief * The checkBaroSensorCRC function gets all the barometric sensor coefficients * and calls crc4 function to calculate the CRC of the coefficients and compares * them to the provided CRC by the manufacturer. * @details Inputs: hasBaroCoeffsBeenChecked * @details Outputs: hasBaroCoeffsBeenChecked * @return none *************************************************************************/ static void checkBaroSensorCRC( void ) { // The baro CRC is the last 4 bits of the 16-bit manufacturing register U32 baroCRC = (U32)getFPGABaroCoeffsCRC(); BOOL hasCRCChanged = ( baroCRC != getU32OverrideValue( &baroConvConsts.coeffsCRC ) ? TRUE : FALSE ); // Once FPGA is ready get the barometric sensor's temperature conversion constants if ( ( TRUE == hasCRCChanged ) || ( TRUE == baroConvConsts.hasCRCCheckBeenRequested ) ) { U32 calculatedCRC; BARO_SENSORS_COEFFS_T baroCoeffs; baroCoeffs.mfgInfo = getFPGABaroMfgInfo(); baroCoeffs.pressSensitivity = getFPGABaroPressureSensitivity(); baroCoeffs.pressOffset = getFPGABaroPressureOffset(); baroCoeffs.tempCoeffOfPressSens = getFPGABaroTempCoeffOfPressSensitvity(); baroCoeffs.tempCoeffPressOffset = getFPGABaroTempCoeffOfPressOffset(); baroCoeffs.referenceTemp = getFPGABaroReferenceTemperature(); baroCoeffs.tempCoeffOfTemp = getFPGABaroTempCoeffOfTemperature(); baroCoeffs.crc = 0x00; // Keep zero for the seventh byte in CRC4 formula calculatedCRC = (U32)crc4( (U16*)&baroCoeffs, sizeof( baroCoeffs ) ); baroConvConsts.coeffsCRC.data = baroCRC; baroConvConsts.hasCRCBeenChecked = TRUE; baroConvConsts.hasCRCCheckBeenRequested = FALSE; SEND_EVENT_WITH_2_U32_DATA( DG_EVENT_BARO_SENSOR_MFG_CRC_CHECK, calculatedCRC, baroCRC ) if ( calculatedCRC != baroCRC ) { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_BAROMETRIC_SENSOR_COEFFS_BAD_CRC, calculatedCRC, baroCRC ); } } else if ( ( TRUE == didTimeout( baroConvConsts.waitForCoeffStartTimeMS, BARO_SENSOR_WAIT_FOR_COEFF_TIME_OUT_MS ) ) && ( FALSE == baroConvConsts.hasCRCBeenChecked ) ) { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_BAROMETRIC_SENSOR_COEFFS_BAD_CRC, 0, baroCRC ); } } /*********************************************************************//** * @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; } } } /*********************************************************************//** * @brief * The getCalibrationAppliedTemperatureValue function applies the calibration * values to the provided temperature value * @details Inputs: tempSensorCalRecord * @details Outputs: none * @param sensorIndex Temperature sensor index * @param temperature pointer to the calculated temperature value * @return none *************************************************************************/ static void getCalibrationAppliedTemperatureValue( U32 sesnorIndex, F32* temperature ) { CAL_DATA_DG_TEMP_SENSORS_T calId; F32 tempTemperature = *temperature; switch( sesnorIndex ) { case TEMPSENSORS_INLET_PRIMARY_HEATER: calId = CAL_DATA_INLET_PRIMARY_HEATER_TEMP; break; case TEMPSENSORS_OUTLET_PRIMARY_HEATER: calId = CAL_DATA_OUTLET_PRIMARY_HEATER_TEMP; break; case TEMPSENSORS_CONDUCTIVITY_SENSOR_1: calId = CAL_DATA_COND_SENSOR_1_TEMP; break; case TEMPSENSORS_CONDUCTIVITY_SENSOR_2: calId = CAL_DATA_COND_SENSOR_2_TEMP; break; case TEMPSENSORS_OUTLET_REDUNDANT: calId = CAL_DATA_OUTLET_REDUNDANT_TEMP; break; case TEMPSENSORS_INLET_DIALYSATE: calId = CAL_DATA_INLET_DIALYSATE_TEMP; break; case TEMPSENSORS_HEAT_DISINFECT: calId = CAL_DATA_HEAT_DISINFECT_TEMP; break; case TEMPSENSORS_BAROMETRIC_TEMP_SENSOR: calId = CAL_DATA_BARMOTERIC_TEMP; break; default: // Set the calibration temperature value as num of meaning calibration is not needed for the provided sensor calId = NUM_OF_CAL_DATA_TEMP_SENSORS; break; } if ( calId != NUM_OF_CAL_DATA_TEMP_SENSORS ) { *temperature = pow( tempTemperature, 4 ) * tempSensorCalRecord.tempSensors[ calId ].fourthOrderCoeff + pow( tempTemperature, 3 ) * tempSensorCalRecord.tempSensors[ calId ].thirdOrderCoeff + pow( tempTemperature, 2 ) * tempSensorCalRecord.tempSensors[ calId ].secondOrderCoeff + tempTemperature * tempSensorCalRecord.tempSensors[ calId ].gain + tempSensorCalRecord.tempSensors[ calId ].offset; } } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testSetMeasuredTemperatureOverride function sets the override value * for a specific temperature sensor. * @details Inputs: tempSensors * @details Outputs: tempSensors * @param sensorIndex temperature sensor index * @param temperature temperature value to override if testing is activated * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetMeasuredTemperatureOverride( U32 sensorIndex, F32 temperature ) { BOOL result = FALSE; if ( sensorIndex < NUM_OF_TEMPERATURE_SENSORS ) { if ( TRUE == isTestingActivated() ) { result = TRUE; tempSensors[ sensorIndex ].temperatureValues.ovData = temperature; tempSensors[ sensorIndex ].temperatureValues.override = OVERRIDE_KEY; } } return result; } /*********************************************************************//** * @brief * The testSetMeasuredTemperatureOverride function resets the override * value of a specified temperature sensor. * @details Inputs: tempSensors * @details Outputs: tempSensors * @param sensorIndex temperature sensor index * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testResetMeasuredTemperatureOverride( U32 sensorIndex ) { BOOL result = FALSE; if ( sensorIndex < NUM_OF_TEMPERATURE_SENSORS ) { if ( TRUE == isTestingActivated() ) { result = TRUE; tempSensors[ sensorIndex ].temperatureValues.override = OVERRIDE_RESET; tempSensors[ sensorIndex ].temperatureValues.ovData = tempSensors[ sensorIndex ].temperatureValues.ovInitData; } } return result; } /*********************************************************************//** * @brief * The testSetTemperatureSensorsPublishIntervalOverride function overrides * the temperature sensors publish data interval. * @details Inputs: tempSensorsPublishInterval * @details Outputs: tempSensorsPublishInterval * @param value sensors data broadcast interval (in ms) to override * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetTemperatureSensorsPublishIntervalOverride( U32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { U32 interval = value / TASK_PRIORITY_INTERVAL; result = TRUE; tempSensorsPublishInterval.ovData = interval; tempSensorsPublishInterval.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetTemperatureSensorsPublishIntervalOverride function resets * the override value of temperature sensors publish data interval. * @details Inputs: tempSensorsPublishInterval * @details Outputs: tempSensorsPublishInterval * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testResetTemperatureSensorsPublishIntervalOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; tempSensorsPublishInterval.override = OVERRIDE_RESET; tempSensorsPublishInterval.ovData = tempSensorsPublishInterval.ovInitData; } return result; } /**@}*/