MKW30Z temperature sensor calibration

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MKW30Z temperature sensor calibration

Jump to solution
1,722 Views
lucianfiran
Contributor V

KW40Z_Connectivity_Software_1.0.1 (KSDK_1.3.0) IAR 7.5

MKW40Z/30Z/20Z Reference Manual, Rev. 1.2, 10/2015
28.4.8 Temperature sensor     links to

Temperature Sensor for the HCS08 Microcontroller Family (document AN3031).

http://cache.freescale.com/files/microcontrollers/doc/app_note/AN3031.pdf

witch presents a calibration implementation:

Floating-Point
Calibrated (3 Points) Typical Accuracy ± 2.5degs C
Uncalibrated  Typical Accuracy ± 8degs C

Fixed-Point
Calibrated (3 Points) Typical Accuracy ± 12degs C
Uncalibrated  Typical Accuracy ± 18degs C

In conclusion having fixed-point arithmetic calibrated and un-calibrated does not help you at all...

Having no calibration at all and floating point algo goes to ±8 deg C with is quite hight.

3 point calibration gives good result but is hard to achieve in production (as time and resources).

In production, one point calibration is the easiest to do - measure by chip and measure by reference thermometer near chip.
(@ room temperature)

The HCS08 AN3031 document is accurate on MKW30Z ?

Is some sort of calibration implemented in framework ?

What would be the Calibrated 1 Point Typical Accuracy ?

Thank you,

Lucian

1 Solution
1,193 Views
egoodii
Senior Contributor III

That should work fine -- so your calibration process will yield a 'better' V_TEMP25 (instead of the #define), OR maybe you will want to define a different calibration point (if you can in production) closer to the 'temp range of interest', like around 60C for STANDARD_TEMP; but I WOULD use a constant for adcr100m(ADCR_VDD*100/3300), since your Vdd 'reference' will already be BETTER than the on-chip bandgap.  And with that, slope error, and others you can expect 'worst case' +/-15C tolerance, usually MUCH better.  You will want to 'estimate' the on-chip to LED-chip differential in 'steady state' in the assembled product.

View solution in original post

5 Replies
1,193 Views
egoodii
Senior Contributor III

On-chip temperature Calculations in which I show that with a 'good reference' and single-point (offset) calibration you could guarantee +/-2C 0to50C, using 32bit integer math.

Applies, as far as I know, to ANY former-Freescale microcontroller's temp-sense module (with allowance for the fact that 'older' parts published two slope factors).

1,193 Views
lucianfiran
Contributor V


I understand that the AN is quite old and should be updated !
(Motorola, Freescale, NXP, Qualcomm)

The MKW30Z chip can use floating point math.

The chip measures die temperature or ambient temperature ?

6.4.1 Thermal operating requirements
TJ Die junction temperature –40 100 °C
TA Ambient temperature –40 85 °C

(Max/min expected temp value ?)

How many bits can we use (meters) ?

differential 16-bit, 13-bit, 11-bit, and 9-bit modes
single-ended 16-bit, 12-bit, 10-bit, and 8-bit modes

ADC reference voltage selection.

Variants:
- internal band-gap
- external LDO NCP1117 (3.235V -> 3.365V) (Tlow = 0°C ,Thigh = 125°C)
- external special reference
- external DCDC convertor (buck/boost)

Witch is better NCP1117 3.3V (reference design) or internal band-gap ?


Possible calibrations:

No Calibrattion
1 point calibration (Vtemp25C)
2 point calibration (Vtemp25C + hot slope)
2 point calibration (Vtemp25C + cold slope)
3 point calibration (Vtemp25C + hot, cold slope)
n point calibration

Should we use a dual slope factor ( -40 to 25 to 100) or single  ?

What about MKW30Z framework implementations ?

On frdm_kw40z_demo_1.0 - current chip temperature with a 0.01 °C resolution.

Seems a no calibration implementation.

#define TEMPERATURE_SENSOR_V_BANDGAP_mV         1000    /*!< Bandgap ADC channel voltage (in mV) */
#define TEMPERATURE_SENSOR_ADC_RESOLUTION       32768   /*!< Expanded resolution value 2^Resolution */
#define TEMPERATURE_SENSOR_VTEMP25_mV           716     /*!< Temperature sensor voltage @25C defined by the datasheet */
#define TEMPERATURE_SENSOR_SLOPE_uV             1620    /*!< Temperature sensor slope (in uV) defined by the datasheet */

int16_t temperature_sensor_get_chip_temperature (void){
  adc16_status_t result;
  int16_t bandgapVoltageAdcReading, temperatureChannelAdcReading;
  int16_t vReference, vTemperatureSensor;
  int16_t temperatureReading;
 
  /* Start Bandgap Voltage Measurements */
  result = ADC16_DRV_ConfigConvChn(TEMPERATURE_SENSOR_ADC_INSTANCE, 0, &temperatureSensorBandgapVoltageChannel);
 
  if(result != kStatus_ADC16_Success)
    return kTemperatureSensorConversionStartError;
 
  /* Wait for bandgap voltage measurement reading */
  ADC16_DRV_WaitConvDone (TEMPERATURE_SENSOR_ADC_INSTANCE, 0);
 
  /* Get bandgap measurement */
  bandgapVoltageAdcReading = ADC16_DRV_GetConvValueSigned (TEMPERATURE_SENSOR_ADC_INSTANCE, 0);  
 
  /* Start Temperature Channel Measurements */
  result = ADC16_DRV_ConfigConvChn(TEMPERATURE_SENSOR_ADC_INSTANCE, 0, &temperatureSensorChipTemperatureChannel);
 
  if(result != kStatus_ADC16_Success)
    return kTemperatureSensorConversionStartError;
 
  /* Wait for temperature channel measurement reading */
  ADC16_DRV_WaitConvDone (TEMPERATURE_SENSOR_ADC_INSTANCE, 0);
 
  /* Get temperature channel measurement */
  temperatureChannelAdcReading = ADC16_DRV_GetConvValueSigned (TEMPERATURE_SENSOR_ADC_INSTANCE, 0);
 
  /* Calculate Reference Voltage */
  vReference = (int16_t)((TEMPERATURE_SENSOR_V_BANDGAP_mV * TEMPERATURE_SENSOR_ADC_RESOLUTION)/bandgapVoltageAdcReading);
 
  /* Calculate Temperature Sensor Voltage */
  vTemperatureSensor = (int16_t)((vReference*temperatureChannelAdcReading)/TEMPERATURE_SENSOR_ADC_RESOLUTION);
 
  /* Obtain temperature measurement*/
  temperatureReading = 2500 - (((vTemperatureSensor - TEMPERATURE_SENSOR_VTEMP25_mV)*1000*100)/TEMPERATURE_SENSOR_SLOPE_uV);
 
  return temperatureReading;
}


Another implementation bluetooth_temperature_sensor on temp_sensor.c

/*!
 * @brief These values are used to get the temperature. DO NOT MODIFY
 * The method used in this demo to calculate temperature of chip is mapped to
 * Temperature Sensor for the HCS08 Microcontroller Family document (Document Number: AN3031)
 */
#define ADCR_VDD                (65535U)    // Maximum value when use 16b resolution
#define V_BG                    (1000U)     // BANDGAP voltage in mV (trim to 1.0V)
#define V_TEMP25                (716U)      // Typical converted value at 25 oC in mV
#define M                       (1620U)     // Typical slope:uV/oC
#define STANDARD_TEMP           (25)

#define ADC16_INSTANCE                (0)   // ADC instacne
#define ADC16_TEMPERATURE_CHN         (kAdc16Chn26) // Temperature Sensor Channel
#define ADC16_BANDGAP_CHN             (kAdc16Chn27) // ADC channel of BANDGAP
#define ADC16_CHN_GROUP               (0)   // ADC group configuration selection

uint32_t adcValue = 0;               // ADC value
uint32_t adcrTemp25 = 0;             // Calibrated ADCR_TEMP25
uint32_t adcr100m = 0;               // calibrated conversion value of 100mV
adc16_converter_config_t adcUserConfig1;   // structure for user config


int32_t TempSensor_GetTemperature(void)
{
    int32_t currentTemp = 0;
    adc16_chn_config_t chnConfig;

    // Configure the conversion channel
    // differential and interrupt mode disable.
    chnConfig.chnIdx     = (adc16_chn_t)ADC16_TEMPERATURE_CHN;
#if FSL_FEATURE_ADC16_HAS_DIFF_MODE
    chnConfig.diffConvEnable = false;
#endif
    chnConfig.convCompletedIntEnable  = false;

    // Software trigger the conversion.
    ADC16_DRV_ConfigConvChn(ADC16_INSTANCE, ADC16_CHN_GROUP, &chnConfig);

    // Wait for the conversion to be done.
    ADC16_DRV_WaitConvDone(ADC16_INSTANCE, ADC16_CHN_GROUP);

    // Fetch the conversion value.
    adcValue = ADC16_DRV_GetConvValueSigned(ADC16_INSTANCE, ADC16_CHN_GROUP);

    // Calculates adcValue in 16bit resolution
    // from 12bit resolution in order to convert to temperature.
#if (FSL_FEATURE_ADC16_MAX_RESOLUTION < 16)
    adcValue = adcValue << 4;
#endif

    // Multiplied by 1000 because M in uM/oC
    // Temperature = 25 - (ADCR_T - ADCR_TEMP25) * 100*1000 / ADCR_100M*M
    currentTemp = (int32_t)(STANDARD_TEMP - ((int32_t)adcValue - (int32_t)adcrTemp25) * 100000 /(int32_t)(adcr100m*M));

    // Pause the conversion.
    ADC16_DRV_PauseConv(ADC16_INSTANCE, ADC16_CHN_GROUP);

    return currentTemp;
}


 /*!
 * @brief Parameters calibration: VDD and ADCR_TEMP25
 *
 * This function used BANDGAP as reference voltage to measure vdd and
 * calibrate V_TEMP25 with that vdd value.
 */
static void calibrateParams(void)
{
    adc16_chn_config_t adcChnConfig;
#if FSL_FEATURE_ADC16_HAS_HW_AVERAGE
    adc16_hw_average_config_t userHwAverageConfig;
#endif
    pmc_bandgap_buffer_config_t pmcBandgapConfig = {
        .enable = true,
#if FSL_FEATURE_PMC_HAS_BGEN
        .enableInLowPower = false,
#endif
#if FSL_FEATURE_PMC_HAS_BGBDS
        .drive = kPmcBandgapBufferDriveLow,
#endif
    };

    uint32_t bandgapValue = 0;  // ADC value of BANDGAP
    uint32_t vdd = 0;           // VDD in mV

#if FSL_FEATURE_ADC16_HAS_CALIBRATION
    // Auto calibration
    adc16_calibration_param_t adcCalibraitionParam;
    ADC16_DRV_GetAutoCalibrationParam(ADC16_INSTANCE, &adcCalibraitionParam);
    ADC16_DRV_SetCalibrationParam(ADC16_INSTANCE, &adcCalibraitionParam);
#endif // FSL_FEATURE_ADC16_HAS_CALIBRATION.

    // Enable BANDGAP reference voltage
    PMC_HAL_BandgapBufferConfig(PMC_BASE_PTR, &pmcBandgapConfig);

#if FSL_FEATURE_ADC16_HAS_HW_AVERAGE
    // Use hardware average to increase stability of the measurement.
    userHwAverageConfig.hwAverageEnable = true;
    userHwAverageConfig.hwAverageCountMode = kAdc16HwAverageCountOf32;
    ADC16_DRV_ConfigHwAverage(ADC16_INSTANCE, &userHwAverageConfig);
#endif // FSL_FEATURE_ADC16_HAS_HW_AVERAGE

    // Configure the conversion channel
    // differential and interrupt mode disable.
    adcChnConfig.chnIdx                  = (adc16_chn_t)ADC16_BANDGAP_CHN;
#if FSL_FEATURE_ADC16_HAS_DIFF_MODE
    adcChnConfig.diffConvEnable          = false;
#endif
    adcChnConfig.convCompletedIntEnable  = false;
    ADC16_DRV_ConfigConvChn(ADC16_INSTANCE, ADC16_CHN_GROUP, &adcChnConfig);

    // Wait for the conversion to be done
    ADC16_DRV_WaitConvDone(ADC16_INSTANCE, ADC16_CHN_GROUP);

    // Get current ADC BANDGAP value and format it.
    bandgapValue = ADC16_DRV_GetConvValueSigned(ADC16_INSTANCE, ADC16_CHN_GROUP);
    // Calculates bandgapValue in 16bit resolution
    // from 12bit resolution to calibrate.
#if (FSL_FEATURE_ADC16_MAX_RESOLUTION < 16)
    bandgapValue = bandgapValue << 4;
#endif
    // ADC stop conversion
    ADC16_DRV_PauseConv(ADC16_INSTANCE, ADC16_CHN_GROUP);

    // Get VDD value measured in mV
    // VDD = (ADCR_VDD x V_BG) / ADCR_BG
    vdd = ADCR_VDD * V_BG / bandgapValue;
    // Calibrate ADCR_TEMP25
    // ADCR_TEMP25 = ADCR_VDD x V_TEMP25 / VDD
    adcrTemp25 = ADCR_VDD * V_TEMP25 / vdd;
    // Calculate conversion value of 100mV.
    // ADCR_100M = ADCR_VDD x 100 / VDD
    adcr100m = ADCR_VDD*100/ vdd;

    // Disable BANDGAP reference voltage
    pmcBandgapConfig.enable = false;
    PMC_HAL_BandgapBufferConfig(PMC_BASE_PTR, &pmcBandgapConfig);
}


What about these implementations ?

How good are they ?

Thank you,

Lucian.

0 Kudos
1,193 Views
egoodii
Senior Contributor III

I can't go thru all that code in detail, but the concepts look like they follow my integer-implementation outlines -- with some debugging you can confirm the details.  temperature_sensor_get_chip_temperature looks most like my sequence, where you could 'skip' the vReference calculation (and use a constant) by using either 'good LDO' Vdd or a GOOD external voltage reference.  They also use some int16 where you might as well use int32 on a 32-bit processor.

The temperature measured is, of course, the CPU-chip's die temperature, more specifically 'at some particular point' on the die, but I suppose we can assume a 'small differential' across the die.

I would convert 16-bits; the Temp and BG channels are single-ended.

The internal bandgap is +/-2% 0to50C, +/-3% otherwise.  Your NCP LDO is +/-2% over that specified temp range, so 'somewhat better', but will contribute a +/-10C error-band, as per my writeup.  The temperature-cell-measurements are 'absolute voltages', and thus the conversion accuracy is directly related to the reference accuracy, and because the temperature-result is a DIFFERENCE of two similar numbers, conversion inaccuracy nets a much larger result-error.  To expect some 'real accuracy' will REQUIRE something like the 0.1%-accurate reference I suggest --- HOPEFULLY you have some other analog-functions for your system that would benefit from this precision reference!

AT LEAST make a single-point calibration (to remove the +/-6.2C offset error), where you take the 'measured temperature cell' voltage at a stable operating point, and as compared to a co-located reference-temperature in your production-test-fixture, will allow you to 'assume' the 1.62mV/C slope (617mC/mV) is 'close', and run down that slope to what the measured temperature cell value would be at 25C, and save THAT as Vtemp25mv.  The published slope error is only upto +/-.043C/C, so even at a 50C difference from 25C it only opens a +/-2.5C error-band, and is probably NOT worth the extra production time to correct from a 2nd calibration point.  We do assume here that the temp-cell output is LINEAR, which of course is only an approximation.  I assume the 'older chips' supplied two slopes to try to 'help' that linearization -- I don't personally know what any non-linearity error will contribute.

If you HAVE no 'other good use' for accurate Vref, I simply suggest dropping an ADT75A onto your I2C bus...precalibrated to deliver +/-3C -55to125C@Vdd=3.3V, and it WON'T be influenced (directly, at least!) by CPU-chip-heating.

1,193 Views
lucianfiran
Contributor V

In my application I have the chip surrounded by a lot of LEDs in a close box, lamp head.

At some critical threshold temperature I will start dimm all outputs as some factor proportional to temperature.

If the temperature continue to rise another failure threshold will be set and all outputs will be off.

With some hysteresis after cooling the leds will work again.

Considering  die junction temperature –40 100 °C surrounding chip ambient temperature is –40 85 °C

Worst used leds have Operating Temperature Range Topr -40°C to +80°C

So the region of interest is 60C - 75C ambient near chip temperature.

The board was design with a lot of ground plane to absorb and disperse the led temperature on surface

and a ~uniform temperature distribution on PCB.

I don't have any other other analog functions that require a 'good' reference.

If I use the LDO as reference will be an offset error of +/-10C error-band ?

If an 1 point calibration will be done, the reference thermometer will be close to chip.

The error is due to 2 conversions TempP and TempM.

pastedImage_1.png

The function TempSensor_GetTemperature use the values


uint32_t adcrTemp25 = 0;             // Calibrated ADCR_TEMP25
uint32_t adcr100m = 0;               // calibrated conversion value of 100mV
adc16_converter_config_t adcUserConfig1;   // structure for user config

    // Multiplied by 1000 because M in uM/oC
    // Temperature = 25 - (ADCR_T - ADCR_TEMP25) * 100*1000 / ADCR_100M*M
    currentTemp = (int32_t)(STANDARD_TEMP - ((int32_t)adcValue - (int32_t)adcrTemp25) * 100000 /(int32_t)(adcr100m*M));

generated by function calibrateParams

    // Get VDD value measured in mV
    // VDD = (ADCR_VDD x V_BG) / ADCR_BG
    vdd = ADCR_VDD * V_BG / bandgapValue;
    // Calibrate ADCR_TEMP25
    // ADCR_TEMP25 = ADCR_VDD x V_TEMP25 / VDD
    adcrTemp25 = ADCR_VDD * V_TEMP25 / vdd;
    // Calculate conversion value of 100mV.
    // ADCR_100M = ADCR_VDD x 100 / VDD
    adcr100m = ADCR_VDD*100/ vdd;

and the constants:

#define ADCR_VDD                (65535U)    // Maximum value when use 16b resolution
#define V_BG                    (1000U)     // BANDGAP voltage in mV (trim to 1.0V)
#define V_TEMP25                (716U)      // Typical converted value at 25 oC in mV
#define M                       (1620U)     // Typical slope:uV/oC
#define STANDARD_TEMP           (25)

Thank you,

Lucian

0 Kudos
1,194 Views
egoodii
Senior Contributor III

That should work fine -- so your calibration process will yield a 'better' V_TEMP25 (instead of the #define), OR maybe you will want to define a different calibration point (if you can in production) closer to the 'temp range of interest', like around 60C for STANDARD_TEMP; but I WOULD use a constant for adcr100m(ADCR_VDD*100/3300), since your Vdd 'reference' will already be BETTER than the on-chip bandgap.  And with that, slope error, and others you can expect 'worst case' +/-15C tolerance, usually MUCH better.  You will want to 'estimate' the on-chip to LED-chip differential in 'steady state' in the assembled product.