首页 > 代码库 > Arduino I2C + 温湿度传感器Si7021

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(115200); 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) 62     { 63         Serial.println("CRC checked."); 64     } 65     else 66     { 67         Serial.println("CRC 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

Arduino I2C + 温湿度传感器Si7021