Arduino I2C + 溫濕度傳感器Si7021


 

Si7021是Silicon Labs生產的溫濕度傳感器芯片。其主要特性:

  • 濕度精度:誤差典型值+/-2%RH,最大值+/-3%RH(0~80%RH),出廠已校正
  • 溫度精度:誤差典型值+/-0.3°C,最大值+/-0.4°C(-10°C~85°C),出廠已校正
  • 測量范圍:溫度范圍0~100%RH;溫度范圍最大-40°C~125°C
  • 工作電壓:1.9~3.6V
  • 低功耗:工作時150μA,待機時60nA
  • 接口:I2C,最大速率支持400kbps
  • 長期穩定性:濕度≤0.25%RH/yr,溫度≤0.01°C/yr
  • 封裝:3x3 mm DFN
  • 片上集成加熱器(heater)
  • 可選的疏水性保護蓋


Arduino的連接

由於Arduino UNO的工作電壓是5V,而Si7021無法在5V電平下工作,二者的連接需要電平轉換。轉換的方法是在Si7021和Arduino中間通過I2C Logic Level Converter進行連接。雙向邏輯電平轉換器的原理可參考Philips Semiconductor的應用筆記“Bi-directional level shifter for i2c bus and other systems”。轉換器兩端都自帶了I2C總線需要的上拉電阻

功能調試

1. Si7021測量過程中,可以選擇讓其將SCL拉低(Hold Master Mode),或者不回應MCU發來的訊息(No Hold Master Mode)。

2. 相對濕度測量包含了溫度測量;溫度測量可以單獨進行。

3. 進行相對濕度或溫度測量時,MCU對測量值低字節是否發送ACK,決定了Si7021是否返回CRC校驗碼。當讀取上次相對濕度測量時的溫度值時,Si7021不回復CRC校驗碼。以下代碼中有一半內容是CRC校驗相關的,並不是必須的,CRC算法也未進行優化。

4. 當Si7021用於環境測量時,芯片放置、PCB熱阻隔設計對測量精度、響應時間有很大影響,具體可參見官方“Si70xx Humidity Sensor Designer's Guide”文檔。

測試代碼

 

  1 /*
  2 Measurement of relative humidity and temperature using Si7021
  3 */
  4 
  5 #include <Wire.h>
  6 
  7 #define ADDRESS_SI7021 0x40
  8 #define MEASURE_RH_HOLD 0xE5
  9 #define READ_T_FROM_PRE_RH_MEASUREMENT 0xE0
 10 
 11 byte buffer[] = {0, 0, 0};
 12 byte crcHumi;
 13 
 14 word outHumi = 0;
 15 word outTemp = 0;
 16 float valueHumi = 0;
 17 float valueTemp = 0;
 18 
 19 void setup()
 20 {
 21     Wire.begin();
 22     Serial.begin(9600);
 23 }
 24 
 25 void loop()
 26 {
 27     //perform a RH measurement and read back the RH value
 28     Wire.beginTransmission(ADDRESS_SI7021);
 29     Wire.write(MEASURE_RH_HOLD);
 30     Wire.endTransmission();
 31 
 32     Wire.requestFrom(ADDRESS_SI7021, 3);
 33     if(Wire.available() >= 3)
 34     {
 35         buffer[0] = Wire.read(); //high byte
 36         buffer[1] = Wire.read(); //low byte
 37         buffer[2] = Wire.read(); //crc
 38     }
 39     outHumi = (buffer[0]<<8) | buffer[1];
 40     crcHumi = CRC8(buffer, 3);
 41     
 42     //read temperature from previous RH measurement  
 43     Wire.beginTransmission(ADDRESS_SI7021);
 44     Wire.write(READ_T_FROM_PRE_RH_MEASUREMENT);
 45     Wire.endTransmission();
 46 
 47     Wire.requestFrom(ADDRESS_SI7021, 2);
 48     if(Wire.available() >= 2)
 49     {
 50         buffer[0] = Wire.read(); //high byte
 51         buffer[1] = Wire.read(); //low byte; no crc
 52     }
 53     outTemp = (buffer[0]<<8) | buffer[1];
 54 
 55     valueHumi = 125.0*outHumi/65536 - 6;
 56     valueTemp = 175.72*outTemp/65536 - 46.85;
 57 
 58     Serial.print(valueHumi);    Serial.print(" \%RH\t");
 59     Serial.print(valueTemp);    Serial.println(" `C");
 60 
 61     if (crcHumi == 0 && outHumi != 0 && outTemp != 0)
 62     {
 63         Serial.println("CRC checked.");
 64     }
 65     else
 66     {
 67         Serial.println("Error!");
 68     }
 69 
 70     delay(4000);
 71 }
 72 
 73 byte CRC8(byte *data, byte len)
 74 {
 75     byte crc[8];
 76     byte result = 0;
 77     byte i;
 78     byte doInvert;
 79     String bitString = MakeString(data, len);
 80 
 81     for (i = 0; i < 8; i++)
 82     {
 83         crc[i] = 0;
 84     }
 85 
 86     for (i = 0; i < bitString.length(); i ++)
 87     {
 88         doInvert = (byte(bitString[i] == '1')) ^ crc[7];
 89         crc[7] = crc[6];
 90         crc[6] = crc[5];
 91         crc[5] = crc[4] ^ doInvert;
 92         crc[4] = crc[3] ^ doInvert;
 93         crc[3] = crc[2];
 94         crc[2] = crc[1];
 95         crc[1] = crc[0];
 96         crc[0] = doInvert;
 97     }
 98 
 99     for (i = 0; i < 8; i++)
100     {
101         bitWrite(result, i, crc[i]);
102     }
103 
104     return result;
105 }
106 
107 String MakeString(byte *data, byte len)
108 {
109     int i, j;
110     String tempString[len];
111     String bitString="";
112 
113     for (i = 0; i < len; i++)
114     {
115         tempString[i] = String(data[i], BIN);
116         int zeros = 8 - tempString[i].length();
117         for (j = 0; j < zeros; j++)
118         {
119             tempString[i] = '0' + tempString[i];
120         }
121     }
122 
123     for (i = 0; i < len; i++)
124     {
125         bitString = bitString + tempString[i];
126     }
127 
128     return bitString;
129 }
View Code

 

若連接正常,Si7021將會每隔4秒觸發一次測量,並通過串口打印結果:


參考資料

Silicon Labs - Si7021 Datasheet
Application Note: Bi-directional level shifter for i2c bus and other systems
Application Note: Si70xx Humidity Sensor Designer's Guide
Online CRC Calculation


免責聲明!

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



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