3、温度传感器应用:DS18B20、NTC热敏电阻、SHT30温湿度传感器驱动开发与校准

各位同学,大家好。今天我们来聊聊暖通空调系统里最基础、也最关键的环节——温度采集。

说实话,我在这个行业摸爬滚打十几年,见过太多因为温度测不准导致的能效翻车案例。有的项目,明明空调主机选型没问题,末端设备也到位了,结果运行能耗就是下不来。一查,原来是传感器偏差了2度,整个控制逻辑全乱套。

所以这节课,我打算把三种最常用的温度传感器——DS18B20、NTC热敏电阻、SHT30温湿度传感器,从驱动开发到校准,掰开了揉碎了讲清楚。

3.1 DS18B20:一线总线的老将

DS18B20,这玩意儿在暖通行业里太常见了。它最大的特点就是便宜、抗干扰、而且只用一根数据线就能通信。

驱动开发要点

DS18B20用的是单总线协议(One-Wire)。说白了,就是一根线上既要传数据,又要传时钟。时序要求比较严格,尤其是复位脉冲和存在脉冲的时序。

我个人习惯用定时器中断来做延时,而不是简单的空循环。为什么?因为空循环在中断里会被打断,时序就乱了。你想想看,如果MCU正在处理其他中断,DS18B20的时序窗口就错过了。

核心时序步骤:

  • 复位:主机拉低总线480μs以上,然后释放
  • 存在脉冲:DS18B20拉低总线60-240μs,表示应答
  • 写时序:写0拉低60μs,写1拉低1-15μs后释放
  • 读时序:主机拉低1-15μs后释放,在15μs内采样
// DS18B20 读取温度示例(伪代码)
uint8_t ds18b20_reset(void) {
    uint8_t presence;
    GPIO_LOW();          // 拉低总线
    delay_us(480);       // 保持480μs
    GPIO_HIGH();         // 释放总线
    delay_us(60);        // 等待60μs
    presence = GPIO_READ(); // 读取存在脉冲
    delay_us(420);       // 等待剩余时间
    return presence;     // 0表示存在
}

float ds18b20_read_temp(void) {
    uint8_t temp_l, temp_h;
    int16_t raw_temp;
    
    ds18b20_reset();
    ds18b20_write_byte(0xCC);  // 跳过ROM
    ds18b20_write_byte(0x44);  // 启动温度转换
    delay_ms(750);             // 等待转换完成
    
    ds18b20_reset();
    ds18b20_write_byte(0xCC);
    ds18b20_write_byte(0xBE);  // 读取暂存器
    
    temp_l = ds18b20_read_byte();
    temp_h = ds18b20_read_byte();
    
    raw_temp = (temp_h << 8) | temp_l;
    return raw_temp * 0.0625;  // 12位分辨率,每LSB对应0.0625°C
}

避坑指南:我曾经在一个项目里,DS18B20的读数总是跳变。查了半天,发现是总线没加上拉电阻。记住,单总线必须外接4.7kΩ上拉电阻到VCC,否则信号不稳定。

3.2 NTC热敏电阻:模拟量的艺术

NTC热敏电阻,说白了就是温度变了,电阻值跟着变。它比DS18B20便宜,但需要ADC采样和查表计算。

硬件连接与分压电路

NTC不能直接接ADC,必须搭一个分压电路。我常用的接法是:NTC串联一个固定电阻,中间抽头接ADC输入。

参数 推荐值 说明
固定电阻R_ref 10kΩ 与NTC在25°C时阻值相同
ADC参考电压 3.3V或5V 取决于MCU
采样精度 12位以上 推荐16位ADC

查表法实现温度转换

NTC的阻值与温度的关系是非线性的。用公式算太慢,我建议用查表法。提前把温度-ADC值对应关系存到Flash里,运行时直接查。

// NTC查表法示例(简化版)
const uint16_t ntc_table[] = {
    // 温度(°C) : ADC值 (假设12位ADC, Vref=3.3V)
    0,   4095,   // 0°C时ADC值
    10,  3800,
    20,  3400,
    25,  3100,   // 25°C时ADC值
    30,  2800,
    40,  2200,
    50,  1600,
};

float ntc_get_temp(uint16_t adc_value) {
    uint8_t i;
    for(i = 0; i < sizeof(ntc_table)/2; i += 2) {
        if(adc_value >= ntc_table[i+1]) {
            // 线性插值
            float ratio = (float)(adc_value - ntc_table[i+1]) / 
                         (ntc_table[i-1] - ntc_table[i+1]);
            return ntc_table[i] + ratio * 10;
        }
    }
    return -40; // 超出范围
}

注意:NTC的自热效应。电流流过NTC会产生热量,导致测量值偏高。我一般控制流过NTC的电流在100μA以内,这样自热误差可以忽略。

3.3 SHT30:数字温湿度一体方案

SHT30是Sensirion家的产品,I2C接口,精度高,而且自带校准。暖通空调里,温湿度都要测的场合,用它最省事。

I2C驱动与数据读取

SHT30的I2C地址是0x44(ADDR引脚接GND)或0x45(ADDR引脚接VCC)。我习惯用0x44,省一根线。

// SHT30读取温湿度示例
#define SHT30_ADDR 0x44

uint8_t sht30_read_data(float *temp, float *hum) {
    uint8_t buf[6];
    
    // 发送测量命令:0x2C 0x06(高重复性)
    i2c_start(SHT30_ADDR << 1);
    i2c_write(0x2C);
    i2c_write(0x06);
    i2c_stop();
    
    delay_ms(15); // 等待测量完成
    
    // 读取6字节数据
    i2c_start((SHT30_ADDR << 1) | 0x01);
    for(i = 0; i < 6; i++) {
        buf[i] = i2c_read(i < 5);
    }
    i2c_stop();
    
    // 计算温度:T = -45 + 175 * (raw / 65535)
    uint16_t raw_temp = (buf[0] << 8) | buf[1];
    *temp = -45.0f + 175.0f * raw_temp / 65535.0f;
    
    // 计算湿度:RH = 100 * (raw / 65535)
    uint16_t raw_hum = (buf[3] << 8) | buf[4];
    *hum = 100.0f * raw_hum / 65535.0f;
    
    return 0; // 成功
}

个人经验:SHT30的I2C时钟频率不要超过400kHz。我试过1MHz,结果数据偶尔会错位。另外,SHT30的CRC校验一定要做,尤其是用在工业现场时。我曾经因为没做CRC,被一个电磁干扰搞得数据全乱套。

3.4 传感器校准:让数据更可靠

传感器出厂时都有一定误差。DS18B20的典型误差是±0.5°C,NTC更差,可能到±1°C。SHT30好一些,±0.2°C。但暖通空调系统里,我们往往需要±0.1°C的精度。

两点校准法

我常用的方法是两点校准。拿一个高精度参考温度计(比如铂电阻PT100),在0°C和50°C两个点做校准。

  1. 把传感器和参考温度计一起放进恒温槽,设定0°C
  2. 记录传感器读数和参考值,得到偏移量offset1
  3. 设定50°C,记录偏移量offset2
  4. 线性插值,得到全量程的校准曲线
// 两点校准示例
typedef struct {
    float offset_low;   // 低温点偏移
    float offset_high;  // 高温点偏移
    float temp_low;     // 低温点温度
    float temp_high;    // 高温点温度
} calib_t;

float apply_calibration(float raw_temp, calib_t *cal) {
    float ratio = (raw_temp - cal->temp_low) / 
                  (cal->temp_high - cal->temp_low);
    float offset = cal->offset_low + 
                   ratio * (cal->offset_high - cal->offset_low);
    return raw_temp - offset;
}

校准注意事项:

  • 恒温槽的稳定时间至少30分钟
  • 每个校准点测量10次取平均
  • 校准参数保存在EEPROM里,掉电不丢失
  • 建议每半年重新校准一次

3.5 三种传感器的选型建议

传感器 精度 成本 接口 适用场景
DS18B20 ±0.5°C 单总线 多点测温、长距离
NTC ±1°C 极低 模拟量 大批量、低成本
SHT30 ±0.2°C I2C 温湿度同时测量

嗯,最后说一句。传感器选型没有绝对的好坏,关键看你的项目需求。如果预算充足,我建议用SHT30,省心。如果要做多点测温,DS18B20是首选。如果成本敏感,NTC也能用,但要做好校准。

好了,这节课就到这里。下一节我们讲执行器驱动,包括风机、水泵、电动阀的控制。到时候见。