4、温湿度传感器(SHT30):原理介绍、I2C通信、接线图、Arduino驱动库安装与测试代码

各位同学,咱们今天来聊聊温湿度传感器。农业气象站里,温湿度是基础中的基础。你想想看,作物生长好不好,病虫害会不会爆发,很大程度上就看这两个参数。

市面上温湿度传感器很多,DHT11、DHT22、AM2301……但我个人最偏爱SHT30。为什么?因为它精度高、稳定性好,而且价格也没贵到哪去。我在一个智能大棚项目里用过DHT22,结果用了半年就开始飘,换了SHT30之后,数据稳得像老狗。嗯,从那以后我就成了SHT30的忠实用户。

4.1 SHT30传感器原理

SHT30是瑞士Sensirion公司出品的数字温湿度传感器。它内部集成了一个电容式湿度传感元件和一个带隙温度传感元件,外加一个14位的ADC和数字信号处理电路。

说白了,它就是把模拟信号在芯片内部直接转成数字信号,然后通过I2C总线送出来。你不需要操心什么模拟电压、参考电压,直接读寄存器就行。

关键参数我列一下:

参数 典型值 备注
温度精度 ±0.3°C 0~65°C范围内
湿度精度 ±2%RH 20~80%RH范围内
工作电压 2.4V~5.5V 3.3V最常用
I2C地址 0x44 或 0x45 由ADDR引脚决定
测量范围 -40~125°C / 0~100%RH 超出范围精度下降

核心要点:SHT30的I2C地址默认是0x44。如果你把ADDR引脚接高电平,地址就变成0x45。这个细节我在项目里吃过亏——买了两个传感器焊在同一根总线上,结果地址冲突,死活读不出数据。后来才发现其中一个模块把ADDR引脚拉高了。

4.2 I2C通信协议

I2C,全称Inter-Integrated Circuit,是飞利浦公司搞出来的两线制串行总线。就两根线:SCL(时钟线)和SDA(数据线)。

为什么农业气象站里I2C这么流行?因为传感器多啊!你挂一个SHT30测温湿度,再挂一个BH1750测光照,再挂一个BMP280测气压……全部挂在同一根I2C总线上,只要地址不冲突就行。省IO口,省布线,多爽。

I2C的基本通信流程是这样的:

  1. 起始信号:SCL高电平时,SDA从高变低
  2. 发送地址:主机发送7位从机地址+1位读写位
  3. 从机应答:从机拉低SDA表示收到
  4. 数据传输:每8位数据后跟一个应答位
  5. 停止信号:SCL高电平时,SDA从低变高

对于SHT30来说,读数据的流程更具体一些:

  • 先发一条测量命令(比如0x2C06),告诉传感器“你开始测吧”
  • 等一会儿(大约15ms),传感器完成测量
  • 再发读命令,把6个字节的数据读回来
  • 前2字节是温度,中间2字节是湿度,最后2字节是CRC校验

我的经验:SHT30的测量命令有很多种,比如0x2C06是“高重复性、时钟拉伸使能”,0x2C10是“中重复性”。我个人习惯用0x2C06,精度最高。虽然功耗大一点点,但农业气象站又不靠电池供电,无所谓。

4.3 接线图

接线其实很简单。SHT30模块一般有4个引脚:VCC、GND、SCL、SDA。有些模块还多一个ADDR引脚,用来改地址。

以Arduino Uno为例:

SHT30引脚 Arduino引脚 备注
VCC 3.3V 或 5V 推荐3.3V,功耗更低
GND GND 共地必须接
SCL A5 (SCL) Uno的I2C时钟脚
SDA A4 (SDA) Uno的I2C数据脚
ADDR GND 或 悬空 默认地址0x44

注意:I2C总线需要上拉电阻。大多数SHT30模块已经板载了4.7kΩ上拉电阻,所以不需要额外加。但如果你自己用裸片焊的,记得在SCL和SDA上各加一个4.7kΩ电阻到VCC。我曾经偷懒没加上拉,结果通信时好时坏,排查了半天才发现是这个问题。

4.4 Arduino驱动库安装

Arduino驱动SHT30,我推荐用Adafruit的库。虽然Sensirion官方也有库,但Adafruit的库封装得更友好,用起来顺手。

安装步骤:

  1. 打开Arduino IDE,点击「工具」→「管理库」
  2. 搜索框输入「Adafruit SHT31」
  3. 找到「Adafruit SHT31 Library」,点击安装
  4. 它会自动安装依赖库「Adafruit BusIO」和「Adafruit Unified Sensor」

等一下,你可能会问:为什么搜SHT30,出来的是SHT31?

嗯,这里有个小故事。Adafruit的库最初是为SHT31写的,但SHT30和SHT31的寄存器地址完全兼容,所以这个库也能驱动SHT30。我在好几个项目里都这么用,没出过问题。

替代方案:如果你不想用Adafruit的库,也可以用「SparkFun SHT30 Arduino Library」。这个库更轻量,适合资源受限的板子。我个人在Pro Mini上用过,Flash占用少很多。

4.5 测试代码

好了,理论讲完了,咱们来写代码。下面这个例程会每隔2秒读取一次温湿度,并通过串口打印出来。

#include <Wire.h>
#include <Adafruit_SHT31.h>

Adafruit_SHT31 sht30 = Adafruit_SHT31();

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    delay(10);  // 等待串口就绪
  }
  
  Serial.println("SHT30 温湿度传感器测试");
  
  // 初始化I2C,地址默认0x44
  if (!sht30.begin(0x44)) {
    Serial.println("找不到SHT30传感器!请检查接线。");
    while (1) delay(10);
  }
  
  Serial.println("传感器初始化成功!");
}

void loop() {
  float temp = sht30.readTemperature();
  float hum = sht30.readHumidity();
  
  // 检查读数是否有效
  if (!isnan(temp) && !isnan(hum)) {
    Serial.print("温度: ");
    Serial.print(temp);
    Serial.print(" °C\t");
    Serial.print("湿度: ");
    Serial.print(hum);
    Serial.println(" %RH");
  } else {
    Serial.println("读数失败!");
  }
  
  delay(2000);
}

代码逻辑很简单:

  • sht30.begin(0x44):初始化传感器,地址0x44
  • sht30.readTemperature():读温度,返回摄氏度
  • sht30.readHumidity():读湿度,返回百分比
  • isnan():检查读数是否有效,防止传感器掉线时输出乱码

避坑指南:我曾经在项目里遇到过一个问题——传感器刚上电时,前几次读数全是NaN。后来查资料才发现,SHT30上电后需要大约1ms的稳定时间,然后才能正常通信。所以建议在setup()里加一个delay(100),给传感器一点缓冲时间。

上传代码后,打开串口监视器,波特率设成9600。如果一切正常,你会看到类似这样的输出:

SHT30 温湿度传感器测试
传感器初始化成功!
温度: 25.34 °C    湿度: 62.18 %RH
温度: 25.36 °C    湿度: 62.22 %RH
温度: 25.33 °C    湿度: 62.15 %RH

看到数据了吗?温度稳定在25.3°C左右,湿度62%左右。如果你对着传感器哈一口气,湿度会立刻飙升。这就是SHT30的响应速度——快得很。

好了,这一节的内容就到这。下一节咱们会讲光照传感器,到时候你会看到I2C总线上挂多个传感器是怎么玩的。嗯,敬请期待。