给屋子做温湿度监测,很多人第一个买的就是DHT11,便宜、到处都是教程。但你翻翻它的手册会发现一个尴尬的事实:湿度精度±5%RH、温度±2℃,室温25度时读出23度或27度都不算故障。后来Sensirion的SHT31模块价格降下来了,我照着Adafruit和Last Minute Engineers的教程把整个流程走了一遍,这篇就替新手把这条路捋顺,重点说说它到底比DHT11准在哪。

先看账本:三家的精度差了多少
先把官方数字摆出来。按奥松DHT11产品手册,它的湿度精度是±5%RH,温度精度±2℃,采样周期大于2秒一次。而Sensirion官网对SHT31-DIS-B的标称是典型湿度精度±2%RH(0-100%RH全量程),温度典型精度±0.2℃,湿度响应时间8秒左右。更新的SHT40更狠:±1.8%RH、±0.2℃,平均供电电流只有0.4µA。
差距直观一点说:DHT11温度能差出2度,你做风扇联动、做暖气提醒,阈值根本没法定;SHT31的0.2℃已经够做室内温控曲线了。湿度上±5%RH和±2%RH的差别,在养植物、存茶叶这类场景里就是"能用"和"好用"的区别。
不过DHT11也不是一无是处:它用单总线,一根数据线就能跑,官网手册标3.3到5.5V供电,一块多钱一个。SHT31走I2C,要多占一根线,模块价格也贵一些——Adafruit官方那块SHT31-D扩展板卖13.95美元(截至11月10日),国内兼容模块便宜得多。你可以把它理解成"多花几块钱买回准确度"。
认识模块:正面芯片,背面引脚
常见的SHT31模块是四脚布局:VIN接电源、GND接地、SCL是I2C时钟线、SDA是I2C数据线。芯片本身是Sensirion的SHT31-DIS,出厂已校准,读出来就是物理量,不用像老式湿敏电阻那样自己算公式。

Adafruit这块板还有三个附加引脚值得认识:ADR是I2C地址选择脚,默认拉低、地址为0x44,接到VIN就变成0x45——这意味着同一条I2C总线上可以挂两块SHT31;RST是硬件复位脚;ALR是报警输出,可以设置温湿度越限时触发中断。普通玩家只用VIN/GND/SCL/SDA四根线就够了。
接线:四根线的事
以Arduino UNO为例,SHT31模块的VIN接3.3V或5V都行(Adafruit官方教程写3-5V均可,跟随主控逻辑电平走),GND接GND,SDA接UNO的A4,SCL接A5。A4/A5是UNO上I2C总线的固定位置,在Mega上则是数字20和21。如果你买的是带STEMMA QT插头的版本,插线更省事,原理一样。

新手容易卡的就两处:一是把SDA和SCL接反了,现象是程序里begin()返回失败、串口打印"Couldn't find SHT31";二是面包板插接触不良,I2C时钟没信号,同样报找不到器件。遇到报错先别怀疑代码,检查这两根线。
装库和代码:照抄就能跑
打开Arduino IDE的"工具-管理库",搜Adafruit SHT31,装它,同时它会带上Adafruit BusIO这个依赖库,一起装上。库管理器里显示的版本是1.1.5。装好后打开文件-示例-Adafruit_SHT31-SHT31test,或者直接用下面这段(与示例程序一致):
#include "Arduino.h"
#include "Wire.h"
#include "Adafruit_SHT31.h"
Adafruit_SHT31 sht31 = Adafruit_SHT31();
void setup() {
Serial.begin(9600);
if (! sht31.begin(0x44)) { // Set to 0x45 for alternate I2C address
Serial.println("Couldn't find SHT31");
while (1) delay(1);
}
}
void loop() {
float t = sht31.readTemperature();
float h = sht31.readHumidity();
if (! isnan(t)) { // check if 'is not a number'
Serial.print("Temp *C = "); Serial.print(t); Serial.print("\t\t");
} else {
Serial.println("Failed to read temperature");
}
if (! isnan(h)) { // check if 'is not a number'
Serial.print("Hum. % = "); Serial.println(h);
} else {
Serial.println("Failed to read humidity");
}
delay(1000);
}说明一下:原来代码里的头文件尖括号写法在部分平台上会被转义处理吞掉,所以这里改成了引号写法,两者在Arduino编译器下是等价的。
上传后打开串口监视器,波特率9600,就能看到Temp和Hum两个数在刷新。官方教程里给的小技巧挺实用:对着传感器哈一口气,湿度值会明显跳高再回落,说明器件在工作。这段代码里有两个值得注意的细节:begin(0x44)里传的是I2C地址,如果你的模块ADR接了高电平,记得改成0x45;循环里用isnan()判断读数是不是有效数字,I2C偶发读失败时会返回NaN,做个判断程序就不会打出乱码值。
买SHT31还是SHT40?
SHT40是Sensirion的第四代,官方标称精度比SHT31还高一档(±1.8%RH对±2%RH),供电电压拉宽到1.08-3.6V,芯片尺寸只有1.5×1.5×0.5毫米。但市面上现成的Arduino模块、教程和库,SHT31生态更成熟,Adafruit_SHT31库里begin完就是readTemperature、readHumidity两个函数,对新手非常友好。我的建议是:第一次上手买SHT31模块,想追低功耗或做电池设备再考虑SHT40,两家用法几乎一样,社区也有现成的SHT4x库。
还有个容易被忽略的小功能:SHT31内置加热器,库里的sht31.heater(true)可以打开它,用来蒸发凝结的水汽,湿度过高时可以短暂开启除凝露,注意别长时间开着,它会影响温度读数。
总结
整体走下来,SHT31接Arduino比DHT11还省心:不用自己倒时序,I2C即插即读,精度从"差着2度"直接进到"零点几度"。接线四根线、装一个库、抄一段官方示例,半小时内能跑通。它不是最便宜的方案,但如果你打算让温湿度数据真的参与控制逻辑,这十几块钱花得值。











±2℃对±0.2℃,这账一算就明白了,好文。
引脚那段写得好,ADR接VIN变0x45这个之前真不知道,正好手里有两块模块,可以挂一条总线上了。
去年用DHT11做过鱼缸房的温湿度记录,一到下雨天湿度读数能在一格里跳七八个点,后来换了SHT31才稳定下来。文章里那个哈气测试确实管用,我当时也是这么确认传感器活着的。另外提醒一句,I2C走线别太长,之前接了六十厘米的杜邦线偶尔会读失败,缩短到二十厘米内就没再出过NaN。