3、传感器数据采集基础:常见传感器(温湿度、光照、运动、气体等)的读取方法及数据格式
在ESP32规则引擎的编排体系中,传感器数据是触发条件判断的“第一公里”。无论是温湿度、光照、运动还是气体浓度,其采集质量直接决定了后续AI结果分析和设备动作的准确性。本章将聚焦于ESP32与常见传感器的物理连接、驱动读取方法以及数据格式的标准化处理,帮助你在规则引擎中建立可靠的数据底座。
上图展示了从传感器到ESP32再到数据标准化的完整链路。传感器层负责物理量到电信号的转换,ESP32通过GPIO、ADC或I2C等接口读取原始数据,最终在数据标准化层统一为带类型、值和单位的结构化格式。下面我们将逐一拆解各类传感器的读取原理与工程实现。
3.1 温湿度传感器:DHT22与SHT30的读取方法
核心原理:温湿度传感器是环境监控中最基础的器件。DHT22采用单总线协议,通过一个数据引脚分时输出40位数据(16位湿度、16位温度、8位校验),其温度分辨率为0.1°C,湿度分辨率为0.1%RH。SHT30则基于I2C接口,内部集成校准电路,直接输出16位温湿度数据,精度更高且支持CRC校验。
读取操作流程:
- 硬件连接:DHT22的DATA引脚接ESP32的GPIO4(需外接4.7kΩ上拉电阻至3.3V),VCC接3.3V,GND共地。SHT30的SCL接GPIO22,SDA接GPIO21,同样需要上拉电阻。
- 驱动初始化:对于DHT22,需使用
DHTesp库,调用dht.setup(gpio, DHTesp::DHT22)完成初始化。对于SHT30,使用Adafruit_SHT31库,调用sht31.begin(0x44)(默认I2C地址)。 - 数据读取:DHT22每次读取间隔需大于2秒,否则返回错误。SHT30支持单次或周期读取,单次读取延迟约15ms。
- 数据校验:DHT22需检查校验位;SHT30可启用CRC校验,确保数据完整性。
// DHT22 读取示例
#include <DHTesp.h>
DHTesp dht;
void setup() {
dht.setup(4, DHTesp::DHT22);
}
void loop() {
TempAndHumidity th = dht.getTempAndHumidity();
if (dht.getStatus() == 0) {
Serial.printf("Temp: %.1f°C, Hum: %.1f%%\n", th.temperature, th.humidity);
}
delay(2000);
}
{"type":"temp","value":25.3,"unit":"°C","ts":1699999999}。这样规则引擎可以直接通过value字段进行阈值判断,无需关心底层传感器差异。
3.2 光照传感器:BH1750的数字量读取与换算
核心原理:BH1750是数字环境光传感器,I2C接口,测量范围0-65535 lx,分辨率可配置为0.5、1或4 lx。其内部光电二极管将光强转换为电流,经ADC数字化后通过I2C输出16位数据。该传感器适合用于智能照明、窗帘联动等场景。
读取操作流程:
- 地址配置:ADDR引脚接低电平时地址为0x23,接高电平时为0x5C。需确保总线上无地址冲突。
- 指令发送:发送
0x10(连续高分辨率模式)或0x20(单次高分辨率模式)。单次模式读取后自动进入掉电状态,适合低功耗应用。 - 数据读取:等待测量完成(典型180ms),读取2字节数据,合并为16位无符号整数。
- 单位换算:原始值除以1.2(高分辨率模式)得到实际光照值(单位lx)。
// BH1750 读取示例
#include <Wire.h>
uint16_t readBH1750() {
Wire.beginTransmission(0x23);
Wire.write(0x10); // 连续高分辨率模式
Wire.endTransmission();
delay(180);
Wire.requestFrom(0x23, 2);
uint16_t val = (Wire.read() << 8) | Wire.read();
return val / 1.2;
}
3.3 运动传感器:PIR红外与MPU6050加速度计
核心原理:运动检测分为两类:PIR(被动红外)用于检测人体移动,输出数字信号(高/低电平),适合安防和人来灯亮场景;MPU6050是六轴惯性测量单元(三轴加速度+三轴陀螺仪),通过I2C输出16位原始数据,适合设备姿态检测和振动分析。
读取方法对比:
| 传感器 | 接口类型 | 输出格式 | 典型应用 | 注意事项 |
|---|---|---|---|---|
| PIR HC-SR501 | GPIO数字输入 | 0/1电平 | 人体存在检测 | 灵敏度/延时旋钮调节 |
| MPU6050 | I2C | 16位有符号整数 | 跌倒检测、姿态识别 | 需先唤醒并配置量程 |
PIR读取流程:初始化GPIO为输入模式,通过digitalRead()读取电平。当检测到人体移动时输出高电平,持续2-3秒后恢复低电平。注意PIR模块上两个电位器分别调节灵敏度和输出延时。
MPU6050读取流程:
- 调用
Wire.begin()初始化I2C。 - 通过
MPU6050库的initialize()方法唤醒传感器。 - 设置加速度量程(±2g/±4g/±8g/±16g)和陀螺仪量程(±250/±500/±1000/±2000°/s)。
- 读取6个16位寄存器,转换为实际物理值:
accel_g = raw / 16384(±2g量程时)。
// MPU6050 读取示例
#include <MPU6050.h>
MPU6050 mpu;
void setup() {
Wire.begin();
mpu.initialize();
mpu.setFullScaleAccelRange(MPU6050_ACCEL_FS_2);
}
void loop() {
int16_t ax = mpu.getAccelerationX();
float ax_g = ax / 16384.0;
Serial.printf("Accel X: %.2f g\n", ax_g);
delay(100);
}
3.4 气体传感器:MQ系列模拟量读取与标定
核心原理:MQ系列气体传感器(如MQ-135空气质量、MQ-2可燃气体)基于气敏电阻,其阻值随目标气体浓度变化。传感器模块通常输出模拟电压(0-3.3V或0-5V),需通过ESP32的ADC(模数转换器)读取。ESP32内置12位ADC,可检测0-3.3V电压,分辨率约0.8mV。
读取操作流程:
- 硬件连接:传感器AO引脚接ESP32的ADC引脚(如GPIO34),注意ESP32的ADC输入范围不能超过3.3V,若模块输出5V需分压。
- ADC初始化:使用
analogRead()函数读取原始值(0-4095)。 - 电压换算:
voltage = raw * 3.3 / 4095。 - 浓度估算:MQ系列输出与浓度呈非线性关系,通常需查手册中的灵敏度曲线,或使用经验公式
ppm = pow(10, (voltage - b) / m)进行对数拟合。
// MQ-135 读取示例
int raw = analogRead(34);
float voltage = raw * 3.3 / 4095.0;
// 假设标定参数(需根据实际传感器校准)
float ppm = pow(10, (voltage - 1.2) / 0.6);
Serial.printf("Raw: %d, Voltage: %.2fV, PPM: %.1f\n", raw, voltage, ppm);
3.5 数据采集的工程化处理与常见误区
数据滤波与去抖:传感器原始数据常包含噪声,尤其是ADC采样和运动传感器。推荐使用滑动平均滤波(窗口5-10个样本)或中值滤波。对于数字信号(如PIR),需加入软件去抖,连续读取3次相同电平才确认状态变化。
采样策略:根据传感器特性设置合理的采样间隔。DHT22至少2秒一次,BH1750可100ms一次,MPU6050可1kHz但建议降频至50Hz以节省CPU。规则引擎中,采样频率应高于条件判断的最小时间粒度,但不宜过高导致数据洪泛。
常见误区:
- 忽略上拉电阻:I2C和单总线必须外接上拉电阻(典型4.7kΩ),否则通信不稳定。
- ADC引脚误用:ESP32的ADC2引脚与WiFi共用,若同时启用WiFi会导致采样失败,应优先使用ADC1(GPIO32-39)。
- 数据单位不统一:温度可能来自DHT22(°C)或DS18B20(°C),但光照可能来自BH1750(lx)或光敏电阻(电压值),规则引擎中必须统一单位。
- 忽略传感器预热:气体传感器和部分湿度传感器需要预热时间,上电后立即读取的数据不可信。
valid、stale),当连续读取失败超过3次时标记数据失效,避免基于错误数据触发设备动作。
总结复盘:传感器数据采集是规则引擎的基石。本章覆盖了四类典型传感器的读取方法,核心要点可归纳为:数字传感器(DHT22、BH1750、MPU6050)依赖通信协议(单总线/I2C),需注意时序和地址配置;模拟传感器(MQ系列)依赖ADC转换,需关注电压范围和标定;数字IO传感器(PIR)最简单,但需处理去抖和灵敏度调节。无论哪种传感器,最终都应转换为带类型、数值、单位和时间戳的标准化JSON格式,供规则引擎统一消费。下一阶段,我们将探讨如何将这些原始数据转化为规则引擎可用的条件判断因子。