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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM