Arduino I2C + 温湿度传感器HTS221

摘要:
可以设置1.7~3.6V数据输出频率(ODR):但用户需要读取校准信息并计算校准后的结果包:这是同类型传感器的最小片上集成加热器引脚的定义以及其他温度和湿度传感器的比率:当CS=1时,它是I2C接口:当测量完成且温度和湿度数据可供读取时:该功能也可通过设置控制寄存器(CTRL_REG3)关闭,尽管HTS221支持I2C和三线SPI接口以连接到Arduino。

主要特性

Arduino I2C + 温湿度传感器HTS221第1张

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)

管脚定义

Arduino I2C + 温湿度传感器HTS221第2张

和其他的温湿度传感器比,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总线所需的上拉电阻。

Arduino I2C + 温湿度传感器HTS221第3张

功能调试

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的操作上。

测试代码

Arduino I2C + 温湿度传感器HTS221第4张Arduino I2C + 温湿度传感器HTS221第5张
  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秒触发一次测量并打印结果:

Arduino I2C + 温湿度传感器HTS221第6张

结论

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

参考资料

HTS221 Capacitive digital sensor for relative humidity and temperature

免责声明:文章转载自《Arduino I2C + 温湿度传感器HTS221》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇git 发布版本eventlet的学习下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

plsql导出导入 表结构、表数据、存储过程等

导出:首先点击   TOOLS,选择  EXPORT TABLES  选中你需要导出的表,   勾选  “Create tables” 是因为在导入的数据库中没有此表 如果勾选"Drop tables" 而没有勾选 “Create tables” ,而数据库中没有此表,会报表和视图不存在 Output file 为导出的路径   如果你想导的表  数据记录...

浅谈银行数据仓库:数据集市建模思路 ——监管报送项目的数据集市建模实践

前言:数据集市的目标   数据集市,是数据仓库 ADM 层最主要的数据形态,应用在特定业务场景的高度汇总数据,支持特定人员或部门进行数据分析、统计、决策等行为。(数据仓库分层架构及建设思路可查阅作者的《浅谈银行数据仓库的构建之路》)概念理解起来不难,难在如何制定数据集市的落地方式,这时必须结果导向,从实现目标进行反推。 数据集市的目标   从概念可以了解,...

二维码知识介绍(转)

一、二维码的分类 二维码,从字面上看就是用两个维度(水平方向和垂直方向)来进行数据的编码,条形码只利用了一个维度(水平方向)表示信息,在另一个维度(垂直方向)没有意义,所以二维码比条形码有着更高的数据存储容量。 从形成方式上,二维码可以分为两类, 1、堆叠式二维码:在一维条形码的基础上,将多个条形码堆积在一起进行编码,常见的编码标准有PDF417等   ...

MySQL主从复制什么原因会造成不一致,如何预防及解决?

一、导致主从不一致的原因主要有: 人为原因导致从库与主库数据不一致(从库写入) 主从复制过程中,主库异常宕机 设置了ignore/do/rewrite等replication等规则 binlog非row格式 异步复制本身不保证,半同步存在提交读的问题,增强半同步起来比较完美。 但对于异常重启(Replication Crash Safe),从库写数据(G...

Hive 以及mysql 中如何做except 数据操作

在db2 和 oracle 中 ,当我们想知道两张结构相同的table 中,数据差异时候可以采用如下sql : select * from table1 except select * from table2 上面语句 求出来的就是 数据在table1 而不再table2 中的数据 , 但是令人失望的是mysql 和hive 中竟然没有提供这样子...

Oracle 存储过程,触发器,事务,锁

1.1存储过程   存储过程是一种命名的PL/SQL程序块,他可以有参数,也可以有若干个输入、输出参数。甚至可以有多个即做输入又做输出的参数,但他都没有返回值。存储过程被保存在数据库中,他不可以被SQL语句直接执行调用。通过EXECUTE命令或在PL/SQL命令中调用,因为存储过程是已经编译好的代码块,所以被调用或引用时,执行效率很高。 1.1.1 存储过...