一、概述
NTC是Negative Temperature Coefficient 的缩写,意思是负的温度系数,泛指负温度系数很大的半导体材料或元器件,通常我们提到的NTC是指负温度系数热敏电阻,简称NTC热敏电阻。又被称为负温度系数热敏电阻,是一类电阻值随温度增大而减小的一种传感器电阻。
NTC的选型有两个比较重要的参数,一个是25℃的阻值,另一个是B常数(25/50℃),如果两个NTC的这两项参数一样,它们的NTC阻值和温度的曲线也差不多相似,可以进行替代。
电路采用10K的B值3950的NTC,3.3v经过10K阻值的电阻,再经过NTC接地,io2测量NTC的分压值。25°C时NTC阻值10K,大概分压到1650mV,温度越高分压越低。
二、代码
利用ESP32C3的ADC,采样ntc的分压值,再计算出ntc的阻值,再算出温度值。根据电压的大小,动态调整采样的衰减值(测量范围)。ADC采样输出电压值最大2885mV,可测最低-13°C的温度,如果要测量更低温度,需要提高NTC前面电阻的阻值。
#include "driver/adc.h"
#include "math.h"
void ntc_task(void){
#define ADC1_CHAN0 ADC1_CHANNEL_2
#define ADC_ATTEN ADC_ATTEN_DB_11
#define ADC_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_TP
static int adc_raw[8];
static int adc_raw_mean;//
static esp_adc_cal_characteristics_t adc1_chars;
adc_atten_t adc_atten_db = ADC_ATTEN;//max 2500 mV
uint8_t adc_atten_db_update = 0;
uint32_t voltage = 0,resistent = 0;//voltage max value: 2885 mV
float temp=0.0;
esp_adc_cal_characterize(ADC_UNIT_1, adc_atten_db, ADC_WIDTH_BIT_DEFAULT, 0, &adc1_chars);
//ADC1 config
ESP_ERROR_CHECK(adc1_config_width(ADC_WIDTH_BIT_DEFAULT));
ESP_ERROR_CHECK(adc1_config_channel_atten(ADC1_CHAN0, adc_atten_db));
printf("default adc_atten_db = %d\r\n",adc_atten_db);
while (1) {
adc_raw[0] = adc1_get_raw(ADC1_CHAN0);
adc_raw[1] = adc1_get_raw(ADC1_CHAN0);
adc_raw[2] = adc1_get_raw(ADC1_CHAN0);
adc_raw[3] = adc1_get_raw(ADC1_CHAN0);
adc_raw_mean = (adc_raw[0] + adc_raw[1] + adc_raw[2] + adc_raw[3])>>2;//mean of last 4 raw data
//ESP_LOGI(TAG_CH, "raw data: %d", adc_raw_mean);
#define NTC_B 3950
#define NTC_Rp 10000
#define NTC_RES_PULLUP 10000
voltage = esp_adc_cal_raw_to_voltage(adc_raw_mean, &adc1_chars);
resistent = NTC_RES_PULLUP*voltage/(3300-voltage);
temp = 1/(1/298.15 + log((float)resistent/NTC_Rp)/NTC_B) - 273.15;
printf("cali data: %d mV, resistent %5d, temp %.1f\r\n", voltage,resistent,temp);
if(voltage >1350){
if(adc_atten_db != ADC_ATTEN_DB_11){
adc_atten_db = ADC_ATTEN_DB_11;
adc_atten_db_update = 1;
printf("adc_atten_db = %d\r\n",adc_atten_db);
esp_adc_cal_characterize(ADC_UNIT_1, adc_atten_db, ADC_WIDTH_BIT_DEFAULT, 0, &adc1_chars);
ESP_ERROR_CHECK(adc1_config_channel_atten(ADC1_CHAN0, adc_atten_db));
}
}else if(voltage <1350 && voltage > 1050){
if(adc_atten_db != ADC_ATTEN_DB_6){
adc_atten_db = ADC_ATTEN_DB_6;
adc_atten_db_update = 1;
}
}else if(voltage < 1050 && voltage > 750){
if(adc_atten_db != ADC_ATTEN_DB_2_5){
adc_atten_db = ADC_ATTEN_DB_2_5;
adc_atten_db_update = 1;
}
}else if(voltage < 750){
if(adc_atten_db != ADC_ATTEN_DB_0){
adc_atten_db = ADC_ATTEN_DB_0;
adc_atten_db_update = 1;
}
}
if(adc_atten_db_update){
printf("adc_atten_db = %d\r\n",adc_atten_db);
esp_adc_cal_characterize(ADC_UNIT_1, adc_atten_db, ADC_WIDTH_BIT_DEFAULT, 0, &adc1_chars);
ESP_ERROR_CHECK(adc1_config_channel_atten(ADC1_CHAN0, adc_atten_db));
adc_atten_db_update = 0;
}
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
void app_main(void)
{
ntc_task();
}
三、效果图
四、影响精度的因素
上拉电阻的阻值,NTC的阻值,B值,ADC的精度,都会影响输出精度,本身NTC精度也不太高。