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.