跳转至

传感器

在本页中,你连接两个传感器并在门户网站上输出它们的数据。首先是 SHT31(柜气候),然后是温度计(加热器温度)。这是"获得数据"的步骤,在添加管理逻辑之前。

与核心库一起工作的原则很简单:你的代码在 loop() 中将新读数写入 s_link.telemetry.* 字段,外观自动将它们发布到云端每 telemetryPeriodMs,来自 Config。你不需要手动调用发布。

遥测字段

对于我们的柜子,使用三个字段(索引 [0] — 第一个也是唯一的室):

字段 存储内容 Config 中的标志
s_link.telemetry.airTempC[0] 空气温度,°C hasAirTemp
s_link.telemetry.airHumidityPct[0] 空气湿度,% hasAirHumidity
s_link.telemetry.heaterTempC[0] 加热器温度,°C hasHeaterTemp

我们已经在前一步的 Config 中包括了所有三个标志。

规则:传感器代码不应该阻塞 loop()

外观 idryer-core 在同一个 loop() 中为 Wi-Fi 和 MQTT 服务。因此在读取传感器时,你不能调用 delay() — 暂停会断开网络会话。传感器按计时器轮询,已准备好的值只是被读取。生态系统中的现成驱动程序已经以这种方式组织。

步骤 1. SHT31:柜气候

你不需要从头开始编写 SHT31 驱动程序 — 现成的 Sht31ClimateSensor 类在 iDryer-Storage 示例中。它使用 robtillaart/SHT31 库并无阻塞地读取传感器。

  1. 在你的 platformio.inilib_deps 中添加 SHT31 库:

    lib_deps =
        file://path/to/idryer-core
        bblanchon/ArduinoJson @ ^6.21.0
        knolleary/PubSubClient
        robtillaart/SHT31 @ ^0.5.0
    
  2. iDryer-Storage/src/storage/sensors/ 复制四个文件到你的 src/ 文件夹:Sht31ClimateSensor.hSht31ClimateSensor.cppIClimateSensor.hsensor_reading.h

  3. 通过 I2C 连接传感器(见接线图)并在 src/main.cpp 中读取它:

#include <Wire.h>
#include <iDryer.h>
#include "Sht31ClimateSensor.h"

static Sht31ClimateSensor s_climate(&Wire);
static bool               s_climateOk = false;

void setup() {
    Serial.begin(115200);
    Wire.begin(8, 9);                 // SDA, SCL — 你的板的引脚
    s_climateOk = s_climate.begin();  // 自己找到地址 0x44 或 0x45
    s_link.begin();
}

void loop() {
    s_link.loop();

    if (s_climateOk) {
        s_climate.tick(millis());
        SensorReading r = s_climate.get();
        if (r.ok) {
            s_link.telemetry.airTempC[0]       = r.temperature;
            s_link.telemetry.airHumidityPct[0] = r.humidity;
        }
    }
}

SensorReading 结构(字段 oktemperaturehumidity)在 sensor_reading.h 中声明。刷入后,门户网站会显示柜温度和湿度 — 这是来自设备的第一个反馈。

步骤 2. 温度计:加热器温度

我没有现成的 ESP32 温度计类,所以我们直接在 src/main.cpp 中编写。温度计连接到 ADC 引脚通过转换器(见接线图):控制器测量中点的电压,根据它计算温度计的电阻,然后是温度。

#include <math.h>

static const int   THERM_PIN  = 2;         // ADC 引脚
static const float SERIES_R   = 4700.0f;   // 分压器电阻,欧
static const float NOMINAL_R  = 100000.0f; // 温度计在 25 °C 时的电阻,欧
static const float NOMINAL_T  = 25.0f;     // °C
static const float BETA       = 3950.0f;   // 温度计数据表中的 B 系数

// 返回加热器温度(°C)。
static float readHeaterTempC() {
    int   raw = analogRead(THERM_PIN);          // 0..4095 在 ESP32 上
    float v   = (float)raw / 4095.0f;           // 完整范围的分数
    float r   = SERIES_R * (1.0f - v) / v;      // 温度计电阻,欧
    // Steinhart–Hart 方程(B 参数):
    float tK  = 1.0f / (1.0f / (NOMINAL_T + 273.15f) + logf(r / NOMINAL_R) / BETA);
    return tK - 273.15f;
}

loop() 中,在 SHT31 读取旁边写结果到遥测:

s_link.telemetry.heaterTempC[0] = readHeaterTempC();

这是简化的读取 — 根据你的温度计调整参数

常数 NOMINAL_RBETA 取决于特定的温度计 — 从其数据表中获取(常见的家用温度计 — 通用 3950,100 kΩ)。分压器公式对应于接线图中的方案:温度计到 3.3V,电阻到 GND。对于其他布局,公式会改变。ESP32 ADC 是非线性的,因此对于精确测量,读数是经过校准的 — 在 iDryer 系列控制器中,为此使用温度计表(Thermistor 库)。

万用表温度计检查 — 检查温度计

本章后 src/main.cpp 的完整版本

下面是整个文件。相对于上一章的新行标记为 // ← 第 5 章;其余的没有改变。

??? 注解「什么是 — 第 4 章后的 src/main.cpp

```cpp
#include <iDryer.h>

static const iDryer::Config CFG = {
    .deviceType        = iDryer::DeviceType::Dryer,
    .unitsCount        = 1,
    .hasHeater         = true,
    .hasFan            = true,
    .hasAirTemp        = true,
    .hasAirHumidity    = true,
    .hasHeaterTemp     = true,
    .telemetryPeriodMs = 5000,
    .statusPeriodMs    = 10000,
    .hardwareVersion   = "1.0",
    .firmwareVersion   = "0.1.0",
    .model             = "DIY Storage Cabinet",
};
static iDryer::Link s_link(CFG);

void setup() {
    Serial.begin(115200);
    s_link.begin();
}

void loop() {
    s_link.loop();
}
```

检查结果

在此步骤后,门户网站应显示三个值:

  • 柜内空气温度;
  • 柜内湿度;
  • 加热器温度。

如果读数"浮动"或明显错误:

  • 检查公共地和接线(来自电源导线的干扰)— 接线错误
  • 检查分压器电阻的标称值和温度计类型;
  • 确保 SHT31 通过 I2C 响应(正确的地址和线)。

"传感器显示垃圾"诊断 — 检查温度计常见错误

接下来

我们有来自传感器的数据。现在在YAML 菜单中描述设备设置(目标温度、磁滞),以便可以从门户网站更改它们并存储在内存中。