主要特性
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 HTS2213 */
4
5 #include
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 floatt0, t1, h0, h1;22 intt0out, t1out, h0out, h1out;23
24 int outHumi = 0;25 int outTemp = 0;26 float valueHumi = 0;27 float valueTemp = 0;28
29 voidsetup()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 voidloop()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 voidReadCaliData()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, floatout_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也并未给出已验证的典型误差和最大误差,实测湿度误差较大。
参考资料