
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 }
若連接正常,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
