Arduino I2C + 温湿度传感器Si7021#

img img

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总线需要的上拉电阻

img

功能调试#

  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”文档。

测试代码#

/*
Measurement of relative humidity and temperature using Si7021
*/

#include <Wire.h>

#define ADDRESS_SI7021 0x40
#define MEASURE_RH_HOLD 0xE5
#define READ_T_FROM_PRE_RH_MEASUREMENT 0xE0

byte buffer[] = {0, 0, 0};
byte crcHumi;

word outHumi = 0;
word outTemp = 0;
float valueHumi = 0;
float valueTemp = 0;

void setup()
{
    Wire.begin();
    Serial.begin(9600);
}

void loop()
{
    //perform a RH measurement and read back the RH value
    Wire.beginTransmission(ADDRESS_SI7021);
    Wire.write(MEASURE_RH_HOLD);
    Wire.endTransmission();

    Wire.requestFrom(ADDRESS_SI7021, 3);
    if(Wire.available() >= 3)
    {
        buffer[0] = Wire.read(); //high byte
        buffer[1] = Wire.read(); //low byte
        buffer[2] = Wire.read(); //crc
    }
    outHumi = (buffer[0]<<8) | buffer[1];
    crcHumi = CRC8(buffer, 3);

    //read temperature from previous RH measurement
    Wire.beginTransmission(ADDRESS_SI7021);
    Wire.write(READ_T_FROM_PRE_RH_MEASUREMENT);
    Wire.endTransmission();

    Wire.requestFrom(ADDRESS_SI7021, 2);
    if(Wire.available() >= 2)
    {
        buffer[0] = Wire.read(); //high byte
        buffer[1] = Wire.read(); //low byte; no crc
    }
    outTemp = (buffer[0]<<8) | buffer[1];

    valueHumi = 125.0*outHumi/65536 - 6;
    valueTemp = 175.72*outTemp/65536 - 46.85;

    Serial.print(valueHumi);    Serial.print(" \%RH\t");
    Serial.print(valueTemp);    Serial.println(" `C");

    if (crcHumi == 0 && outHumi != 0 && outTemp != 0)
    {
        Serial.println("CRC checked.");
    }
    else
    {
        Serial.println("Error!");
    }

    delay(4000);
}

byte CRC8(byte *data, byte len)
{
    byte crc[8];
    byte result = 0;
    byte i;
    byte doInvert;
    String bitString = MakeString(data, len);

    for (i = 0; i < 8; i++)
    {
        crc[i] = 0;
    }

    for (i = 0; i < bitString.length(); i ++)
    {
        doInvert = (byte(bitString[i] == '1')) ^ crc[7];
        crc[7] = crc[6];
        crc[6] = crc[5];
        crc[5] = crc[4] ^ doInvert;
        crc[4] = crc[3] ^ doInvert;
        crc[3] = crc[2];
        crc[2] = crc[1];
        crc[1] = crc[0];
        crc[0] = doInvert;
    }

    for (i = 0; i < 8; i++)
    {
        bitWrite(result, i, crc[i]);
    }

    return result;
}

String MakeString(byte *data, byte len)
{
    int i, j;
    String tempString[len];
    String bitString="";

    for (i = 0; i < len; i++)
    {
        tempString[i] = String(data[i], BIN);
        int zeros = 8 - tempString[i].length();
        for (j = 0; j < zeros; j++)
        {
            tempString[i] = '0' + tempString[i];
        }
    }

    for (i = 0; i < len; i++)
    {
        bitString = bitString + tempString[i];
    }

    return bitString;
}

若连接正常,Si7021将会每隔4秒触发一次测量,并通过串口打印结果:

img

参考资料#

  • [Silicon Labs - Si7021 Datasheet](http://www.silabs.com/Support Documents/TechnicalDocs/Si7021.pdf)

  • [Application Note: Bi-directional level shifter for i2c bus and other systems](http://www.cnblogs.com/Bi-directional level shifter for i2c bus and other systems)

  • [Application Note: Si70xx Humidity Sensor Designer's Guide]

  • Online CRC Calculation