快速设计一款温湿度产品原型(Arduino 接入)

更新时间:2021-09-10 07:16:31

概况

温湿度传感器作为基础传感类别,在智能家居领域应用广泛。通过温湿度传感器采集温度和湿度,可以实现多样化的智能场景联动。比如在炎热的夏季,温湿度传感器检测到室内温度高于 29℃,联动打开空调,当室内温度降到 23℃ 以下时,联动关闭空调,整个过程自动智能控制调节,省心又省电,让温度始终处于舒适的范围,极大的方便了我们的生活。

基于涂鸦平台可以简单、快速地完成一款智能温湿度传感器的开发。温湿度传感器套件使用了 Arduino 开发板、涂鸦 Wi-Fi 通信板和 SHT30 温湿度传感器。传感器每隔 1 秒采集一次环境温湿度数据,并通过 I2C 接口将数据传给 Arduino 开发板;Arduino 开发板通过串口与 Wi-Fi 通信板连接,此时使用涂鸦智能 App 可对温湿度传感器进行配网,配网后可以将湿度传感器数据展现在手机端,并与其他智能设备联动。
本 Demo 教程采用 Arduino IDE 进行编程,可方便地移植于各 Arduino 系列开发板。

物料清单

硬件 (3)软件 (1)
  • 涂鸦三明治温湿度传感器功能板

    数量:1

    查看详情

  • 涂鸦三明治 Wi-Fi MCU 通信板(WB3S)

    数量:1

    查看详情

  • Arduino UNO

    数量:1

    Arduino UNO 官方开发板

步骤

  • 第 1 步:硬件连接

    本次使用的涂鸦三明治开发板温湿度传感套件主要包含:

    • 温湿度传感器功能板。板载 SHT30 温湿度传感器,I2C 接口,负责温湿度数据的采集传输。
    • Wi-Fi MCU 通信板。板载涂鸦Wi-Fi 通用模组,负责智能化连接。模组已烧录通用固件,包含 MCU 对接涂鸦串口协议,可使用模组+App+云的涂鸦智能化服务。
    • MCU控制板。采用 Arduino UNO 开发板,负责传感数据接收和模组通讯控制。

    将三明治开发板套件控制板、通讯板、功能板拼接组装,实物效果如下图。
    实装图片

  • 第 2 步:涂鸦库下载安装

    2.1 搭建环境

    参考 Arduino IDE 官方网站 下载并安装 Arduino IDE。
    下载 IDE

    2.2 安装 Tuya_WiFi_MCU_SDK 库

    有两种安装方式可供选择:

    • IDE 中搜索名为 Tuya_WiFi_MCU_SDK 的第三方库后直接安装。
    • 下载 Tuya_WiFi_MCU_SDK 软件包,解压后存放在 Arduino IDE 安装目录下的 libraries 文件夹中。

    安装成功后重启 Arduino IDE,即可看到第三方库中已经有 Tuya_WiFi_MCU_SDK 库。
    image.png

    2.3 选择示例工程

    在示例中可以看到涂鸦库中有多种基础示例,选择 SHT30 示例代码,编译下载。
    image.png

  • 第 3 步:功能详述

    体验了 Demo 例程后,接下来我们详细讲解整个 Demo 例程实现的具体步骤,开发者可以根据步骤类比,快速开发一个属于自己的温湿度传感器。
    具体开发过程可参考:Arduino 开发指南。

    3.1 创建产品

    1. 在 涂鸦IoT平台 创建产品,获取设备开发必须的 PID,DP点等信息。
      image.png
    2. 功能根据自身需求选择,这里基本功能可默认只选温湿度显示功能。
      image.png

    3.2 代码实现

    代码部分的实现主要可以分为配网、设备信息初始化、获取 SHT30 传感信息三大部分。

    配网部分
    涂鸦模组和 Arduino 板连接时会干扰到对 Arduino 板的烧录,烧录时应断开 Arduino 板与涂鸦通信板的连接。
    例程烧录成功后将 Arduino 开发板上串口(Serial)与 涂鸦模组上的 RXD 和 TXD 连接起来,然后将 Arduino 开发板上的引脚 7 连接一下GND然后断开(模拟按键按下)。传感器套件将会进入配网模式,在进入配网状态和配网过程中 Arduino 开发板上的 LED 将会闪烁,此时打开涂鸦智能 App 对套件进行配网操作。配网成功后,Arduino 开发板上的 LED 将会停止闪烁,配网成功后即可通过 App 对设备进行控制。

    注意:Arduino 开发板中的 默认 Serial 串口已被 Tuya_WiFi_MCU_SDK 接管,请不要对默认 Serial(引脚 0 ,1)做任何操作。

    /* Current LED status */
    unsigned char led_state = 0;
    /* Connect network button pin */
    int wifi_key_pin = 7;
    /* last time */
    unsigned long last_time = 0;
    
    void setup()
    {
        ...
       /* 相关外设初始化 */
      //Initialize led port, turn off led.
      pinMode(LED_BUILTIN, OUTPUT);
      digitalWrite(LED_BUILTIN, LOW);
      //Initialize networking keys.
      pinMode(wifi_key_pin, INPUT_PULLUP);
        ...
      last_time = millis();
    }
    
    void loop()
    {
        ...
      //Enter the connection network mode when Pin7 is pressed.
      if (digitalRead(wifi_key_pin) == LOW) {
        delay(80);
        if (digitalRead(wifi_key_pin) == LOW) {
          my_device.mcu_set_wifi_mode(SMART_CONFIG);
        }
      }
      /* LED blinks when network is being connected */
      if ((my_device.mcu_get_wifi_work_state() != WIFI_LOW_POWER) && (my_device.mcu_get_wifi_work_state() != WIFI_CONN_CLOUD) && (my_device.mcu_get_wifi_work_state() != WIFI_SATE_UNKNOW)) {
        if (millis()- last_time >= 500) {
          last_time = millis();
    
          if (led_state == LOW) {
            led_state = HIGH;
          } else {
            led_state = LOW;
          }
    
          digitalWrite(LED_BUILTIN, led_state);
        }
          ...
    }
    

    设备信息初始化

    #include <TuyaWifi.h>
    
    TuyaWifi my_device;
    
    /* Data point define */
    #define DPID_TEMP_CURRENT     1
    #define DPID_HUMIDITY_CURRENT 2
    
    /* Current device DP values */
    int temperature = 0;
    int humidity = 0;
    
    /* Stores all DPs and their types. PS: array[][0]:dpid, array[][1]:dp type. 
     *                                     dp type(TuyaDefs.h) : DP_TYPE_RAW, DP_TYPE_BOOL, DP_TYPE_VALUE, DP_TYPE_STRING, DP_TYPE_ENUM, DP_TYPE_BITMAP
    */
    unsigned char dp_array[][2] =
    {
      {DPID_TEMP_CURRENT, DP_TYPE_VALUE},
      {DPID_HUMIDITY_CURRENT, DP_TYPE_VALUE},
    };
    
    unsigned char pid[] = {"xxxxxxxxxxxxxxxx"};//xxxxxxxxxxxxxxxx 应为你的PID
    unsigned char mcu_ver[] = {"1.0.0"};
    
    void setup()
    {
      Serial.begin(9600);
        ...
      my_device.init(pid, mcu_ver);
      //incoming all DPs and their types array, DP numbers
      my_device.set_dp_cmd_total(dp_array, 2);
      //register DP download processing callback function
      my_device.dp_process_func_register(dp_process);
      //register upload all DP callback function
      my_device.dp_update_all_func_register(dp_update_all);
        ...
    }
    
    void loop()
    {
      my_device.uart_service();
        ...
      delay(1000);
    }
    
    /**
     * @description: DP download callback function.
     * @param {unsigned char} dpid
     * @param {const unsigned char} value
     * @param {unsigned short} length
     * @return {unsigned char}
     */
    unsigned char dp_process(unsigned char dpid,const unsigned char value[], unsigned short length)
    {
      /* all DP only report */
      return SUCCESS;
    }
    
    /**
     * @description: Upload all DP status of the current device.
     * @param {*}
     * @return {*}
     */
    void dp_update_all(void)
    {
      my_device.mcu_dp_update(DPID_TEMP_CURRENT, temperature, 1);
      my_device.mcu_dp_update(DPID_HUMIDITY_CURRENT, humidity, 1);
    }
    

    获取SHT30传感器信息

    #include <Wire.h>
    
    /* SHT30 */
    #define SHT30_I2C_ADDR 0x44
    
    /* Current device DP values */
    int temperature = 0;
    int humidity = 0;
    
    void setup()
    {
        ...
      // Initialise I2C communication as MASTER
      Wire.begin();
        ...
    }
    
    void loop()
    {
        ...
      /* get the temperature and humidity */
      get_sht30_value(&temperature, &humidity);
    
      if ((my_device.mcu_get_wifi_work_state() == WIFI_CONNECTED) || (my_device.mcu_get_wifi_work_state() == WIFI_CONN_CLOUD)) {
        my_device.mcu_dp_update(DPID_TEMP_CURRENT, temperature, 1);
        my_device.mcu_dp_update(DPID_HUMIDITY_CURRENT, humidity, 1);
      }
    
      delay(1000);
    }
    
    void get_sht30_value(int *temp_value, int *humi_value)
    {
      unsigned char i2c_data[6];
    
      // Start I2C Transmission
      Wire.beginTransmission(SHT30_I2C_ADDR);
      // Send measurement command
      Wire.write(0x2C);
      Wire.write(0x06);
      // Stop I2C transmission
      Wire.endTransmission();
      delay(500);
    
      // Request 6 bytes of data
      Wire.requestFrom(SHT30_I2C_ADDR, 6);
    
      // Read 6 bytes of i2c_data
      // temperature msb, temperature lsb, temperature crc, humidity msb, humidity lsb, humidity crc
      if (Wire.available() == 6) {
        for (int i = 0; i < 6 ; i++) {
          i2c_data[i] = Wire.read();
        }
        
        if ((sht30_crc(i2c_data, 2) == i2c_data[2]) && (sht30_crc(i2c_data+3, 2) == i2c_data[5])) {/* crc success */
          *temp_value = (((((i2c_data[0] * 256.0) + i2c_data[1]) * 175) / 65535.0) - 45) * 100;
          *humi_value = ((((i2c_data[3] * 256.0) + i2c_data[4]) * 100) / 65535.0) * 100;
        } else {
          *temp_value = 0;
          *humi_value = 0;
        }
      }
    }
    
    /**
     * @description: check sht30 temperature and humidity data
     * @param {unsigned char} *data
     * @param {unsigned int} count
     * @return {*}
     */
    unsigned char sht30_crc(unsigned char *data, unsigned int count)
    {
        unsigned char crc = 0xff;
        unsigned char current_byte;
        unsigned char crc_bit;
    
        /* calculates 8-Bit checksum with given polynomial */
        for (current_byte = 0; current_byte < count; ++current_byte)
        {
            crc ^= (data[current_byte]);
            for (crc_bit = 8; crc_bit > 0; --crc_bit)
            {
                if (crc & 0x80)
                    crc = (crc << 1) ^ 0x31;
                else
                    crc = (crc << 1);
            }
        }
        return crc;
    }
    
  • 第 4 步:配网联动

    编译下载完成,根据示例代码,将 Arduino 开发板上的引脚 7 连接一下GND然后断开(模拟按键按下),Arduino板会给模组发重置配网指令,板载 LED 进入闪烁状态,表示模组进入配网模式。此时可以使用涂鸦智 App 给模组配网,配网成功后,即可测试数据上报下发。
    App

    所有功能调试通过后,App 端已经可以接收到温湿度传感器的数据。智能传感器最大的应用场景是用来收集传感数据来和其它产品进行联动,如果开发者手中有涂鸦生态设备或开发板,可以在 App 端实现场景联动功能的配置。场景联动的配置可参考 场景联动设置。

    image.png

小结

基于涂鸦平台,使用涂鸦三明治开发板,Arduino IDE 编程,快速实现一款智能温湿度传感器产品原型搭建。