• Arduino I2C + 温湿度传感器HTS221


    主要特性

    HTS221是意法半导体(STMicroelectronics)生产的小体积、数字式温湿度传感器IC。该IC目前在官网仍处在“评估”状态。其主要特性:

    • 工作电压:1.7~3.6V
    • 数据输出频率(ODR)可设:1Hz ~ 12.5Hz
    • 低功耗:2μA@1Hz ODR
    • 温度精度:给出误差典型值+/-0.5°C, 15~40°C;但注明“Typical specifications are not guaranteed.”。无误差最大值信息。
    • 湿度精度:给出误差典型值+/-4.5%RH, 20~80%RH;同样注明“Typical specifications are not guaranteed.”。无误差最大值信息。
    • 内置16-bit ADC
    • 接口:I2C或3-wire SPI
    • 出厂已校准,但需要用户自行读取校准信息、并计算校准后的结果
    • 封装:2 x 2 x 0.9mm HLGA-6L封装,是已知同类传感器中体积最小的
    • 片上集成加热器(heater)

    管脚定义

    和其他的温湿度传感器比,HTS221的芯片管脚功能更多、也略显复杂:

    • VDD:电源,支持1.7~3.6V电压
    • GND:地
    • CS:I2C/3-wire SPI接口选择,当CS=1时为I2C接口,反之为3-wire SPI接口。默认为1。
    • SCL/SPC:I2C或3-wire SPI接口的时钟线,由CS选择。
    • SDA/SDI/SDO:I2C或3-wire SPI接口的数据线,由CS选择。
    • DRDY:提供Data Ready信号输出。当测量完成、有温湿度数据可供读取时,DRDY为高电平;当无温湿度数据、或温湿度数据已被读取完毕后,DRDY为低电平。该功能也可以通过设置控制寄存器(CTRL_REG3)关闭。

    与Arduino的连接

    虽然HTS221支持I2C、3-wire SPI接口。对于3-wire SPI接口,其数据输入/输出(SDI/SDO)共用一条信号线,不同于Arduino的四线制SPI,有MOSI、MOSI信号线的区分。因此还是通过I2C接口连接。由于Arduino UNO正常工作在5V电压下,因此二者的连接还需要I2C Logic Level Converter。留意Converter带了I2C总线所需的上拉电阻。

    功能调试

    1. HTS221内置不少寄存器,每个寄存器都有一个8bit的子地址(sub-address)。在操作时,既可以单独对某个地址的寄存器进行I2C读/写,也可以在一次I2C命令中对连续的多个地址的寄存器进行读/写。

    2. 手册没有给出每次测量所需的测量时间,实测默认配置下one shot测量用时约3ms。代码中通过读取STATUS_REG寄存器,来判断一次测量是否完毕。也可以通过读取DRDY管脚信号进行判断。

    3. HTS221将出厂前的校准信息保存在内部寄存器中,温度校准有两对数据:t0 & t0out, t1 & t1out,湿度校准亦有两对数据:h0 & h0t0out, h1 & h1t0out。从命名上看,湿度校准数据是在t0温度下做的。MCU将HTS221温湿度输出值得到后,还需要利用这两组校正数据进行反推(线性插值),继而获得所代表的温湿度测量结果。代码在初始化部分,读取了四组校准数据并打印了出来。
        为什么不能像其他传感器那样,读出来的值就是计算好的最终结果呢?

    4. Arduino库自带的map()只能对整型进行操作,因此将其改成了对浮点数进行操作。

    5. 从测量结果上看,湿度动辄75%以上,明显偏高不少。

    6. 尝试用中断函数捕获DRDY上升沿,进而在中断函数中进行数据读取。可是不知为何,中断函数会卡在对I2C的操作上。

    测试代码

      1 /*
      2 Measurement of relative humidity and temperature using HTS221
      3 */
      4 
      5 #include <Wire.h>
      6 
      7 #define ADDRESS_HTS221 0x5F
      8 #define CTRL_REG1 0x20
      9 #define CTRL_REG2 0x21
     10 #define STATUS_REG 0x27
     11 #define HUMIDITY_OUT_L_REG 0x28
     12 #define T0_degC_x8 0x32
     13 #define T0_OUT 0x3C
     14 #define H0_rH_x2 0x30
     15 #define H0_T0_OUT 0x36
     16 #define H1_T0_OUT 0x3A
     17 
     18 byte buffer[] = {0, 0, 0, 0};
     19 byte status = 0;
     20 
     21 float t0, t1, h0, h1;
     22 int t0out, t1out, h0out, h1out;
     23 
     24 int outHumi = 0;
     25 int outTemp = 0;
     26 float valueHumi = 0;
     27 float valueTemp = 0;
     28 
     29 void setup()
     30 {
     31     Wire.begin();
     32     Serial.begin(9600);
     33 
     34     //turn on the HTS221, set the update mode to one shot
     35     Wire.beginTransmission(ADDRESS_HTS221);
     36     Wire.write(CTRL_REG1);
     37     Wire.write(0x84);
     38     Wire.endTransmission();
     39 
     40     ReadCaliData();
     41 
     42     //print the calibration coefficients
     43     Serial.println("Calibration coefficients: ");
     44     Serial.print("t0 = "); Serial.print(t0); Serial.print(" `C, t0out = "); Serial.println(t0out);
     45     Serial.print("t1 = "); Serial.print(t1); Serial.print(" `C, t1out = "); Serial.println(t1out);
     46     Serial.print("h0 = "); Serial.print(h0); Serial.print(" \%RH, h0out = "); Serial.println(h0out);
     47     Serial.print("h1 = "); Serial.print(h1); Serial.print(" \%RH, h1out = "); Serial.println(h1out);
     48     Serial.println("------------------------");
     49 }
     50 
     51 void loop()
     52 {
     53     //perform a measurement
     54     Wire.beginTransmission(ADDRESS_HTS221);
     55     Wire.write(CTRL_REG2);
     56     Wire.write(0x01);
     57     Wire.endTransmission();
     58 
     59     //check the status
     60     status = 0;
     61     while (status != 0x03) //typical conversition time: 3ms
     62     {
     63         delayMicroseconds(3000);
     64         Wire.beginTransmission(ADDRESS_HTS221);
     65         Wire.write(STATUS_REG);
     66         Wire.endTransmission();
     67 
     68         Wire.requestFrom(ADDRESS_HTS221, 1);
     69         if(Wire.available() >= 1)
     70         {
     71             status = Wire.read(); 
     72         }
     73         delayMicroseconds(500);
     74         // Serial.println(status, HEX);
     75     }
     76 
     77     //read multiple bytes incrementing the register address
     78     Wire.beginTransmission(ADDRESS_HTS221);
     79     Wire.write(HUMIDITY_OUT_L_REG | 0x80);
     80     Wire.endTransmission();
     81 
     82     Wire.requestFrom(ADDRESS_HTS221, 4);
     83     if (Wire.available() >= 4)
     84     {
     85         for (byte i = 0; i < 4; i++)
     86         {
     87             buffer[i] = Wire.read();
     88         }
     89     }
     90 
     91     outHumi = (buffer[1] << 8) | buffer[0];
     92     outTemp = (buffer[3] << 8) | buffer[2];
     93 
     94     valueTemp = mapFloat(outTemp, t0out, t1out, t0, t1);
     95     valueHumi = mapFloat(outHumi, h0out, h1out, h0, h1);
     96     Serial.print(valueTemp); Serial.print(" `C, ");
     97     Serial.print(valueHumi); Serial.println(" \%RH");
     98 
     99     delay(4000);
    100 }
    101 
    102 void ReadCaliData()
    103 {
    104     //read out t0degCx8, t1degCx8
    105     Wire.beginTransmission(ADDRESS_HTS221);
    106     Wire.write(T0_degC_x8 | 0x80);
    107     Wire.endTransmission();
    108     Wire.requestFrom(ADDRESS_HTS221, 4);
    109     if (Wire.available() >= 4)
    110     {
    111         for (byte i = 0; i < 4; i++)
    112         {
    113             buffer[i] = Wire.read();
    114         }
    115     }
    116     word t0degCx8 = ((buffer[3] & 0b00000011) << 8) | buffer[0];
    117     word t1degCx8 = ((buffer[3] & 0b00001100) << 6) | buffer[1];
    118     t0 = t0degCx8/8.0;
    119     t1 = t1degCx8/8.0;
    120 
    121     //read out t0out, t1out
    122     Wire.beginTransmission(ADDRESS_HTS221);
    123     Wire.write(T0_OUT | 0x80);
    124     Wire.endTransmission();
    125     Wire.requestFrom(ADDRESS_HTS221, 4);
    126     if (Wire.available() >= 4)
    127     {
    128         for (byte i = 0; i < 4; i++)
    129         {
    130             buffer[i] = Wire.read();
    131         }
    132     }
    133     t0out = (buffer[1] << 8) | buffer[0];
    134     t1out = (buffer[3] << 8) | buffer[2];
    135 
    136     //read out h0RHx2, h1RHx2
    137     Wire.beginTransmission(ADDRESS_HTS221);
    138     Wire.write(H0_rH_x2 | 0x80);
    139     Wire.endTransmission();
    140 
    141     Wire.requestFrom(ADDRESS_HTS221, 2);
    142     if (Wire.available() >= 2)
    143     {
    144         for (byte i = 0; i < 2; i++)
    145         {
    146             buffer[i] = Wire.read();
    147         }
    148     }
    149     byte h0RHx2 = buffer[0];
    150     byte h1RHx2 = buffer[1];
    151     h0 = h0RHx2/2.0;
    152     h1 = h1RHx2/2.0;
    153 
    154     //read out h0t0Out
    155     Wire.beginTransmission(ADDRESS_HTS221);
    156     Wire.write(H0_T0_OUT | 0x80);
    157     Wire.endTransmission();
    158     Wire.requestFrom(ADDRESS_HTS221, 2);
    159     if (Wire.available() >= 2)
    160     {
    161         for (byte i = 0; i < 2; i++)
    162         {
    163             buffer[i] = Wire.read();
    164         }
    165     }
    166     h0out = (buffer[1] << 8) | buffer[0];
    167 
    168     //read out h1t0Out
    169     Wire.beginTransmission(ADDRESS_HTS221);
    170     Wire.write(H1_T0_OUT | 0x80);
    171     Wire.endTransmission();
    172     Wire.requestFrom(ADDRESS_HTS221, 2);
    173     if (Wire.available() >= 2)
    174     {
    175         for (byte i = 0; i < 2; i++)
    176         {
    177             buffer[i] = Wire.read();
    178         }
    179     }
    180     h1out = (buffer[1] << 8) | buffer[0];
    181 }
    182 
    183 float mapFloat(int x, int in_min, int in_max, float out_min, float out_max)
    184 {
    185   return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
    186 }
    View Code

    首先打印HTS221保存的校准信息,之后会每隔4秒触发一次测量并打印结果:

    结论

    与Si7021比,HTS221(under evaluation)的体积更小、接口更丰富,使用更灵活,但在硬件接口和软件操作上都略显复杂。精度上,datasheet也并未给出已验证的典型误差和最大误差,实测湿度误差较大。

    参考资料

    HTS221 Capacitive digital sensor for relative humidity and temperature

  • 相关阅读:
    冒泡排序
    Objective-C 命名规范
    时间轴的制作
    CocoaPods 哪些事
    消息转发机制入门篇
    架构
    算法学习
    AutoLayout自动布局
    网络学习
    HDU 3832 Earth Hour (最短路)
  • 原文地址:https://www.cnblogs.com/zlbg/p/4216251.html
Copyright © 2020-2023  润新知