Index: firmware/App/Controllers/TemperatureSensors.c =================================================================== diff -u -ref5ef16518466c92687b869cabfa16eaf3365dc0 -r2496e9225fa1b2c627d625def02515a0f0dd5793 --- firmware/App/Controllers/TemperatureSensors.c (.../TemperatureSensors.c) (revision ef5ef16518466c92687b869cabfa16eaf3365dc0) +++ firmware/App/Controllers/TemperatureSensors.c (.../TemperatureSensors.c) (revision 2496e9225fa1b2c627d625def02515a0f0dd5793) @@ -1,631 +1,631 @@ -/**********************************************************************//** - * - * Copyright (c) 2019-2020 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 - * - * @date 7-Apr-2020 - * @author Dara Navaei - * - * @brief DG temperature sensors controller - * - **************************************************************************/ -#include // For temperature calculation - -#include "TemperatureSensors.h" -#include "FPGA.h" - -// TODO: For testing only REMOVE -#include "Timers.h" -// TODO: For testing only REMOVE - -// Private variables - -#define PRIMARY_HEATER_EXT_TEMP_SENSORS_GAIN 16U ///< Primary heater external temperature sensors gain -#define PRIMARY_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE 19600U ///< 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 COND_SENSORS_TEMP_SENSOR_GAIN 16U ///< Conductivity sensor gain -#define COND_SENSORS_TEMP_SENSOR_REF_RESISTANCE 19600U ///< Conductivity sensor reference resistance -#define COND_SENSORS_TEMP_SENSOR_0_DEGREE_RESISTANCE 1000U ///< Conductivity sensor zero degree resistance - -#define TRIMMER_HEATER_EXT_TEMP_SENSORS_GAIN 32U ///< Trimmer heater external temperature sensors gain -#define TRIMMER_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE 5110U ///< 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 HEATERS_INTERNAL_ADC_TO_TEMP_CONVERSION_COEFF 0.0625 ///< Heaters internal temperature sensors ADC to temperature conversion coefficient - -#define TEMP_SENSORS_ADC_BITS 24U ///< External temperature sensors ADC bits -#define TEMP_SENSORS_ADC_MAX_COUNT (pow(2,TEMP_SENSORS_ADC_BITS)) ///< Temperature sensors max ADC count - -#define TEMP_EQUATION_COEFF_A (3.9083 * pow(10,-3)) ///< ADC to temperature conversion coefficient A -#define TEMP_EQUATION_COEFF_B (-5.775 * pow(10,-7)) ///< ADC to temperature conversion coefficient B - -#define MAX_NUM_OF_RAW_ADC_SAMPLES 20U ///< Number of ADC reads for moving average calculations - -#define ADC_READ_FIRST_READ_INDEX 0U ///< ADC array first ADC read index - -#define ADC_READ_NEXT_INDEX_INDEX 0U ///< ADC array next insertion index -#define ADC_READ_RUNNING_SUM_INDEX 1U ///< ADC array running sum index - -#define ADC_READ_GAIN_INDEX 0U ///< ADC array gain index -#define ADC_READ_REF_RESISTANCE_INDEX 1U ///< ADC array reference resistances index -#define ADC_READ_0_DEG_RESISTANCE_INDEX 2U ///< ADC array zero degree resistance index - -#define READ_AND_ERROR_PREV_FPGA_COUNT_INDEX 0U -#define READ_AND_ERROR_INTERNAL_READ_COUNT_INDEX 1U -#define READ_AND_ERROR_INTERNAL_ERROR_COUNT_INDEX 2U -#define READ_AND_ERROR_PREV_FPGA_ERROR_INDEX 3U -#define NUM_OF_READ_AND_ERROR_ARRAY_COLUMNS 4U - -#define MAX_ALLOWED_TEMP_DELTA_BETWEEN_SENSORS 2U ///< Maximum allowed temperature delta between sensors - -#define NUM_OF_RUNNING_SUM_AND_INDEX_ARRAY_COLUMNS 2U ///< Number of columns in running sum and index array -#define NUM_OF_TEMP_SENSORS_CONSTANTS_ARRAY_COLUMNS 3U ///< Number of columns in temperature sensors constants - -#define MAX_ALLOWED_UNCHANGED_ADC_READS 4U ///< Maximum number of times that the read of a sensor cannot change - -#define EXTERNAL_TEMP_SENSORS_ERROR_VALUE 0x80 -#define HEATERS_INTERNAL_TEMP_SENSOR_FAULT 0x01 -#define MASK_OFF_U32_MSB 0x00FFFFFF - -/// Temperature sensor self test states -typedef enum tempSensors_Self_Test_States -{ - TEMPSENSORS_SELF_TEST_START = 0, ///< Temperature sensors self test start - TEMPSENSORS_SELF_TEST_ADC_CHECK, ///< Temperature sensors self ADC check - TEMPSENSORS_SELF_TEST_CONSISTENCY_CHECK, ///< Temperature sensors self test consistency check - TEMPSENSORS_SELF_TEST_COMPLETE, ///< Temperature sensors self test complete - NUM_OF_TEMPSENSORS_SELF_TEST_STATES ///< Total number of self test states -} TEMPSENSORS_SELF_TEST_STATES_T; - -/// 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; - -/// FPGA error and read counts -typedef struct -{ - U08 RTDErrorCount; ///< RTD error count (include all 4 conductivity and temperature sensors) - U08 RTDReadCount; ///< RTD read count (include all 4 conductivity and temperature sensors) - U08 TRoErrorCount; ///< THDo (outlet redundant temperature sensor) error count - U08 TRoReadCount; ///< THDo (outlet redundant temperature sensor) read count - U08 TDiErrorCount; ///< TDi (inlet dialysate) temperature sensor error count - U08 TDiReadCount; ///< TDi (inlet dialysate) temperature sensor read count - U08 primaryHeaterFlags; ///< Primary heater internal temperature sensor error flags - U08 primaryHeaterReadCount; ///< Primary heater internal temperature sensor read count - U08 trimmerHeaterFlags; ///< Trimmer heater internal temperature sensor error flags - U08 trimmerHeaterReadCount; ///< Trimmer heater internal temperature sensor read count -} FPGA_READ_AND_ERROR_COUNTS_T; // TODO REmove - -static SELF_TEST_STATUS_T tempSensorsSelfTestResult; ///< Self test result of the TemperatureSensors module -static TEMPSENSORS_SELF_TEST_STATES_T tempSensorsSelfTestState; ///< TemperatureSensor self test state -static TEMPSENSORS_EXEC_STATES_T tempSensorsExecState; ///< TemperatureSensor exec state -static U32 sampleCount; ///< Initial ADC read index until the array if filled up for the first time -static U32 rawADCReads [ NUM_OF_TEMPERATURE_SENSORS ] ///< Raw ADC reads array - [ MAX_NUM_OF_RAW_ADC_SAMPLES ]; -static U32 runningSumAndIndex [ NUM_OF_TEMPERATURE_SENSORS ] ///< Running sum and next ADC index array - [ NUM_OF_RUNNING_SUM_AND_INDEX_ARRAY_COLUMNS ]; -static U32 tempSensorsConstants [ NUM_OF_TEMPERATURE_SENSORS ] ///< Temperature sensors constants - [ NUM_OF_TEMP_SENSORS_CONSTANTS_ARRAY_COLUMNS ]; -static F32 avgADCReads [ NUM_OF_TEMPERATURE_SENSORS ]; //TODO remove ///< Temperature sensors averaged ADC values -static F32 temperatureValues [ NUM_OF_TEMPERATURE_SENSORS ]; -static U32 readAndErrorCounts [ NUM_OF_TEMPERATURE_SENSORS ] [ NUM_OF_READ_AND_ERROR_ARRAY_COLUMNS ]; - -// Private functions prototypes - -static TEMPSENSORS_SELF_TEST_STATES_T handleSelfTestStart ( void ); -static TEMPSENSORS_SELF_TEST_STATES_T handleSelfTestADCCheck ( void ); -static TEMPSENSORS_SELF_TEST_STATES_T handleSelfTestConsistencyCheck ( void ); - -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 ); -static void processADCRead ( U32 sensorIndex, U32 adc, U32 fpgaError, U32 fpgaCount ); - -// Public functions - -/************************************************************************* - * @brief initTemperatureSensors - * The initTemperatureSensors function initializes the module - * @details - * Inputs : none - * Outputs : none - * @param none - * @return none - *************************************************************************/ -void initTemperatureSensors ( void ) -{ - U08 i; - tempSensorsSelfTestResult = SELF_TEST_STATUS_IN_PROGRESS; - tempSensorsSelfTestState = TEMPSENSORS_SELF_TEST_START; - tempSensorsExecState = TEMPSENSORS_EXEC_STATE_START; - sampleCount = 0; - - // Initialize TPi and TPo constants - for ( i = TEMPSENSORS_INLET_PRIMARY_HEATER_TEMP_SENSOR; i < TEMPSENSORS_CONDUCTIVITY_SENSOR_1_TEMP_SENSOR; i++ ) - { - tempSensorsConstants [ i ] [ ADC_READ_GAIN_INDEX ] = PRIMARY_HEATER_EXT_TEMP_SENSORS_GAIN; - tempSensorsConstants [ i ] [ ADC_READ_REF_RESISTANCE_INDEX ] = PRIMARY_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE; - tempSensorsConstants [ i ] [ ADC_READ_0_DEG_RESISTANCE_INDEX ] = PRIMARY_HEATER_EXT_TEMP_SENSORS_0_DEGREE_RESISTANCE; - } - // Initialize TD1 and TD2 constants - for ( i = TEMPSENSORS_CONDUCTIVITY_SENSOR_1_TEMP_SENSOR; i < TEMPSENSORS_OUTLET_REDUNDANCY_TEMP_SENSOR; i++ ) - { - tempSensorsConstants [ i ] [ ADC_READ_GAIN_INDEX ] = COND_SENSORS_TEMP_SENSOR_GAIN; - tempSensorsConstants [ i ] [ ADC_READ_REF_RESISTANCE_INDEX ] = COND_SENSORS_TEMP_SENSOR_REF_RESISTANCE; - tempSensorsConstants [ i ] [ ADC_READ_0_DEG_RESISTANCE_INDEX ] = COND_SENSORS_TEMP_SENSOR_0_DEGREE_RESISTANCE; - } - // Initialize TRo and TDi constants - for ( i = TEMPSENSORS_OUTLET_REDUNDANCY_TEMP_SENSOR; i < TEMPSENSORS_PRIMARY_HEATER_INTERNAL_TEMP_SENSOR; i++ ) - { - tempSensorsConstants [ i ] [ ADC_READ_GAIN_INDEX ] = TRIMMER_HEATER_EXT_TEMP_SENSORS_GAIN; - tempSensorsConstants [ i ] [ ADC_READ_REF_RESISTANCE_INDEX ] = TRIMMER_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE; - tempSensorsConstants [ i ] [ ADC_READ_0_DEG_RESISTANCE_INDEX ] = TRIMMER_HEATER_EXT_TEMP_SENSORS_0_DEGREE_RESISTANCE; - } - - // Initialize primary heater internal temperature sensor - // The heaters do not need gain, reference resistance, and zero degree resistance - tempSensorsConstants [ TEMPSENSORS_PRIMARY_HEATER_INTERNAL_TEMP_SENSOR ] [ ADC_READ_GAIN_INDEX ] = 0; - tempSensorsConstants [ TEMPSENSORS_PRIMARY_HEATER_INTERNAL_TEMP_SENSOR ] [ ADC_READ_REF_RESISTANCE_INDEX ] = 0; - tempSensorsConstants [ TEMPSENSORS_PRIMARY_HEATER_INTERNAL_TEMP_SENSOR ] [ ADC_READ_0_DEG_RESISTANCE_INDEX ] = 0; - // Initialize trimmer heater internal temperature sensor - tempSensorsConstants [ TEMPSENSORS_TRIMMER_HEATER_INTERNAL_TEMP_SESNOR ] [ ADC_READ_GAIN_INDEX ] = 0; - tempSensorsConstants [ TEMPSENSORS_TRIMMER_HEATER_INTERNAL_TEMP_SESNOR ] [ ADC_READ_REF_RESISTANCE_INDEX ] = 0; - tempSensorsConstants [ TEMPSENSORS_TRIMMER_HEATER_INTERNAL_TEMP_SESNOR ] [ ADC_READ_0_DEG_RESISTANCE_INDEX ] = 0; -} -/************************************************************************* - * @brief execTemperatureSensorsSelfTest - * The execTemperatureSensorsSelfTest function runs the TemperatureSensors - * POST during the self test - * @details - * Inputs : none - * Outputs : SELF_TEST_STATUS_T - * @param none - * @return SELF_TEST_STATUS_T - *************************************************************************/ -SELF_TEST_STATUS_T execTemperatureSensorsSelfTest ( void ) -{ - switch ( tempSensorsSelfTestState ) - { - case TEMPSENSORS_SELF_TEST_START: - - tempSensorsSelfTestState = handleSelfTestStart(); - break; - - case TEMPSENSORS_SELF_TEST_ADC_CHECK: - - tempSensorsSelfTestState = handleSelfTestADCCheck(); - break; - - case TEMPSENSORS_SELF_TEST_CONSISTENCY_CHECK: - - tempSensorsSelfTestState = handleSelfTestConsistencyCheck(); - break; - - case TEMPSENSORS_SELF_TEST_COMPLETE: - - // Done with self test, do nothing - break; - - default: - - SET_ALARM_WITH_2_U32_DATA ( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_TEMPERATURE_SENSORS_INVALID_SELF_TEST_STATE, - tempSensorsSelfTestState ); - tempSensorsSelfTestState = TEMPSENSORS_SELF_TEST_COMPLETE; - break; - } - - return tempSensorsSelfTestResult; -} -/************************************************************************* - * @brief execTemperatureSensors - * The execTemperatureSensors function runs the TemperatureSensors main - * tasks - * @details - * Inputs : none - * Outputs : none - * @param none - * @return none - *************************************************************************/ -void execTemperatureSensors ( void ) -{ - // read the sensors all the time - switch ( tempSensorsExecState ) - { - case TEMPSENSORS_SELF_TEST_START: - - tempSensorsExecState = handleExecStart(); - break; - - case TEMPSENSORS_EXEC_STATE_GET_ADC_VALUES: - - tempSensorsExecState = handleExecGetADCValues(); - break; - - default: - - SET_ALARM_WITH_2_U32_DATA ( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_TEMPERATURE_SENSORS_EXEC_INVALID_STATE, - tempSensorsExecState ); - tempSensorsExecState = TEMPSENSORS_EXEC_STATE_GET_ADC_VALUES; - break; - } -} -/************************************************************************* - * @brief getTemperatureValue - * The getTemperatureValue function gets the enum of the requested - * temperature sensor, converts the ADC of it to temperature in degree C - * and returns the temperature - * @details - * Inputs : TEMPERATURE_SENSORS_T (sensor) - * Outputs : F32 (temperature in deg C) - * @param none - * @return F32 (temperature in deg C) - *************************************************************************/ -F32 getTemperatureValue ( TEMPERATURE_SENSORS_T sensor ) -{ - F32 temperature; - switch ( sensor ) - { - case TEMPSENSORS_INLET_PRIMARY_HEATER_TEMP_SENSOR: - - temperature = temperatureValues [ TEMPSENSORS_INLET_PRIMARY_HEATER_TEMP_SENSOR ]; - break; - - case TEMPSENSORS_OUTLET_PRIMARY_HEATER_TEMP_SENSOR: - - temperature = temperatureValues [ TEMPSENSORS_OUTLET_PRIMARY_HEATER_TEMP_SENSOR ]; - break; - - case TEMPSENSORS_CONDUCTIVITY_SENSOR_1_TEMP_SENSOR: - - temperature = temperatureValues [ TEMPSENSORS_CONDUCTIVITY_SENSOR_1_TEMP_SENSOR ]; - break; - - case TEMPSENSORS_CONDUCTIVITY_SENSOR_2_TEMP_SENSOR: - - temperature = temperatureValues [ TEMPSENSORS_CONDUCTIVITY_SENSOR_2_TEMP_SENSOR ]; - break; - - case TEMPSENSORS_OUTLET_REDUNDANCY_TEMP_SENSOR: - - temperature = temperatureValues [ TEMPSENSORS_OUTLET_REDUNDANCY_TEMP_SENSOR ]; - break; - - case TEMPSENSORS_INLET_DIALYSATE_TEMP_SENSOR: - - temperature = temperatureValues [ TEMPSENSORS_INLET_DIALYSATE_TEMP_SENSOR ]; - break; - - case TEMPSENSORS_PRIMARY_HEATER_INTERNAL_TEMP_SENSOR: - - temperature = temperatureValues [ TEMPSENSORS_PRIMARY_HEATER_INTERNAL_TEMP_SENSOR ]; - break; - - case TEMPSENSORS_TRIMMER_HEATER_INTERNAL_TEMP_SESNOR: - - temperature = temperatureValues [ TEMPSENSORS_TRIMMER_HEATER_INTERNAL_TEMP_SESNOR ]; - break; - - default: - // ToDo: Warning? - break; - } - - return temperature; -} - -// Private functions - -/************************************************************************* - * @brief getADC2TempConversion - * The getADC2TempConversion function calculates the temperature from - * ADC read from FPGA - * @details - * Inputs : U32 (adc, gain, refResistance) - * Outputs : F32 (temperature in deg C) - * @param none - * @return F32 (temperature in deg C) - *************************************************************************/ -static F32 getADC2TempConversion ( F32 avgADC, U32 gain, U32 refResistance, U32 zeroDegResistance ) -{ - //R(RTD) = R(ref) * (adc – 2^N-1) / (G *2^N-1); - F32 resistance = (refResistance * (avgADC - pow(2,(TEMP_SENSORS_ADC_BITS - 1)))) / (gain * pow(2,(TEMP_SENSORS_ADC_BITS - 1))); - //T=(-A+√(A^2-4B(1-R_T/R_0 )))/2B - F32 secondSqrtPart = 4 * TEMP_EQUATION_COEFF_B * (1 - (resistance / zeroDegResistance)); - F32 temperature = (-TEMP_EQUATION_COEFF_A + sqrt(pow(TEMP_EQUATION_COEFF_A, 2) - secondSqrtPart)) / (2 * TEMP_EQUATION_COEFF_B); - - return temperature; -} -/************************************************************************* - * @brief processADCRead - * 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 : U32 (sensorIndex, adc) - * Outputs : none - * @param none - * @return none - *************************************************************************/ -static void processADCRead (U32 sensorIndex, U32 adc, U32 fpgaError, U32 fpgaCount ) -{ - U32 error; - U32 heatersTemperature; - BOOL isADCValid = FALSE; - F32 temperature; - - - // TODO For testing only. REMOVE - /*temperature = getADC2TempConversion ( adc, - tempSensorsConstants [ TEMPSENSORS_CONDUCTIVITY_SENSOR_2_TEMP_SENSOR ] [ ADC_READ_GAIN_INDEX ], - tempSensorsConstants [ TEMPSENSORS_CONDUCTIVITY_SENSOR_2_TEMP_SENSOR ] [ ADC_READ_REF_RESISTANCE_INDEX ], - tempSensorsConstants [ TEMPSENSORS_CONDUCTIVITY_SENSOR_2_TEMP_SENSOR ] [ ADC_READ_0_DEG_RESISTANCE_INDEX ] );*/ - // TODO for testing only. REMOVE - - /* - * check if the index is not the heaters - * Mask the values accordingly - * if error is 0x80 for the external sensors, increment - * if count has not changed, update the previous count, increment the internal error count - * if the internal error count is above the threshold, set alarm, set the bool avGCalc to false - * if count is greater than previous, update the previous and reset the internal count - * set the avgCalc to true - * if the avgCalc in true, calculate all the steps and immediately convert to temperature - */ - if ( sensorIndex != TEMPSENSORS_PRIMARY_HEATER_INTERNAL_TEMP_SENSOR || sensorIndex != TEMPSENSORS_TRIMMER_HEATER_INTERNAL_TEMP_SESNOR ) - { - error = adc & MASK_OFF_U32_MSB; - /* - * what if the fpga channel error is not zero? - * what if the fpga channel error is zero but the individual is not? - */ - - if ( fpgaError != 0 ) - { - if ( error == EXTERNAL_TEMP_SENSORS_ERROR_VALUE ) - { - // TODO: alarm? - } - isADCValid = FALSE; - } - if ( error == EXTERNAL_TEMP_SENSORS_ERROR_VALUE ) - { - //tODO: FILL UP - isADCValid = FALSE; - } - } - else - { - // Fault state is the 17th bit - U32 fault = adc & MASK_OFF_LSW; - fault = fault & 0x0001; - - if ( fault == HEATERS_INTERNAL_TEMP_SENSOR_FAULT ) - { - // Fault alarm? or have a threshold? - // If the fault is 1, should we check the individuals? - } - - heatersTemperature = adc & 0xFF05; - heatersTemperature = (heatersTemperature & 0x7FFF) >> 2; - } - - U32 previousReadCount = readAndErrorCounts [ sensorIndex ] [ READ_AND_ERROR_PREV_FPGA_COUNT_INDEX ]; - if ( fpgaCount == previousReadCount ) - { - U32 internalErrorCount = readAndErrorCounts [ sensorIndex ] [ READ_AND_ERROR_INTERNAL_ERROR_COUNT_INDEX ]; - if ( internalErrorCount > MAX_ALLOWED_UNCHANGED_ADC_READS ) - { - // TODO alarm - } - else - { - readAndErrorCounts [ sensorIndex ] [ READ_AND_ERROR_PREV_FPGA_COUNT_INDEX ] = fpgaCount; - readAndErrorCounts [ sensorIndex ] [ READ_AND_ERROR_INTERNAL_ERROR_COUNT_INDEX ] = internalErrorCount++; - } - isADCValid = FALSE; - } - else if ( fpgaCount > previousReadCount ) - { - readAndErrorCounts [ sensorIndex ] [ READ_AND_ERROR_PREV_FPGA_COUNT_INDEX ] = fpgaCount; - readAndErrorCounts [ sensorIndex ] [ READ_AND_ERROR_INTERNAL_ERROR_COUNT_INDEX ] = 0; - isADCValid = TRUE; - } - - if ( isADCValid ) - { - // Update the values in the folders - U32 index = runningSumAndIndex [ sensorIndex ] [ ADC_READ_NEXT_INDEX_INDEX ]; - U32 runningSum = runningSumAndIndex [ sensorIndex ] [ ADC_READ_RUNNING_SUM_INDEX ]; - U32 indexValue = rawADCReads [ sensorIndex ] [ index ]; - U32 nextIndex = INC_WRAP( index, ADC_READ_FIRST_READ_INDEX, MAX_NUM_OF_RAW_ADC_SAMPLES - 1 ); - runningSum = runningSum - indexValue + adc; - - rawADCReads [ sensorIndex ] [ index ] = adc; - runningSumAndIndex [ sensorIndex ] [ ADC_READ_NEXT_INDEX_INDEX ] = nextIndex; - runningSumAndIndex [ sensorIndex ] [ ADC_READ_RUNNING_SUM_INDEX ] = runningSum; - - // If the buffer array is being filled for the first time, the number of samples - // are changing. When the array is filled up completely, max number of samples are used - if ( sampleCount < MAX_NUM_OF_RAW_ADC_SAMPLES ) - { - sampleCount++; - } - else - { - sampleCount = MAX_NUM_OF_RAW_ADC_SAMPLES; - } - // Calculate average - F32 avgADCReads = runningSum / sampleCount; - - // The external temperature sensors have gain and other parameters for temperature - // calculations. The heaters internal temperature sensors do not have any parameters - // this is used to decide whether to call the quadratic equation or not - if ( tempSensorsConstants [ sensorIndex ] [ ADC_READ_GAIN_INDEX ] != 0 ) - { - temperature = getADC2TempConversion ( avgADCReads, - tempSensorsConstants [ sensorIndex ] [ ADC_READ_GAIN_INDEX ], - tempSensorsConstants [ sensorIndex ] [ ADC_READ_REF_RESISTANCE_INDEX ], - tempSensorsConstants [ sensorIndex ] [ ADC_READ_0_DEG_RESISTANCE_INDEX ] ); - } - else - { - temperature = avgADCReads * HEATERS_INTERNAL_ADC_TO_TEMP_CONVERSION_COEFF; - } - - temperatureValues [ sensorIndex ] = temperature; - } -} -/************************************************************************* - * @brief handleSelfTestStart - * The handleSelfTestStart function waits for the ADC read array to be - * filled up for the first time. It then sets the state to next state - * @details - * Inputs : none - * Outputs : state (TEMPSENSORS_SELF_TEST_STATES_T) - * @param none - * @return state (TEMPSENSORS_SELF_TEST_STATES_T) - *************************************************************************/ -static TEMPSENSORS_SELF_TEST_STATES_T handleSelfTestStart ( void ) -{ - return TEMPSENSORS_SELF_TEST_ADC_CHECK; -} -/************************************************************************* - * @brief handleSelfTestADCCheck - * The handleSelfTestADCCheck function checks whether the ADC reads. If the - * reads are above the maximum 24bit ADC count, it will throw an alarm and - * switches to the next state - * @details - * Inputs : none - * Outputs : state (TEMPSENSORS_SELF_TEST_STATES_T) - * @param none - * @return state (TEMPSENSORS_SELF_TEST_STATES_T) - *************************************************************************/ -static TEMPSENSORS_SELF_TEST_STATES_T handleSelfTestADCCheck ( void ) -{ - TEMPSENSORS_SELF_TEST_STATES_T state = TEMPSENSORS_SELF_TEST_CONSISTENCY_CHECK; - - U08 i; - for ( i = 0; i < sizeof(avgADCReads); i++ ) - { - U32 avgADC = avgADCReads [ i ]; - - if ( avgADC > TEMP_SENSORS_ADC_MAX_COUNT ) - { - SET_ALARM_WITH_1_U32_DATA ( ALARM_ID_TEMPERATURE_SENSORS_OUT_OF_RANGE, TEMPSENSORS_SELF_TEST_ADC_CHECK ); - } - } - - return state; -} -/************************************************************************* - * @brief handleSelfTestConsistencyCheck - * The handleSelfTestConsistencyCheck function checks the values of the - * sensors to make sure they are within the allowed range from each other - * @details - * Inputs : none - * Outputs : state (TEMPSENSORS_SELF_TEST_STATES_T) - * @param none - * @return state (TEMPSENSORS_SELF_TEST_STATES_T) - *************************************************************************/ -static TEMPSENSORS_SELF_TEST_STATES_T handleSelfTestConsistencyCheck ( void ) -{ - //TODO Consider edge cases for the consistency check - TEMPSENSORS_SELF_TEST_STATES_T state = TEMPSENSORS_SELF_TEST_COMPLETE; - - U32 largestDelta; - U08 i, j; - - // Check if all the sensors are within a certain degree c - // from each other - for ( i = 0; i < sizeof(temperatureValues); i++ ) - { - for ( j = 0; j < sizeof(temperatureValues); j++ ) - { - if ( i != j ) - { - largestDelta = MAX( largestDelta, fabs(temperatureValues [ i ] - temperatureValues [ j ]) ); - } - if ( largestDelta > MAX_ALLOWED_TEMP_DELTA_BETWEEN_SENSORS ) - { - SET_ALARM_WITH_1_U32_DATA ( ALARM_ID_TEMPERATURE_SENSORS_INCONSISTENT, TEMPSENSORS_SELF_TEST_CONSISTENCY_CHECK ); - } - } - } - - return state; -} -/************************************************************************* - * @brief handleExecStart - * The handleExecStart function switches the state to read - * @details - * Inputs : none - * Outputs : state (TEMPSENSORS_EXEC_STATES_T) - * @param none - * @return state (TEMPSENSORS_EXEC_STATES_T) - *************************************************************************/ -static TEMPSENSORS_EXEC_STATES_T handleExecStart ( void ) -{ - return TEMPSENSORS_EXEC_STATE_GET_ADC_VALUES; -} -/************************************************************************* - * @brief handleExecGetADCValues - * The handleExecGetADCValues function reads the ADC values from FPGA - * @details - * Inputs : none - * Outputs : state (TEMPSENSORS_EXEC_STATES_T) - * @param none - * @return state (TEMPSENSORS_EXEC_STATES_T) - *************************************************************************/ -static TEMPSENSORS_EXEC_STATES_T handleExecGetADCValues ( void ) -{ - TEMPSENSORS_EXEC_STATES_T state = TEMPSENSORS_EXEC_STATE_GET_ADC_VALUES; - - // Check the read count for a change before inserting - // Need to remember the fpga counter and if it has not changed increment another counter and - // zero it if it changed. if it is above a certain number throw fault - // error counter from fpga same as above remember, if it is incremented: - - // Look at the error counter and the specific error flag to make sure the error is a temp sensor - // Add a byte array to have bits for each sensor to find out exactly what sensor failed - //processADCRead( TEMPSENSORS_INLET_PRIMARY_HEATER_TEMP_SENSOR, getFPGATPiTemp() ); - //processADCRead( TEMPSENSORS_OUTLET_PRIMARY_HEATER_TEMP_SENSOR, getFPGATPoTemp() ); - //processADCRead( TEMPSENSORS_CONDUCTIVITY_SENSOR_1_TEMP_SENSOR, getFPGACD1Temp() ); - //processADCRead( TEMPSENSORS_CONDUCTIVITY_SENSOR_2_TEMP_SENSOR, getFPGACD2Temp() ); - //processADCRead( TEMPSENSORS_OUTLET_REDUNDANCY_TEMP_SENSOR, getFPGATHDoTemp() ); - //processADCRead( TEMPSENSORS_INLET_DIALYSATE_TEMP_SENSOR, getFPGATDiTemp() ); - //processADCRead( TEMPSENSORS_PRIMARY_HEATER_INTERNAL_TEMP_SENSOR, getFPGAPrimaryHeaterTemp() ); - //processADCRead( TEMPSENSORS_TRIMMER_HEATER_INTERNAL_TEMP_SESNOR, getFPGATrimmerHeaterTemp() ); - - // TODO REMOVE THIS CODE. FOR TESTING ONLY - - - /*U08 dara; - U32 test [20] = {16327313, 16330313, 16333313, 16336313, 16339313, 16342313, 16345313, 16348313, 16351313, 16354313, - 16357313, 16360313, 16363313, 16366313, 16369313, 16372313, 16375313, 16378313, 16381313, 16384313}; - - U32 test2 [20] = {16348313, 16358313, 16368313, 16378313, 16388313, 16398313, 16408313, 16418313, 16428313, 16438313, - 16448313, 16458313, 16468313, 16478313, 16488313, 16498313, 16508313, 16518313, 16528313, 16538313}; - - for ( dara = 0; dara<20; dara++) - { - processADCRead(0, test[dara]); - } - dara = 0; - for ( dara = 0; dara<20; dara++) - { - processADCRead(0, test2[dara]); - }*/ - // TODO REMOVE THE ABOVE CODE - - return state; -} +/**********************************************************************//** + * + * Copyright (c) 2019-2020 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 + * + * @date 7-Apr-2020 + * @author Dara Navaei + * + * @brief DG temperature sensors controller + * + **************************************************************************/ +#include // For temperature calculation + +#include "TemperatureSensors.h" +#include "FPGA.h" + +// TODO: For testing only REMOVE +#include "Timers.h" +// TODO: For testing only REMOVE + +// Private variables + +#define PRIMARY_HEATER_EXT_TEMP_SENSORS_GAIN 16U ///< Primary heater external temperature sensors gain +#define PRIMARY_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE 19600U ///< 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 COND_SENSORS_TEMP_SENSOR_GAIN 16U ///< Conductivity sensor gain +#define COND_SENSORS_TEMP_SENSOR_REF_RESISTANCE 19600U ///< Conductivity sensor reference resistance +#define COND_SENSORS_TEMP_SENSOR_0_DEGREE_RESISTANCE 1000U ///< Conductivity sensor zero degree resistance + +#define TRIMMER_HEATER_EXT_TEMP_SENSORS_GAIN 32U ///< Trimmer heater external temperature sensors gain +#define TRIMMER_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE 5110U ///< 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 HEATERS_INTERNAL_ADC_TO_TEMP_CONVERSION_COEFF 0.0625 ///< Heaters internal temperature sensors ADC to temperature conversion coefficient + +#define TEMP_SENSORS_ADC_BITS 24U ///< External temperature sensors ADC bits +#define TEMP_SENSORS_ADC_MAX_COUNT (pow(2,TEMP_SENSORS_ADC_BITS)) ///< Temperature sensors max ADC count + +#define TEMP_EQUATION_COEFF_A (3.9083 * pow(10,-3)) ///< ADC to temperature conversion coefficient A +#define TEMP_EQUATION_COEFF_B (-5.775 * pow(10,-7)) ///< ADC to temperature conversion coefficient B + +#define MAX_NUM_OF_RAW_ADC_SAMPLES 20U ///< Number of ADC reads for moving average calculations + +#define ADC_READ_FIRST_READ_INDEX 0U ///< ADC array first ADC read index + +#define ADC_READ_NEXT_INDEX_INDEX 0U ///< ADC array next insertion index +#define ADC_READ_RUNNING_SUM_INDEX 1U ///< ADC array running sum index + +#define ADC_READ_GAIN_INDEX 0U ///< ADC array gain index +#define ADC_READ_REF_RESISTANCE_INDEX 1U ///< ADC array reference resistances index +#define ADC_READ_0_DEG_RESISTANCE_INDEX 2U ///< ADC array zero degree resistance index + +#define READ_AND_ERROR_PREV_FPGA_COUNT_INDEX 0U +#define READ_AND_ERROR_INTERNAL_READ_COUNT_INDEX 1U +#define READ_AND_ERROR_INTERNAL_ERROR_COUNT_INDEX 2U +#define READ_AND_ERROR_PREV_FPGA_ERROR_INDEX 3U +#define NUM_OF_READ_AND_ERROR_ARRAY_COLUMNS 4U + +#define MAX_ALLOWED_TEMP_DELTA_BETWEEN_SENSORS 2U ///< Maximum allowed temperature delta between sensors + +#define NUM_OF_RUNNING_SUM_AND_INDEX_ARRAY_COLUMNS 2U ///< Number of columns in running sum and index array +#define NUM_OF_TEMP_SENSORS_CONSTANTS_ARRAY_COLUMNS 3U ///< Number of columns in temperature sensors constants + +#define MAX_ALLOWED_UNCHANGED_ADC_READS 4U ///< Maximum number of times that the read of a sensor cannot change + +#define EXTERNAL_TEMP_SENSORS_ERROR_VALUE 0x80 +#define HEATERS_INTERNAL_TEMP_SENSOR_FAULT 0x01 +#define MASK_OFF_U32_MSB 0x00FFFFFF + +/// Temperature sensor self test states +typedef enum tempSensors_Self_Test_States +{ + TEMPSENSORS_SELF_TEST_START = 0, ///< Temperature sensors self test start + TEMPSENSORS_SELF_TEST_ADC_CHECK, ///< Temperature sensors self ADC check + TEMPSENSORS_SELF_TEST_CONSISTENCY_CHECK, ///< Temperature sensors self test consistency check + TEMPSENSORS_SELF_TEST_COMPLETE, ///< Temperature sensors self test complete + NUM_OF_TEMPSENSORS_SELF_TEST_STATES ///< Total number of self test states +} TEMPSENSORS_SELF_TEST_STATES_T; + +/// 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; + +/// FPGA error and read counts +typedef struct +{ + U08 RTDErrorCount; ///< RTD error count (include all 4 conductivity and temperature sensors) + U08 RTDReadCount; ///< RTD read count (include all 4 conductivity and temperature sensors) + U08 TRoErrorCount; ///< THDo (outlet redundant temperature sensor) error count + U08 TRoReadCount; ///< THDo (outlet redundant temperature sensor) read count + U08 TDiErrorCount; ///< TDi (inlet dialysate) temperature sensor error count + U08 TDiReadCount; ///< TDi (inlet dialysate) temperature sensor read count + U08 primaryHeaterFlags; ///< Primary heater internal temperature sensor error flags + U08 primaryHeaterReadCount; ///< Primary heater internal temperature sensor read count + U08 trimmerHeaterFlags; ///< Trimmer heater internal temperature sensor error flags + U08 trimmerHeaterReadCount; ///< Trimmer heater internal temperature sensor read count +} FPGA_READ_AND_ERROR_COUNTS_T; // TODO REmove + +static SELF_TEST_STATUS_T tempSensorsSelfTestResult; ///< Self test result of the TemperatureSensors module +static TEMPSENSORS_SELF_TEST_STATES_T tempSensorsSelfTestState; ///< TemperatureSensor self test state +static TEMPSENSORS_EXEC_STATES_T tempSensorsExecState; ///< TemperatureSensor exec state +static U32 sampleCount; ///< Initial ADC read index until the array if filled up for the first time +static U32 rawADCReads [ NUM_OF_TEMPERATURE_SENSORS ] ///< Raw ADC reads array + [ MAX_NUM_OF_RAW_ADC_SAMPLES ]; +static U32 runningSumAndIndex [ NUM_OF_TEMPERATURE_SENSORS ] ///< Running sum and next ADC index array + [ NUM_OF_RUNNING_SUM_AND_INDEX_ARRAY_COLUMNS ]; +static U32 tempSensorsConstants [ NUM_OF_TEMPERATURE_SENSORS ] ///< Temperature sensors constants + [ NUM_OF_TEMP_SENSORS_CONSTANTS_ARRAY_COLUMNS ]; +static F32 avgADCReads [ NUM_OF_TEMPERATURE_SENSORS ]; //TODO remove ///< Temperature sensors averaged ADC values +static F32 temperatureValues [ NUM_OF_TEMPERATURE_SENSORS ]; +static U32 readAndErrorCounts [ NUM_OF_TEMPERATURE_SENSORS ] [ NUM_OF_READ_AND_ERROR_ARRAY_COLUMNS ]; + +// Private functions prototypes + +static TEMPSENSORS_SELF_TEST_STATES_T handleSelfTestStart ( void ); +static TEMPSENSORS_SELF_TEST_STATES_T handleSelfTestADCCheck ( void ); +static TEMPSENSORS_SELF_TEST_STATES_T handleSelfTestConsistencyCheck ( void ); + +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 ); +static void processADCRead ( U32 sensorIndex, U32 adc, U32 fpgaError, U32 fpgaCount ); + +// Public functions + +/************************************************************************* + * @brief initTemperatureSensors + * The initTemperatureSensors function initializes the module + * @details + * Inputs : none + * Outputs : none + * @param none + * @return none + *************************************************************************/ +void initTemperatureSensors ( void ) +{ + U08 i; + tempSensorsSelfTestResult = SELF_TEST_STATUS_IN_PROGRESS; + tempSensorsSelfTestState = TEMPSENSORS_SELF_TEST_START; + tempSensorsExecState = TEMPSENSORS_EXEC_STATE_START; + sampleCount = 0; + + // Initialize TPi and TPo constants + for ( i = TEMPSENSORS_INLET_PRIMARY_HEATER_TEMP_SENSOR; i < TEMPSENSORS_CONDUCTIVITY_SENSOR_1_TEMP_SENSOR; i++ ) + { + tempSensorsConstants [ i ] [ ADC_READ_GAIN_INDEX ] = PRIMARY_HEATER_EXT_TEMP_SENSORS_GAIN; + tempSensorsConstants [ i ] [ ADC_READ_REF_RESISTANCE_INDEX ] = PRIMARY_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE; + tempSensorsConstants [ i ] [ ADC_READ_0_DEG_RESISTANCE_INDEX ] = PRIMARY_HEATER_EXT_TEMP_SENSORS_0_DEGREE_RESISTANCE; + } + // Initialize TD1 and TD2 constants + for ( i = TEMPSENSORS_CONDUCTIVITY_SENSOR_1_TEMP_SENSOR; i < TEMPSENSORS_OUTLET_REDUNDANCY_TEMP_SENSOR; i++ ) + { + tempSensorsConstants [ i ] [ ADC_READ_GAIN_INDEX ] = COND_SENSORS_TEMP_SENSOR_GAIN; + tempSensorsConstants [ i ] [ ADC_READ_REF_RESISTANCE_INDEX ] = COND_SENSORS_TEMP_SENSOR_REF_RESISTANCE; + tempSensorsConstants [ i ] [ ADC_READ_0_DEG_RESISTANCE_INDEX ] = COND_SENSORS_TEMP_SENSOR_0_DEGREE_RESISTANCE; + } + // Initialize TRo and TDi constants + for ( i = TEMPSENSORS_OUTLET_REDUNDANCY_TEMP_SENSOR; i < TEMPSENSORS_PRIMARY_HEATER_INTERNAL_TEMP_SENSOR; i++ ) + { + tempSensorsConstants [ i ] [ ADC_READ_GAIN_INDEX ] = TRIMMER_HEATER_EXT_TEMP_SENSORS_GAIN; + tempSensorsConstants [ i ] [ ADC_READ_REF_RESISTANCE_INDEX ] = TRIMMER_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE; + tempSensorsConstants [ i ] [ ADC_READ_0_DEG_RESISTANCE_INDEX ] = TRIMMER_HEATER_EXT_TEMP_SENSORS_0_DEGREE_RESISTANCE; + } + + // Initialize primary heater internal temperature sensor + // The heaters do not need gain, reference resistance, and zero degree resistance + tempSensorsConstants [ TEMPSENSORS_PRIMARY_HEATER_INTERNAL_TEMP_SENSOR ] [ ADC_READ_GAIN_INDEX ] = 0; + tempSensorsConstants [ TEMPSENSORS_PRIMARY_HEATER_INTERNAL_TEMP_SENSOR ] [ ADC_READ_REF_RESISTANCE_INDEX ] = 0; + tempSensorsConstants [ TEMPSENSORS_PRIMARY_HEATER_INTERNAL_TEMP_SENSOR ] [ ADC_READ_0_DEG_RESISTANCE_INDEX ] = 0; + // Initialize trimmer heater internal temperature sensor + tempSensorsConstants [ TEMPSENSORS_TRIMMER_HEATER_INTERNAL_TEMP_SESNOR ] [ ADC_READ_GAIN_INDEX ] = 0; + tempSensorsConstants [ TEMPSENSORS_TRIMMER_HEATER_INTERNAL_TEMP_SESNOR ] [ ADC_READ_REF_RESISTANCE_INDEX ] = 0; + tempSensorsConstants [ TEMPSENSORS_TRIMMER_HEATER_INTERNAL_TEMP_SESNOR ] [ ADC_READ_0_DEG_RESISTANCE_INDEX ] = 0; +} +/************************************************************************* + * @brief execTemperatureSensorsSelfTest + * The execTemperatureSensorsSelfTest function runs the TemperatureSensors + * POST during the self test + * @details + * Inputs : none + * Outputs : SELF_TEST_STATUS_T + * @param none + * @return SELF_TEST_STATUS_T + *************************************************************************/ +SELF_TEST_STATUS_T execTemperatureSensorsSelfTest ( void ) +{ + switch ( tempSensorsSelfTestState ) + { + case TEMPSENSORS_SELF_TEST_START: + + tempSensorsSelfTestState = handleSelfTestStart(); + break; + + case TEMPSENSORS_SELF_TEST_ADC_CHECK: + + tempSensorsSelfTestState = handleSelfTestADCCheck(); + break; + + case TEMPSENSORS_SELF_TEST_CONSISTENCY_CHECK: + + tempSensorsSelfTestState = handleSelfTestConsistencyCheck(); + break; + + case TEMPSENSORS_SELF_TEST_COMPLETE: + + // Done with self test, do nothing + break; + + default: + + SET_ALARM_WITH_2_U32_DATA ( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_TEMPERATURE_SENSORS_INVALID_SELF_TEST_STATE, + tempSensorsSelfTestState ); + tempSensorsSelfTestState = TEMPSENSORS_SELF_TEST_COMPLETE; + break; + } + + return tempSensorsSelfTestResult; +} +/************************************************************************* + * @brief execTemperatureSensors + * The execTemperatureSensors function runs the TemperatureSensors main + * tasks + * @details + * Inputs : none + * Outputs : none + * @param none + * @return none + *************************************************************************/ +void execTemperatureSensors ( void ) +{ + // read the sensors all the time + switch ( tempSensorsExecState ) + { + case TEMPSENSORS_SELF_TEST_START: + + tempSensorsExecState = handleExecStart(); + break; + + case TEMPSENSORS_EXEC_STATE_GET_ADC_VALUES: + + tempSensorsExecState = handleExecGetADCValues(); + break; + + default: + + SET_ALARM_WITH_2_U32_DATA ( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_TEMPERATURE_SENSORS_EXEC_INVALID_STATE, + tempSensorsExecState ); + tempSensorsExecState = TEMPSENSORS_EXEC_STATE_GET_ADC_VALUES; + break; + } +} +/************************************************************************* + * @brief getTemperatureValue + * The getTemperatureValue function gets the enum of the requested + * temperature sensor, converts the ADC of it to temperature in degree C + * and returns the temperature + * @details + * Inputs : TEMPERATURE_SENSORS_T (sensor) + * Outputs : F32 (temperature in deg C) + * @param none + * @return F32 (temperature in deg C) + *************************************************************************/ +F32 getTemperatureValue ( TEMPERATURE_SENSORS_T sensor ) +{ + F32 temperature; + switch ( sensor ) + { + case TEMPSENSORS_INLET_PRIMARY_HEATER_TEMP_SENSOR: + + temperature = temperatureValues [ TEMPSENSORS_INLET_PRIMARY_HEATER_TEMP_SENSOR ]; + break; + + case TEMPSENSORS_OUTLET_PRIMARY_HEATER_TEMP_SENSOR: + + temperature = temperatureValues [ TEMPSENSORS_OUTLET_PRIMARY_HEATER_TEMP_SENSOR ]; + break; + + case TEMPSENSORS_CONDUCTIVITY_SENSOR_1_TEMP_SENSOR: + + temperature = temperatureValues [ TEMPSENSORS_CONDUCTIVITY_SENSOR_1_TEMP_SENSOR ]; + break; + + case TEMPSENSORS_CONDUCTIVITY_SENSOR_2_TEMP_SENSOR: + + temperature = temperatureValues [ TEMPSENSORS_CONDUCTIVITY_SENSOR_2_TEMP_SENSOR ]; + break; + + case TEMPSENSORS_OUTLET_REDUNDANCY_TEMP_SENSOR: + + temperature = temperatureValues [ TEMPSENSORS_OUTLET_REDUNDANCY_TEMP_SENSOR ]; + break; + + case TEMPSENSORS_INLET_DIALYSATE_TEMP_SENSOR: + + temperature = temperatureValues [ TEMPSENSORS_INLET_DIALYSATE_TEMP_SENSOR ]; + break; + + case TEMPSENSORS_PRIMARY_HEATER_INTERNAL_TEMP_SENSOR: + + temperature = temperatureValues [ TEMPSENSORS_PRIMARY_HEATER_INTERNAL_TEMP_SENSOR ]; + break; + + case TEMPSENSORS_TRIMMER_HEATER_INTERNAL_TEMP_SESNOR: + + temperature = temperatureValues [ TEMPSENSORS_TRIMMER_HEATER_INTERNAL_TEMP_SESNOR ]; + break; + + default: + // ToDo: Warning? + break; + } + + return temperature; +} + +// Private functions + +/************************************************************************* + * @brief getADC2TempConversion + * The getADC2TempConversion function calculates the temperature from + * ADC read from FPGA + * @details + * Inputs : U32 (adc, gain, refResistance) + * Outputs : F32 (temperature in deg C) + * @param none + * @return F32 (temperature in deg C) + *************************************************************************/ +static F32 getADC2TempConversion ( F32 avgADC, U32 gain, U32 refResistance, U32 zeroDegResistance ) +{ + //R(RTD) = R(ref) * (adc – 2^N-1) / (G *2^N-1); + F32 resistance = (refResistance * (avgADC - pow(2,(TEMP_SENSORS_ADC_BITS - 1)))) / (gain * pow(2,(TEMP_SENSORS_ADC_BITS - 1))); + //T=(-A+√(A^2-4B(1-R_T/R_0 )))/2B + F32 secondSqrtPart = 4 * TEMP_EQUATION_COEFF_B * (1 - (resistance / zeroDegResistance)); + F32 temperature = (-TEMP_EQUATION_COEFF_A + sqrt(pow(TEMP_EQUATION_COEFF_A, 2) - secondSqrtPart)) / (2 * TEMP_EQUATION_COEFF_B); + + return temperature; +} +/************************************************************************* + * @brief processADCRead + * 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 : U32 (sensorIndex, adc) + * Outputs : none + * @param none + * @return none + *************************************************************************/ +static void processADCRead (U32 sensorIndex, U32 adc, U32 fpgaError, U32 fpgaCount ) +{ + U32 error; + U32 heatersTemperature; + BOOL isADCValid = FALSE; + F32 temperature; + + + // TODO For testing only. REMOVE + /*temperature = getADC2TempConversion ( adc, + tempSensorsConstants [ TEMPSENSORS_CONDUCTIVITY_SENSOR_2_TEMP_SENSOR ] [ ADC_READ_GAIN_INDEX ], + tempSensorsConstants [ TEMPSENSORS_CONDUCTIVITY_SENSOR_2_TEMP_SENSOR ] [ ADC_READ_REF_RESISTANCE_INDEX ], + tempSensorsConstants [ TEMPSENSORS_CONDUCTIVITY_SENSOR_2_TEMP_SENSOR ] [ ADC_READ_0_DEG_RESISTANCE_INDEX ] );*/ + // TODO for testing only. REMOVE + + /* + * check if the index is not the heaters + * Mask the values accordingly + * if error is 0x80 for the external sensors, increment + * if count has not changed, update the previous count, increment the internal error count + * if the internal error count is above the threshold, set alarm, set the bool avGCalc to false + * if count is greater than previous, update the previous and reset the internal count + * set the avgCalc to true + * if the avgCalc in true, calculate all the steps and immediately convert to temperature + */ + if ( sensorIndex != TEMPSENSORS_PRIMARY_HEATER_INTERNAL_TEMP_SENSOR || sensorIndex != TEMPSENSORS_TRIMMER_HEATER_INTERNAL_TEMP_SESNOR ) + { + error = adc & MASK_OFF_U32_MSB; + /* + * what if the fpga channel error is not zero? + * what if the fpga channel error is zero but the individual is not? + */ + + if ( fpgaError != 0 ) + { + if ( error == EXTERNAL_TEMP_SENSORS_ERROR_VALUE ) + { + // TODO: alarm? + } + isADCValid = FALSE; + } + if ( error == EXTERNAL_TEMP_SENSORS_ERROR_VALUE ) + { + //tODO: FILL UP + isADCValid = FALSE; + } + } + else + { + // Fault state is the 17th bit + U32 fault = adc & MASK_OFF_LSW; + fault = fault & 0x0001; + + if ( fault == HEATERS_INTERNAL_TEMP_SENSOR_FAULT ) + { + // Fault alarm? or have a threshold? + // If the fault is 1, should we check the individuals? + } + + heatersTemperature = adc & 0xFF05; + heatersTemperature = (heatersTemperature & 0x7FFF) >> 2; + } + + U32 previousReadCount = readAndErrorCounts [ sensorIndex ] [ READ_AND_ERROR_PREV_FPGA_COUNT_INDEX ]; + if ( fpgaCount == previousReadCount ) + { + U32 internalErrorCount = readAndErrorCounts [ sensorIndex ] [ READ_AND_ERROR_INTERNAL_ERROR_COUNT_INDEX ]; + if ( internalErrorCount > MAX_ALLOWED_UNCHANGED_ADC_READS ) + { + // TODO alarm + } + else + { + readAndErrorCounts [ sensorIndex ] [ READ_AND_ERROR_PREV_FPGA_COUNT_INDEX ] = fpgaCount; + readAndErrorCounts [ sensorIndex ] [ READ_AND_ERROR_INTERNAL_ERROR_COUNT_INDEX ] = internalErrorCount++; + } + isADCValid = FALSE; + } + else if ( fpgaCount > previousReadCount ) + { + readAndErrorCounts [ sensorIndex ] [ READ_AND_ERROR_PREV_FPGA_COUNT_INDEX ] = fpgaCount; + readAndErrorCounts [ sensorIndex ] [ READ_AND_ERROR_INTERNAL_ERROR_COUNT_INDEX ] = 0; + isADCValid = TRUE; + } + + if ( isADCValid ) + { + // Update the values in the folders + U32 index = runningSumAndIndex [ sensorIndex ] [ ADC_READ_NEXT_INDEX_INDEX ]; + U32 runningSum = runningSumAndIndex [ sensorIndex ] [ ADC_READ_RUNNING_SUM_INDEX ]; + U32 indexValue = rawADCReads [ sensorIndex ] [ index ]; + U32 nextIndex = INC_WRAP( index, ADC_READ_FIRST_READ_INDEX, MAX_NUM_OF_RAW_ADC_SAMPLES - 1 ); + runningSum = runningSum - indexValue + adc; + + rawADCReads [ sensorIndex ] [ index ] = adc; + runningSumAndIndex [ sensorIndex ] [ ADC_READ_NEXT_INDEX_INDEX ] = nextIndex; + runningSumAndIndex [ sensorIndex ] [ ADC_READ_RUNNING_SUM_INDEX ] = runningSum; + + // If the buffer array is being filled for the first time, the number of samples + // are changing. When the array is filled up completely, max number of samples are used + if ( sampleCount < MAX_NUM_OF_RAW_ADC_SAMPLES ) + { + sampleCount++; + } + else + { + sampleCount = MAX_NUM_OF_RAW_ADC_SAMPLES; + } + // Calculate average + F32 avgADCReads = runningSum / sampleCount; + + // The external temperature sensors have gain and other parameters for temperature + // calculations. The heaters internal temperature sensors do not have any parameters + // this is used to decide whether to call the quadratic equation or not + if ( tempSensorsConstants [ sensorIndex ] [ ADC_READ_GAIN_INDEX ] != 0 ) + { + temperature = getADC2TempConversion ( avgADCReads, + tempSensorsConstants [ sensorIndex ] [ ADC_READ_GAIN_INDEX ], + tempSensorsConstants [ sensorIndex ] [ ADC_READ_REF_RESISTANCE_INDEX ], + tempSensorsConstants [ sensorIndex ] [ ADC_READ_0_DEG_RESISTANCE_INDEX ] ); + } + else + { + temperature = avgADCReads * HEATERS_INTERNAL_ADC_TO_TEMP_CONVERSION_COEFF; + } + + temperatureValues [ sensorIndex ] = temperature; + } +} +/************************************************************************* + * @brief handleSelfTestStart + * The handleSelfTestStart function waits for the ADC read array to be + * filled up for the first time. It then sets the state to next state + * @details + * Inputs : none + * Outputs : state (TEMPSENSORS_SELF_TEST_STATES_T) + * @param none + * @return state (TEMPSENSORS_SELF_TEST_STATES_T) + *************************************************************************/ +static TEMPSENSORS_SELF_TEST_STATES_T handleSelfTestStart ( void ) +{ + return TEMPSENSORS_SELF_TEST_ADC_CHECK; +} +/************************************************************************* + * @brief handleSelfTestADCCheck + * The handleSelfTestADCCheck function checks whether the ADC reads. If the + * reads are above the maximum 24bit ADC count, it will throw an alarm and + * switches to the next state + * @details + * Inputs : none + * Outputs : state (TEMPSENSORS_SELF_TEST_STATES_T) + * @param none + * @return state (TEMPSENSORS_SELF_TEST_STATES_T) + *************************************************************************/ +static TEMPSENSORS_SELF_TEST_STATES_T handleSelfTestADCCheck ( void ) +{ + TEMPSENSORS_SELF_TEST_STATES_T state = TEMPSENSORS_SELF_TEST_CONSISTENCY_CHECK; + + U08 i; + for ( i = 0; i < sizeof(avgADCReads); i++ ) + { + U32 avgADC = avgADCReads [ i ]; + + if ( avgADC > TEMP_SENSORS_ADC_MAX_COUNT ) + { + SET_ALARM_WITH_1_U32_DATA ( ALARM_ID_TEMPERATURE_SENSORS_OUT_OF_RANGE, TEMPSENSORS_SELF_TEST_ADC_CHECK ); + } + } + + return state; +} +/************************************************************************* + * @brief handleSelfTestConsistencyCheck + * The handleSelfTestConsistencyCheck function checks the values of the + * sensors to make sure they are within the allowed range from each other + * @details + * Inputs : none + * Outputs : state (TEMPSENSORS_SELF_TEST_STATES_T) + * @param none + * @return state (TEMPSENSORS_SELF_TEST_STATES_T) + *************************************************************************/ +static TEMPSENSORS_SELF_TEST_STATES_T handleSelfTestConsistencyCheck ( void ) +{ + //TODO Consider edge cases for the consistency check + TEMPSENSORS_SELF_TEST_STATES_T state = TEMPSENSORS_SELF_TEST_COMPLETE; + + U32 largestDelta; + U08 i, j; + + // Check if all the sensors are within a certain degree c + // from each other + for ( i = 0; i < sizeof(temperatureValues); i++ ) + { + for ( j = 0; j < sizeof(temperatureValues); j++ ) + { + if ( i != j ) + { + largestDelta = MAX( largestDelta, fabs(temperatureValues [ i ] - temperatureValues [ j ]) ); + } + if ( largestDelta > MAX_ALLOWED_TEMP_DELTA_BETWEEN_SENSORS ) + { + SET_ALARM_WITH_1_U32_DATA ( ALARM_ID_TEMPERATURE_SENSORS_INCONSISTENT, TEMPSENSORS_SELF_TEST_CONSISTENCY_CHECK ); + } + } + } + + return state; +} +/************************************************************************* + * @brief handleExecStart + * The handleExecStart function switches the state to read + * @details + * Inputs : none + * Outputs : state (TEMPSENSORS_EXEC_STATES_T) + * @param none + * @return state (TEMPSENSORS_EXEC_STATES_T) + *************************************************************************/ +static TEMPSENSORS_EXEC_STATES_T handleExecStart ( void ) +{ + return TEMPSENSORS_EXEC_STATE_GET_ADC_VALUES; +} +/************************************************************************* + * @brief handleExecGetADCValues + * The handleExecGetADCValues function reads the ADC values from FPGA + * @details + * Inputs : none + * Outputs : state (TEMPSENSORS_EXEC_STATES_T) + * @param none + * @return state (TEMPSENSORS_EXEC_STATES_T) + *************************************************************************/ +static TEMPSENSORS_EXEC_STATES_T handleExecGetADCValues ( void ) +{ + TEMPSENSORS_EXEC_STATES_T state = TEMPSENSORS_EXEC_STATE_GET_ADC_VALUES; + + // Check the read count for a change before inserting + // Need to remember the fpga counter and if it has not changed increment another counter and + // zero it if it changed. if it is above a certain number throw fault + // error counter from fpga same as above remember, if it is incremented: + + // Look at the error counter and the specific error flag to make sure the error is a temp sensor + // Add a byte array to have bits for each sensor to find out exactly what sensor failed + //processADCRead( TEMPSENSORS_INLET_PRIMARY_HEATER_TEMP_SENSOR, getFPGATPiTemp() ); + //processADCRead( TEMPSENSORS_OUTLET_PRIMARY_HEATER_TEMP_SENSOR, getFPGATPoTemp() ); + //processADCRead( TEMPSENSORS_CONDUCTIVITY_SENSOR_1_TEMP_SENSOR, getFPGACD1Temp() ); + //processADCRead( TEMPSENSORS_CONDUCTIVITY_SENSOR_2_TEMP_SENSOR, getFPGACD2Temp() ); + //processADCRead( TEMPSENSORS_OUTLET_REDUNDANCY_TEMP_SENSOR, getFPGATHDoTemp() ); + //processADCRead( TEMPSENSORS_INLET_DIALYSATE_TEMP_SENSOR, getFPGATDiTemp() ); + //processADCRead( TEMPSENSORS_PRIMARY_HEATER_INTERNAL_TEMP_SENSOR, getFPGAPrimaryHeaterTemp() ); + //processADCRead( TEMPSENSORS_TRIMMER_HEATER_INTERNAL_TEMP_SESNOR, getFPGATrimmerHeaterTemp() ); + + // TODO REMOVE THIS CODE. FOR TESTING ONLY + + + /*U08 dara; + U32 test [20] = {16327313, 16330313, 16333313, 16336313, 16339313, 16342313, 16345313, 16348313, 16351313, 16354313, + 16357313, 16360313, 16363313, 16366313, 16369313, 16372313, 16375313, 16378313, 16381313, 16384313}; + + U32 test2 [20] = {16348313, 16358313, 16368313, 16378313, 16388313, 16398313, 16408313, 16418313, 16428313, 16438313, + 16448313, 16458313, 16468313, 16478313, 16488313, 16498313, 16508313, 16518313, 16528313, 16538313}; + + for ( dara = 0; dara<20; dara++) + { + processADCRead(0, test[dara]); + } + dara = 0; + for ( dara = 0; dara<20; dara++) + { + processADCRead(0, test2[dara]); + }*/ + // TODO REMOVE THE ABOVE CODE + + return state; +}