Index: firmware/App/Controllers/Thermistors.c =================================================================== diff -u -r45263215b372cd579e8e16bb8073c287c726c55d -r1f500f8e6159a3fbab85ea68389e918a6df66400 --- firmware/App/Controllers/Thermistors.c (.../Thermistors.c) (revision 45263215b372cd579e8e16bb8073c287c726c55d) +++ firmware/App/Controllers/Thermistors.c (.../Thermistors.c) (revision 1f500f8e6159a3fbab85ea68389e918a6df66400) @@ -14,26 +14,26 @@ // ********** private definitions ********** -#define THERMISTORS_DATA_PUBLISH_INTERVAL (MS_PER_SECOND / TASK_GENERAL_INTERVAL) ///< Thermistors publish data time interval. -#define THERMISTORS_ADC_READ_INTERVAL (MS_PER_SECOND / (2 * TASK_GENERAL_INTERVAL)) ///< Thermistors ADC read time interval. -#define ADC_FPGA_READ_DELAY_COUNT 1 ///< FGPA read delay upon startup. -#define ONBOARD_THERMISTOR_SOURCE_VOLTAGE 3 ///< Onboard thermistor source voltage. -#define ONBOARD_THERMISTOR_REFERENCE_RESISTOR 10 ///< Onboard thermistor reference resistor. -#define ONBOARD_THERMISTOR_BETA_VALUE 3380 ///< Onboard thermistor beta value. -#define ONBOARD_THERMISTOR_REFERENCE_TEMPERATURE 298 ///< Onboard thermistor reference temperature. -#define TWELVE_BIT_RESOLUTION 4096 ///< 12 bit resolution conversion. -#define CELSIUS_TO_KELVIN_CONVERSION 273.15 ///< Celsius to Kelvin temperature conversion. -#define ADC_TEMP_SENSORS_CONVERSION_CONST 272.5 ///< ADC temperature sensors conversion constant. -#define MIN_ALLOWED_TEMPERATURE 10 ///< Thermistors/sensors minimum allowed temperature reading. -#define MAX_ALLOWED_TEMPERATURE 70 ///< Thermistors/sensors maximum allowed temperature reading. +#define THERMISTORS_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Thermistors publish data time interval. +#define THERMISTORS_ADC_READ_INTERVAL ( MS_PER_SECOND / ( 2 * TASK_GENERAL_INTERVAL ) ) ///< Thermistors ADC read time interval. +#define ADC_FPGA_READ_DELAY_COUNT 1 ///< FGPA read delay upon startup. +#define ONBOARD_THERMISTOR_SOURCE_VOLTAGE 3 ///< Onboard thermistor source voltage. +#define ONBOARD_THERMISTOR_REFERENCE_RESISTOR 10 ///< Onboard thermistor reference resistor. +#define ONBOARD_THERMISTOR_BETA_VALUE 3380 ///< Onboard thermistor beta value. +#define ONBOARD_THERMISTOR_REFERENCE_TEMPERATURE 298 ///< Onboard thermistor reference temperature. +#define TWELVE_BIT_RESOLUTION 4096 ///< 12 bit resolution conversion. +#define CELSIUS_TO_KELVIN_CONVERSION 273.15 ///< Celsius to Kelvin temperature conversion. +#define ADC_TEMP_SENSORS_CONVERSION_CONST 272.5 ///< ADC temperature sensors conversion constant. +#define MIN_ALLOWED_TEMPERATURE 0 ///< Thermistors/sensors minimum allowed temperature reading. +#define MAX_ALLOWED_TEMPERATURE 70 ///< Thermistors/sensors maximum allowed temperature reading. +#define MAX_ALLOWED_TEMP_OUT_OF_RANGE_COUNT ( MS_PER_SECOND / ( 4 * TASK_GENERAL_INTERVAL ) ) ///< Thermistors/sensors maximum allowed temperature out of range count. /// Thermistors self test states typedef enum thermistors_Self_Test_States { - THERMISTORS_SELF_TEST_START = 0, ///< Thermistors self test start - THERMISTROS_SELF_TEST_ADC_CHECK, ///< Thermistors self test ADC check - THERMISTORS_SELF_TEST_COMPLETE, ///< Thermistors self test complete - NUM_OF_THERMISTORS_SEsLF_TEST_STATES, ///< Number of thermistors self test states + THERMISTROS_SELF_TEST_CHECK_RANGE = 0, ///< Thermistors self test range check + THERMISTORS_SELF_TEST_COMPLETE, ///< Thermistors self test complete + NUM_OF_THERMISTORS_SELF_TEST_STATES, ///< Number of thermistors self test states } THERMISTORS_SELF_TEST_STATES_T; /// Thermistors exec states @@ -49,23 +49,30 @@ { S32 rawADCRead; ///< Thermistor raw ADC read OVERRIDE_F32_T temperatureValue; ///< Thermistor temperature value + U32 tempOutOfRangeCount; ///< Thermistor temperature out of range counter } THERMISTOR_T; -static SELF_TEST_STATUS_T thermistorsSelfTestReslt = SELF_TEST_STATUS_IN_PROGRESS; ///< Thermistors self test result -static THERMISTORS_SELF_TEST_STATES_T thermistorsSelfTestState = THERMISTORS_SELF_TEST_START; ///< Thermistors self test state -static THERMISTORS_EXEC_STATES_T thermistorsExecState = THERMISTORS_EXEC_STATE_START; ///< Thermistors exec state -static THERMISTOR_T thermistorsStatus[ NUM_OF_THERMISTORS ]; ///< Thermistors array +static SELF_TEST_STATUS_T thermistorsSelfTestReslt = SELF_TEST_STATUS_IN_PROGRESS; ///< Thermistors self test result +static THERMISTORS_SELF_TEST_STATES_T thermistorsSelfTestState = THERMISTROS_SELF_TEST_CHECK_RANGE; ///< Thermistors self test state +static THERMISTORS_EXEC_STATES_T thermistorsExecState = THERMISTORS_EXEC_STATE_START; ///< Thermistors exec state +static THERMISTOR_T thermistorsStatus[ NUM_OF_THERMISTORS ]; ///< Thermistors array static OVERRIDE_U32_T thermistorsPublishInterval = { THERMISTORS_DATA_PUBLISH_INTERVAL, - THERMISTORS_DATA_PUBLISH_INTERVAL, 0, 0 }; ///< Thermistors publish time interval override -static U32 dataPublishCounter; ///< Thermistors data publish timer counter -static U32 adcReadCounter; ///< Thermistors ADC read counter + THERMISTORS_DATA_PUBLISH_INTERVAL, 0, 0 }; ///< Thermistors publish time interval override +static U32 dataPublishCounter; ///< Thermistors data publish timer counter +static U32 adcReadCounter; ///< Thermistors ADC read counter -static const F32 fpgaBoardTempSensorConvCoeff = 503.975 / TWELVE_BIT_RESOLUTION; ///< FPGA board temperature sensor conversion coefficient -static const F32 adcTempSensorsConversionCoeff1 = 1 / 13584; ///< ADC temperature sensors conversion coefficient 1 -static const F32 adcTempSensorsConversionCoeff2 = 0x800000 / 13584; ///< ADC temperature sensors conversion coefficient 2 +static const F32 fpgaBoardTempSensorConvCoeff = 503.975 / TWELVE_BIT_RESOLUTION; ///< FPGA board temperature sensor conversion coefficient +static const F32 adcTempSensorsConversionCoeff1 = 1 / 13584; ///< ADC temperature sensors conversion coefficient 1 +static const F32 adcTempSensorsConversionCoeff2 = 0x800000 / 13584; ///< ADC temperature sensors conversion coefficient 2 +static const F32 onBoardThermistorVoltageConvCoeff = ONBOARD_THERMISTOR_SOURCE_VOLTAGE / + TWELVE_BIT_RESOLUTION; ///< On board thermistor ADC to voltage conversion coefficient +static const F32 onBoardThermistorBetaValueInv = 1 / ONBOARD_THERMISTOR_BETA_VALUE; ///< On board thermistor beta value inverse +static const F32 onBoardThermistorRefTempInv = 1 / ONBOARD_THERMISTOR_REFERENCE_TEMPERATURE; ///< On board thermistor reference temONBOARD_THERMISTOR_REFERENCE_TEMPERATUREperature inverse // ********** private function prototypes ********** +static THERMISTORS_SELF_TEST_STATES_T handleSelfTestRangeCheck( void ); + static THERMISTORS_EXEC_STATES_T handleExecStart( void ); static THERMISTORS_EXEC_STATES_T handleExecGetADCValues( void ); @@ -86,10 +93,18 @@ *************************************************************************/ void initThermistors( void ) { + THERMISTORS_TEMP_SENSORS_T thermistor; + + // Reset the thermistors values for a run thermistorsSelfTestReslt = SELF_TEST_STATUS_IN_PROGRESS; thermistorsExecState = THERMISTORS_EXEC_STATE_START; - thermistorsSelfTestState = THERMISTORS_SELF_TEST_START; + thermistorsSelfTestState = THERMISTROS_SELF_TEST_CHECK_RANGE; dataPublishCounter = 0; + + for ( thermistor = THERMISTOR_ONBOARD_NTC; thermistor < NUM_OF_THERMISTORS; thermistor++ ) + { + thermistorsStatus[ thermistor ].tempOutOfRangeCount = 0; + } } /*********************************************************************//** @@ -103,17 +118,16 @@ { switch ( thermistorsSelfTestState ) { - case THERMISTORS_SELF_TEST_START: + case THERMISTROS_SELF_TEST_CHECK_RANGE: + thermistorsSelfTestState = handleSelfTestRangeCheck(); break; - case THERMISTROS_SELF_TEST_ADC_CHECK: - break; - case THERMISTORS_SELF_TEST_COMPLETE: // Done with POST. Do nothing. break; default: + // Wrong state was called, raise an alarm SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_THERMISTORS_INVALID_SELF_TEST_STATE, thermistorsSelfTestState ); thermistorsSelfTestState = THERMISTORS_SELF_TEST_COMPLETE; break; @@ -142,6 +156,7 @@ break; default: + // Wrong state was called, raise an alarm SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_THERMISTORS_INVALID_EXEC_STATE, thermistorsExecState ); thermistorsExecState = THERMISTORS_EXEC_STATE_GET_ADC_VALUES; break; @@ -186,6 +201,61 @@ /*********************************************************************//** * @brief + * The handleSelfTestRangeCheck function checks whether the thermistors + * are in range upon staring the device. + * @details Inputs: thermistorsStatus, adcReadCounter + * @details Outputs: thermistorsStatus, adcReadCounter + * @return next state of self test + *************************************************************************/ +static THERMISTORS_SELF_TEST_STATES_T handleSelfTestRangeCheck( void ) +{ + THERMISTORS_SELF_TEST_STATES_T state = THERMISTROS_SELF_TEST_CHECK_RANGE; + + // Give a short time for FPGA to boot up and start sending the ADC reads + if ( ++adcReadCounter > ADC_FPGA_READ_DELAY_COUNT ) + { + THERMISTORS_TEMP_SENSORS_T thermistor; + F32 temperature; + + // Assuming self test passed + thermistorsSelfTestReslt = SELF_TEST_STATUS_PASSED; + + // Get all the raw readings in ADC + thermistorsStatus[ THERMISTOR_ONBOARD_NTC ].rawADCRead = getIntADCReading( INT_ADC_BOARD_THERMISTOR ); + thermistorsStatus[ TEMPSENSOR_FPGA_SENSOR ].rawADCRead = getFPGABoardTemp(); + thermistorsStatus[ TEMPSENSOR_LOAD_CELL_A1 ].rawADCRead = getFPGALoadCellsA1B1Temp(); + thermistorsStatus[ TEMPSENSOR_LOAD_CELL_A2 ].rawADCRead = getFPGALoadCellsA2B2Temp(); + thermistorsStatus[ TEMPSENSOR_INTERNAL_THDO_RTD ].rawADCRead = getFPGATHDoInternalTemp(); + thermistorsStatus[ TEMPSENSOR_INTERNAL_TDI_RTD ].rawADCRead = getFPGATDiInternalTemp(); + thermistorsStatus[ TEMPSENSOR_INTERNAL_CONDUCTIVITY ].rawADCRead = getFPGAConductivitySnsrInternalTemp(); + thermistorsStatus[ THERMISTOR_POWER_SUPPLY_1 ].rawADCRead = getIntADCReading( INT_ADC_POWER_SUPPLY_1_THERMISTOR ); + thermistorsStatus[ THERMISTOR_POWER_SUPPLY_2 ].rawADCRead = getIntADCReading( INT_ADC_POWER_SUPPLY_2_THERMISTOR ); + + // Convert the ADC values to temperature + convertADCtoTemperature(); + + for ( thermistor = THERMISTOR_ONBOARD_NTC; thermistor < NUM_OF_THERMISTORS; thermistor++ ) + { + // Get the actual temperature value and not the override value + temperature = thermistorsStatus[ thermistor ].temperatureValue.data; + // If the values are out of range, raise an alarm + if ( temperature < MIN_ALLOWED_TEMPERATURE || temperature >= MAX_ALLOWED_TEMPERATURE ) + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_THERMISOTRS_TEMPERATURE_OUT_OF_RANGE, thermistor, temperature ); + // If any thermistor/sensor is not in range, POST has failed + thermistorsSelfTestReslt = SELF_TEST_STATUS_FAILED; + } + } + // Done with POST + state = THERMISTORS_SELF_TEST_COMPLETE; + adcReadCounter = 0; + } + + return state; +} + +/*********************************************************************//** + * @brief * The handleExecStart function handles the start state of the exec state * machine. * @details Inputs: adcReadCounter @@ -222,13 +292,15 @@ if ( ++adcReadCounter >= THERMISTORS_ADC_READ_INTERVAL ) { // Get all the raw readings in ADC - thermistorsStatus[ THERMISTOR_ONBOARD_NTC ].rawADCRead = getIntADCReading( INT_ADC_BOARD_THERMISTOR ); - thermistorsStatus[ TEMPSENSOR_FPGA_SENSOR ].rawADCRead = getFPGABoardTemp(); - thermistorsStatus[ TEMPSENSOR_LOAD_CELL_A1 ].rawADCRead = getFPGALoadCellsA1B1Temp(); - thermistorsStatus[ TEMPSENSOR_LOAD_CELL_A2 ].rawADCRead = getFPGALoadCellsA2B2Temp(); - thermistorsStatus[ TEMPSENSOR_THDO_RTD ].rawADCRead = getFPGATHDoInternalTemp(); - thermistorsStatus[ TEMPSENSOR_TDI_RTD ].rawADCRead = getFPGATDiInternalTemp(); - thermistorsStatus[ TEMPSENSOR_CONDUCTIVITY ].rawADCRead = getFPGAConductivitySnsrInternalTemp(); + thermistorsStatus[ THERMISTOR_ONBOARD_NTC ].rawADCRead = getIntADCReading( INT_ADC_BOARD_THERMISTOR ); + thermistorsStatus[ TEMPSENSOR_FPGA_SENSOR ].rawADCRead = getFPGABoardTemp(); + thermistorsStatus[ TEMPSENSOR_LOAD_CELL_A1 ].rawADCRead = getFPGALoadCellsA1B1Temp(); + thermistorsStatus[ TEMPSENSOR_LOAD_CELL_A2 ].rawADCRead = getFPGALoadCellsA2B2Temp(); + thermistorsStatus[ TEMPSENSOR_INTERNAL_THDO_RTD ].rawADCRead = getFPGATHDoInternalTemp(); + thermistorsStatus[ TEMPSENSOR_INTERNAL_TDI_RTD ].rawADCRead = getFPGATDiInternalTemp(); + thermistorsStatus[ TEMPSENSOR_INTERNAL_CONDUCTIVITY ].rawADCRead = getFPGAConductivitySnsrInternalTemp(); + thermistorsStatus[ THERMISTOR_POWER_SUPPLY_1 ].rawADCRead = getIntADCReading( INT_ADC_POWER_SUPPLY_1_THERMISTOR ); + thermistorsStatus[ THERMISTOR_POWER_SUPPLY_2 ].rawADCRead = getIntADCReading( INT_ADC_POWER_SUPPLY_2_THERMISTOR ); // Zero the counter for the next round of reading adcReadCounter = 0; @@ -263,16 +335,27 @@ // If the thermisotrs and sensors read temperature out of range, raise an alarm if ( temperature < MIN_ALLOWED_TEMPERATURE || temperature >= MAX_ALLOWED_TEMPERATURE ) { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_THERMISOTRS_TEMPERATURE_OUT_OF_RANGE, thermistor, temperature ); + // If a thermistor/sensor has been out of range consistently, raise an alarm + if ( ++thermistorsStatus[ thermistor ].tempOutOfRangeCount > MAX_ALLOWED_TEMP_OUT_OF_RANGE_COUNT ) + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_THERMISOTRS_TEMPERATURE_OUT_OF_RANGE, thermistor, temperature ); + thermistorsStatus[ thermistor ].tempOutOfRangeCount = 0; + } } + // If the next temperature reading is in range but the counter was greater than 0, reset + else if ( thermistorsStatus[ thermistor ].tempOutOfRangeCount > 0 ) + { + thermistorsStatus[ thermistor ].tempOutOfRangeCount = 0; + } } } /*********************************************************************//** * @brief * The convertADCtoTemperature function converts the ADC values of different * thermistors and temperature sensors to temperature value. - * @details Inputs: thermistorsStatus + * @details Inputs: thermistorsStatus, fpgaBoardTempSensorConvCoeff, + * adcTempSensorsConversionCoeff1, adcTempSensorsConversionCoeff2 * @details Outputs: thermistorsStatus * @param thermistor (also covers the temperature sensors) to convert its value * @return none @@ -297,21 +380,26 @@ break; case TEMPSENSOR_FPGA_SENSOR: + // Temperature(C) = ((ADC x 503.975) / 4096) - 273.15 + // The value of 503.975/4096 was done in a const variable to prevent the division all the time temperature = ( rawADC * fpgaBoardTempSensorConvCoeff ) - CELSIUS_TO_KELVIN_CONVERSION; thermistorsStatus[ TEMPSENSOR_FPGA_SENSOR ].temperatureValue.data = temperature; break; // All these sensors have the same conversion procedure case TEMPSENSOR_LOAD_CELL_A1: case TEMPSENSOR_LOAD_CELL_A2: - case TEMPSENSOR_THDO_RTD: - case TEMPSENSOR_TDI_RTD: - case TEMPSENSOR_CONDUCTIVITY: + case TEMPSENSOR_INTERNAL_THDO_RTD: + case TEMPSENSOR_INTERNAL_TDI_RTD: + case TEMPSENSOR_INTERNAL_CONDUCTIVITY: + // Temperature(C) = ((ADC - 0x800000)/13584) - 272.5 + // The values for 1/0x800000 and 0x800000/13584 were done in a const variable to prevent the division all the time temperature = ( ( rawADC * adcTempSensorsConversionCoeff1 ) - adcTempSensorsConversionCoeff2 ) - ADC_TEMP_SENSORS_CONVERSION_CONST; thermistorsStatus[ thermistor ].temperatureValue.data = temperature; break; default: + // Wrong sensor was called, raise an alarm SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_THERMISTOR_SELECTED, thermistor ); break; } @@ -322,20 +410,32 @@ * @brief * The calcualteOnBoardThemristorTemperature function converts the ADC value * of the onboard thermistor into temperature in C - * @details Inputs: none + * @details Inputs: onBoardThermistorVoltageConvCoeff, + * onBoardThermistorBetaValueInv * @details Outputs: none * @param ADC value to be converted into temperature in C * @return calculated temperature in C *************************************************************************/ static F32 calculateOnBoardThemristorTemperature( U32 adcValue ) { - //TODO add comments - F32 thermistorVoltage = ( adcValue * ONBOARD_THERMISTOR_SOURCE_VOLTAGE ) / TWELVE_BIT_RESOLUTION; - F32 thermistorResistor = ( ( ONBOARD_THERMISTOR_REFERENCE_RESISTOR * ONBOARD_THERMISTOR_SOURCE_VOLTAGE ) - + /* + * voltage = ADC x 3 / 2^12 + * voltage = 3 x 10 / ( 10 + R(T) ) + * R(T) = 10 x e^(3380 x (1/T - 1/298)) + * Solve for T which is temperature in Kelvin + */ + + // Voltage = ADC x 3 / 2^12 for 12 bits resolution and a 3V ADC + // The value of 3 / 2^12 has been calculated in a const to prevent the division again + F32 const thermistorVoltage = adcValue * onBoardThermistorVoltageConvCoeff; + // Calculate the thermistor resistor by solving: thermistorVoltage = (3 x 10) / (10 + R(T)) + F32 const thermistorResistor = ( ( ONBOARD_THERMISTOR_REFERENCE_RESISTOR * ONBOARD_THERMISTOR_SOURCE_VOLTAGE ) - ( ONBOARD_THERMISTOR_REFERENCE_RESISTOR * thermistorVoltage ) ) / thermistorVoltage; - F32 InvTemperature = ( logf(thermistorResistor/ONBOARD_THERMISTOR_REFERENCE_RESISTOR) / ONBOARD_THERMISTOR_BETA_VALUE ) + - ( 1 / ONBOARD_THERMISTOR_REFERENCE_TEMPERATURE); - F32 temperature = 1 / InvTemperature; + // 1/T = Ln(thermistorResistor/10)/3380 + 1/298 + F32 const InvTemperature = ( logf( thermistorResistor / ONBOARD_THERMISTOR_REFERENCE_RESISTOR ) * onBoardThermistorBetaValueInv ) + + onBoardThermistorRefTempInv; + // Inverse the value to get the temperature in Kelvin and then convert it to Celsius + F32 const temperature = ( 1 / InvTemperature ) - CELSIUS_TO_KELVIN_CONVERSION; return temperature; } @@ -374,14 +474,16 @@ { THERMISTORS_DATA_T sensorsData; - // Get all the sensors/thermistors values for publication + // Get all the sensors/thermistors temperature values for publication sensorsData.onboardThermistor = getThermistorTemperatureValue( THERMISTOR_ONBOARD_NTC ); - sensorsData.fpgaBoardTempSensor = getFPGABoardTemp(); - sensorsData.loadCellA1TempSensor = getFPGALoadCellsA1B1Temp(); - sensorsData.loadCellA2TempSensor = getFPGALoadCellsA2B2Temp(); - sensorsData.rtdInternalTempSensor = getFPGATHDoInternalTemp(); - sensorsData.rtdTDiInternalTempSensor = getFPGATDiInternalTemp(); - sensorsData.conductivityTempSensor = getFPGAConductivitySnsrInternalTemp(); + sensorsData.fpgaBoardTempSensor = getThermistorTemperatureValue( TEMPSENSOR_FPGA_SENSOR ); + sensorsData.loadCellA1TempSensor = getThermistorTemperatureValue( TEMPSENSOR_LOAD_CELL_A1 ); + sensorsData.loadCellA2TempSensor = getThermistorTemperatureValue( TEMPSENSOR_LOAD_CELL_A2 ); + sensorsData.rtdInternalTempSensor = getThermistorTemperatureValue( TEMPSENSOR_INTERNAL_THDO_RTD ); + sensorsData.rtdTDiInternalTempSensor = getThermistorTemperatureValue( TEMPSENSOR_INTERNAL_TDI_RTD ); + sensorsData.conductivityTempSensor = getThermistorTemperatureValue( TEMPSENSOR_INTERNAL_CONDUCTIVITY ); + sensorsData.powerSupply1Thermistor = getThermistorTemperatureValue( THERMISTOR_POWER_SUPPLY_1 ); + sensorsData.powerSupply2Thermistor = getThermistorTemperatureValue( THERMISTOR_POWER_SUPPLY_2 ); // Broadcast the thermistors data broadcastThermistorsData( &sensorsData ); @@ -495,7 +597,6 @@ } return result; - } /**@}*/