Page 1 of 1

使用T2-U 和 Sensor_Hub开发一款智能温湿度计

Posted: 2023年 Sep 7日 09:49
by chenyisong

Sensor Hub 是 TuyaOS 传感器管理组件,可以实现对传感器设备的硬件抽象,设备管理和数据处理。基于 sensor_hub 开发传感器应用时,开发者无需关注传感器的传输协议,只需要对传感器挂载硬件接口、工作方式、采集间隔等进行配置,然后在事件回调中读取传感器处理即可。

本项目采用 T2-U 开发板及 TuyaOS Sensor Hub 组件,使用 SHT30 温湿度传感器,开发一款智能 Wi-Fi 温湿度计。

传感器 SHT30

本方案选用 SHT30 作为温湿度传感器。

SHT30 概述

SHT3x 系列是由瑞士 Sensirion 生产的高精度温湿度传感器,提供了一系列新功能,如增强信号处理、两个独特和用户可选I2C地址、一个可编程温湿度极限的报警模式,以及高达1 MHz的通信速度。

芯片资料可在官网 https://sensirion.com/media/documents/213E6A3B/63A5A569/Datasheet_SHT3x_DIS.pdf 下载。

sht3x.png
  • 供电:SHT3x 系列温湿度传感器采用宽电压设计,可使用 2.15 v 至 5.5 v 电压范围。

  • 封装:SHT3x 采用 8-pin DFN 封装

sht3x.png

芯片总共有 8 个引脚:

Pin名称说明
1SDAI2C 数据线引脚
2ADDR地址引脚,可连接 VSS 或 VDD,分别会有不同的地址,不能浮空。
3ALERT报警输出引脚,如果使用,建议接到单片机的外部中断。不用的话需要浮空。
4SCLI2C 时钟线引脚
5VDD电压输入引脚
6nRESET复位引脚,低电平有效。如果不用,建议浮空;也可以通过一个 ≥2 kΩ 的电阻链接到 VDD
7R没有电气连接,需连接到 VSS
8VSS接地
  • I2C 通讯地址:SHT3x 系列温湿度传感器可以通过 ADDR 引脚设置通讯地址。
SHT3x 温湿度传感器I2C地址ADDR(pin 2)引脚配置
I2C address A0x44(默认)连接到逻辑低电平
I2C address B0x45连接到逻辑高电平

数据读取

SHT3x系列温湿度传感器支持I2C快速模式(频率高达1000千赫)。

1. 单次读取

SHT3x 温湿度传感器有一种单次测量模式。这种模式只按我们规定的方式运行一次,测量通信序列由一个启动条件、I2C写标头和一个16位测量命令组成。在传感器完成测量后,通过发送一个START条件和一个I2C读标头,主控可以读取测量结果。具体的格式如下:

single-short-mode.png

2. 周期读取

SHT3X温湿度传感器还有一种周期性检测数据的方式。这种方式先将SHT3X温湿度传感器配置为周期获取模式。在这一模式下就可以周期获取数据了。

periodic-mode.png

3. 数据转换

测量数据总是以16位无符号整数的形式传输。这些值已经线性化,并补偿了温度和电源电压的影响。可以使用简单的公式将这些原始值转换为物理量值。

温度转换公式(结果为摄氏度和华氏度):

temp.png

相对湿度换算公式(结果为%RH):

humidity.png

SRH和ST分别表示原始传感器输出的湿度和温度。只有当SRH和ST用十进制表示时,这些公式才能正确工作。

其中:

  • SHT30 的湿度精度为 +- 2%RH
  • SHT30 的温度精度为 +- 0.2°C

产品创建

第一步:选择品类

  1. 进入 涂鸦 IoT 开发平台,使用先前注册的账号登录。
  1. 在侧边栏单击 产品 > 产品开发 > 创建产品
  1. 在标准类目中,选择 传感 > 环境 > 温湿度传感器
product_create.png
  1. 选择 产品开发 > 自定义方案 > 温湿度传感器
product_create2.png
product_create3.png
  1. 填写 产品名称,通讯协议根据模组对应选择即可,之后单击 创建产品。
product_create4.png
  • T2-U 是 WiFi-蓝牙双模模组,通讯协议选择“WiFi-蓝牙”;同时我们当前使用USB供电,功耗类型选择“标准功耗”。

注:T2-U SDK不支持低功耗功能

第二步:选择功能

创建产品后,需要为产品选择功能。左边列表栏是可以选择的功能,右边列表栏是已经选择的功能,您可以根据实际应用场景选择对应的功能。

  1. 温湿度传感器默认已经添加了"温度"、”湿度“两个功能,其中温度为必选功能不能删除。

在左侧“选择标准功能” 点击添加需新增的功能

create_dp1.png
create_dp2.png
  1. 选择功能后,会跳转到 功能定义 界面。产品名称下方是产品的 PID 信息,中间是为产品选择的功能,可以看到功能的 ID 和数据类型等。如果想要添加功能,可以单击后面的 添加功能 进行调整。

第三步:选择控制面板

  1. 单击 设备交互,在 面板控制 栏中为产品选择控制面板。

    控制面板就是在智能生活 App 上控制设备的界面样式,不同的控制面板界面、控件风格会有所不同。平台提供了大量的公版面板供您选择,您也可以使用涂鸦提供的开发工具包,自定义开发面板或者定制面板。这里以公版面板为例。

  2. 选择控制面板后,还可以更换面板或者简单地编辑面板。您可以使用智能生活 App 扫描右侧的二维码体验面板。

control_interface.png

第四步:选择开发方式

单击 硬件开发,接入方式选择 TuyaOS

hardware_develop.png
product_function.png

配置完成后,复制 PID 至我们需要开发的代码中。

Sensor Hub 应用

Sensor Hub 组件目前已经支持 sht3x、sht4x、cht8305等温湿度传感器驱动,可以在 tdd_sensor_temp_humi 目录下找到。

根据 《TuyaOS Sensor Hub组件介绍》中介绍 Sensor Hub使用流程

  1. 调用 tdd_sensor_xxx_register 注册 xxx 设备。
  2. 调用 tdl_sensor_dev_find 查找 xxx 设备,获得设备句柄(确认 xxx 设备是否注册成功)。
  3. 调用 tdl_sensor_dev_config 配置 xxx 设备(启动前的一些必要配置;启动后也可通过调用该接口控制设备)。
  4. 调用 tdl_sensor_dev_open 启动 xxx 设备(在需要启动时调用),同时需要编写数据通知回调函数。
  5. 调用 tdl_sensor_dev_read 读取 xxx 设备的实时数据(有需要时)。
  6. 调用 tdl_sensor_dev_close 停止 xxx 设备(在需要停止时调用)。

使用示例

在 tuyaos_sensor_hub_demo_quickstart 项目的 src 目录下 app_temp_humi.c中已经实现了以上流程。

1. 设备注册、查找设备获取设备句柄

Code: Select all

STATIC OPERATE_RET __sht30_register(VOID_T)
{
    OPERATE_RET op_ret;

    SR_I2C_GPIO_T i2c_gpio = {
        .scl = SHT30_SCL_PIN,
        .sda = SHT30_SDA_PIN
    };
    SR_TH_I2C_CFG_T sht30_i2c_cfg = {
        .port = 0,
        .addr = SR_I2C_ADDR_SHT3X_A,
        .gpio = i2c_gpio
    };

    SR_TH_MEAS_CFG_T sht30_meas_cfg = {
        .prec = SR_TH_PREC_HIGH,
        .freq = SR_TH_FREQ_1HZ
    };

    op_ret = tdd_sensor_sht3x_register("SHT30", sht30_i2c_cfg, sht30_meas_cfg);
    if (OPRT_OK != op_ret) {
        TAL_PR_ERR("tdd_sensor_sht3x_register, error code: %d.", op_ret);
        return op_ret;
    }

    op_ret = tdl_sensor_dev_find("SHT30", &sg_sht30_handle);
    if (OPRT_OK != op_ret) {
        TAL_PR_ERR("tdl_sensor_dev_find, error code: %d.", op_ret);
        return op_ret;
    }

    return OPRT_OK;
}

2. 设备启动

  • 采集触发模式为:轮询(软件定时)
  • 采集间隔:APP_TEMP_HUMI_READ_CYCLE(当前应用通过宏定义为2 * 1000 ms)
  • 数据就绪通知回调:__sht30_inform_cb
  • 存放返回给app数据的缓存大小:1字节
  • 元素型数据订阅模型配置:NULL

Code: Select all

#define APP_TEMP_HUMI_READ_CYCLE            2  * 1000               // units:ms
STATIC OPERATE_RET __sht30_open(VOID_T)
{
    if (sg_sht30_flag.turn_on) {
        TAL_PR_ERR("The device is already turned on.");
        return OPRT_COM_ERROR;
    }

    OPERATE_RET op_ret;
    SR_DEV_CFG_T sht30_cfg;
    tkl_system_memset(&sht30_cfg, 0, SIZEOF(SR_DEV_CFG_T));

    sht30_cfg.mode.trig_mode = SR_MODE_POLL_SOFT_TM;
    sht30_cfg.mode.poll_intv_ms = APP_TEMP_HUMI_READ_CYCLE;
    sht30_cfg.inform_cb.ele = __sht30_inform_cb;
    sht30_cfg.fifo_size = 1;
    sht30_cfg.ele_sub = NULL;

    op_ret = tdl_sensor_dev_open(sg_sht30_handle, &sht30_cfg);
    if (OPRT_OK != op_ret) {
        TAL_PR_ERR("tdl_sensor_dev_open, error code: %d.", op_ret);
        return op_ret;
    }

    sg_sht30_flag.turn_on = TRUE;
    TAL_PR_INFO("Open device successfully.");

    return OPRT_OK;
}

3.数据获取

在回调函数中获取数据,在函数中对数据进行了比较,当前读取到的数据比上一次读取到的数据差在一定范围之内,才会触发上报。当前应用通过宏定义设置为温度上报间隔为 2.0 ℃,湿度上报间隔为 2.0 %/H

Code: Select all

#define APP_TEMP_REPORT_INTERVAL        20          // default: 2.0 ℃
#define APP_HUMI_REPORT_INTERVAL        20           // default: 2.0 %

STATIC VOID_T __sht30_inform_cb(CHAR_T* name, UCHAR_T ele_num, SR_ELE_BUFF_T *ele_data)
{
    INT_T temp, humi;

    for (UCHAR_T i = 0; i < ele_num; i++) {
        if (ele_data[i].id == SR_TH_ELE_ID_TEMP) {
            temp = (INT_T)(ele_data[i].val[0].sr_float * 10 * TEMP_SCALE);
            
            TAL_PR_INFO("Temp: %d sg_th_dp_data.temp.dp_value: %d", temp, sg_th_dp_data.temp.dp_value);
            if (temp != sg_th_dp_data.temp.dp_value) {
                if ((temp > (sg_th_dp_data.temp.dp_value + APP_TEMP_REPORT_INTERVAL)) || \
                    ((temp + APP_TEMP_REPORT_INTERVAL) < sg_th_dp_data.temp.dp_value)) {

                    sg_th_dp_data.temp.dp_value = temp;
                    sg_sht30_flag.temp_change = TRUE;
                    TAL_PR_INFO("Temp change. Enable report");
                }

            }
        } else {
            humi = (INT_T)(ele_data[i].val[0].sr_float * 10 * HUMI_SCALE);

            TAL_PR_INFO("Humi: %d sg_th_dp_data.humi.dp_value: %d", humi, sg_th_dp_data.humi.dp_value);
            if (humi != sg_th_dp_data.humi.dp_value) {
                if ((humi > (sg_th_dp_data.humi.dp_value + APP_HUMI_REPORT_INTERVAL)) || \
                    ((humi + APP_HUMI_REPORT_INTERVAL) < sg_th_dp_data.humi.dp_value)) {

                    sg_th_dp_data.humi.dp_value = humi;
                    sg_sht30_flag.humi_change = TRUE;
                    TAL_PR_INFO("Humi changed. Enable report");
                }

            }
        }
    }
}

4. 数据上报

示例中上报采用的是软件定时器轮询检测温/湿度变化标记(sg_sht30_flag.temp_change/sg_sht30_flag.humi_change)

Code: Select all

STATIC VOID_T __repo_one_dp_data(CONST UCHAR_T dp_id, CONST UCHAR_T dp_type, CONST TY_OBJ_DP_VALUE_U dp_value)
{
    GW_WIFI_NW_STAT_E wifi_stat = STAT_LOW_POWER;
    get_wf_gw_nw_status(&wifi_stat);
    if (wifi_stat <= STAT_AP_STA_DISC || wifi_stat == STAT_STA_DISC) {
        return;
    }

    TY_OBJ_DP_S dp_repo;

    dp_repo.dpid = dp_id;
    dp_repo.type = dp_type;
    dp_repo.time_stamp = 0;

    switch (dp_type) {
    case PROP_BOOL:
        dp_repo.value.dp_bool = dp_value.dp_bool;
        break;

    case PROP_VALUE:
        dp_repo.value.dp_value = dp_value.dp_value;
        break;

    case PROP_ENUM:
        dp_repo.value.dp_enum = dp_value.dp_enum;
        break;

    case PROP_STR:
        dp_repo.value.dp_str = dp_value.dp_str;
        break;

    case PROP_BITMAP:
        dp_repo.value.dp_bitmap = dp_value.dp_bitmap;
        break;

    default:
        break;
    }

    TAL_PR_INFO("repo_one_dp_data ID:%d", dp_repo.dpid);
    OPERATE_RET op_ret = dev_report_dp_json_async(NULL, &dp_repo, 1);
    if (OPRT_OK != op_ret) {
        TAL_PR_ERR("__repo_one_dp_data -- dev_report_dp_json_async, error code: %d.", op_ret);
    }
}

STATIC VOID_T __sht30_report_timer_cb(TIMER_ID timer_id, VOID_T *arg)
{
    if (sg_sht30_flag.alert) {
        __sht30_alert_occur_handler();
    }

    if (sg_sht30_flag.temp_change) {
        TAL_PR_INFO("temp change report.");
        sg_sht30_flag.temp_change = FALSE;
        __repo_one_dp_data(DP_ID_TEMP, PROP_VALUE, sg_th_dp_data.temp);
    }

    if (sg_sht30_flag.humi_change) {
        TAL_PR_NOTICE("humi change report.");
        sg_sht30_flag.humi_change = FALSE;
        __repo_one_dp_data(DP_ID_HUMI, PROP_VALUE, sg_th_dp_data.humi);
    }
}

示例修改

在 tuyaos_sensor_hub_demo_quickstart 示例中,已经实现了上面的逻辑,开发中做一些适当的修改即可使用

1. PID 修改

获取 “产品创建” 步骤中已创建产品的 PID,

PID.png

可修改 app_temp_humi.h 文件中的 PID

Code: Select all

#define PID "8q46zzdfuofastqr"

2. 功能 DP_ID 号修改

获取 “产品创建” -> "01 功能定义“ 中的标准功能下的DPID修改当前定义。

DPID.png

tuyaos_sensor_hub_demo_quickstart 中功能 DP_ID 定位在 app_temp_humi.h 文件中,根据实际情况修改。

Code: Select all

/**
 * @brief DP list
 */
#define DP_ID_TEMP      1
#define DP_ID_HUMI      2

#define DP_ID_TEMP_MAX  10
#define DP_ID_TEMP_MIN  11
#define DP_ID_HUMI_MAX  12
#define DP_ID_HUMI_MIN  13

#define DP_ID_TEMP_ALT  14
#define DP_ID_HUMI_ALT  15

#define DP_ID_SWITCH    21

#define MAX_DP_NUM          9

3. 温湿度传感器 GPIO 修改

T2-U 使用 I2C 接口连接 SHT3x,tuyaos_sensor_hub_demo_quickstart 中采用软件 I2C 链接,GPIO 定义在 app_temp_humi.h 文件中,可根据实际连接情况修改。

Code: Select all

/**
 * @brief pin define
 */
#define SHT30_SCL_PIN   GPIO_NUM_20
#define SHT30_SDA_PIN   GPIO_NUM_22
#define SHT30_ALT_PIN   GPIO_NUM_14

设备配网与使用

  1. 长按 S2 按钮,使 T2-U 进入配网状态
  2. 使用 涂鸦智能APP 对设备进行配网,连接路由器成功后,设备会自动连接涂鸦云并自动与当前用户绑定,这样就可以在 涂鸦智能APP 上发现对应的设备。
device_list.jpg
  1. 可查看智能温湿度计上报的温度
device.jpg
  1. 可进入“设置" 设置报警温度
device_set.jpg

示例代码下载

tuyaos_sensor_hub_demo_quickstart 示例代码可在以下链接中下载:

  1. github https://github.com/tuya/tuyaos-development-board-t2

  2. Tuya Wind-IDE https://developer.tuya.com/cn/docs/iot-device-dev/tuyaos-wind-ide?id=Kbfy6kfuuqqu3

T2-U开发板获取方式


Re: 使用T2-U 和 Sensor_Hub开发一款智能温湿度计

Posted: 2024年 Apr 13日 12:51
by Tswizzle

你好,我照这步骤烧录到开发板,配网后只有温度显示,湿度一直是0,请问是哪里出了问题