• 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	");
     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

  • 相关阅读:
    【Java例题】3.1 7、11、13的倍数
    【Java例题】2.7找零钱
    【Java例题】2.6 三角形的面积
    【Java例题】2.5 温度转换
    【Java例题】2.4求函数
    【Java例题】2.2 分数类
    【Java例题】2.3 计算银行存款本息
    博客园里面关于abpZero的好的教程
    IOC学习1
    1.开始第一个MVC项目
  • 原文地址:https://www.cnblogs.com/zlbg/p/4185802.html
Copyright © 2020-2023  润新知