• 【mcuclub】CO2及TVOC检测-SGP30


    一、实物图

    二、原理图

    编号名称功能
    1VCC电源正
    2GND电源地
    3SDA串行地址和数据输入/输出
    4SCL串行时钟输入

    三、简介

    SGP30是一款单一芯片上具有多个传感元件的金属氧化物室内气体传感器,内部集成4个气体传感元件,具有完全校准的空气质量输出信号,主要是对空气质量进行检测。可以输出:

    TVOC(Total Volatile Organic Compounds,总挥发性有机物),量程为0~60000ppb;CO2浓度,量程400~60000ppm。

    四、工作原理

    SGP30的传感(MEMS)部分基于金属氧化物(MOx)纳米颗粒的加热膜。气敏材料——金属氧化物颗粒上吸附的氧气与目标气体发生反应,从而释放出电子。这导致由传感器测量的金属氧化物层的电阻发生改变。简而言之,还原性气体的出现造成气敏材料表面氧浓度降低,改变了半导体的电阻(或电导率)。后续通过电路(ASIC)部分对电阻进行检测、信号处理与转换等,最终获取到气体值。

    五、通信协议(I2C通信)

    1、I2C总线介绍

    <1>I2C总线(Inter IC bus)是由Philips公司开发的一种通用数据总线。

    <2>两根通信线:SCL(Serial Clock串行时钟线)、SDA(Serial Data串行数据线)。

    <3>同步、半双工,带数据应答。

    *注:同步(因为它有单独的时钟线)、半双工(SDA只有一根线,并且还要来回通信)

    <4>通用的I2C总线,可以使各种设备的通信标准统一,对于厂家来说,使用成熟的方案可以缩短芯片设计周期、提高稳定性,对于应用者来说,使用通用的通信协议可以避免学习各种各样的自定义协议,降低了学习和应用的难度。

    2、I2C电路规范

    <1>所有I2C设备的SCL连在一起,SDA连在一起

    <2>设备的SCL和SDA均要配置成开漏输出模式(硬件IIC)

    *开漏输出模式——断开时引脚成浮空状态(电路断开,电压不稳定)

    <3>SCL和SDA各添加一个上拉电阻,阻值一般为4.7K~10K左右

    <4>开漏输出和上拉电阻的共同作用实现了“线与”的功能,此设计主要是为了解决多机通信互相干扰的问题。

    3、I2C时序结构

    起始信号:SCL高电平期间,SDA从高电平切换到低电平

    停止信号:SCL高电平期间,SDA从低电平切换到高电平

    代码如下:

    /****

    *******I2C总线启动信号

    *****/

    void SGP30_IIC_Start(void)

    {

       SGP30_SDA = 1;

       SGP30_SCL = 1;

       SGP30_IIC_Delay(DELAY_TIME);

       SGP30_SDA = 0;

       SGP30_IIC_Delay(DELAY_TIME);

       SGP30_SCL = 0;

    }

    /****

    *******I2C总线停止信号

    *****/

    void SGP30_IIC_Stop(void)

    {

       SGP30_SDA = 0;

       SGP30_SCL = 1;

       SGP30_IIC_Delay(DELAY_TIME);

       SGP30_SDA = 1;

       SGP30_IIC_Delay(DELAY_TIME);

    }

    发送应答:在接收完一个字节之后,主机在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答。

    接收应答:在发送完一个字节之后,主机在下一个时钟接收一位数据,判断从机是否应答,数据0表示应答,数据1表示非应答(主机在接收之前,需要释放SDA)。

    代码如下:

    /****

    *******发送应答或非应答信号

    *****/

    void SGP30_IIC_SendAck(bit ackbit)

    {

       SGP30_SCL = 0;

       SGP30_SDA = ackbit;

       SGP30_IIC_Delay(DELAY_TIME);

       SGP30_SCL = 1;

       SGP30_IIC_Delay(DELAY_TIME);

       SGP30_SCL = 0;

       SGP30_SDA = 1;

       SGP30_IIC_Delay(DELAY_TIME);

    }

    /****

    *******等待应答信号

    *****/

    bit SGP30_IIC_WaitAck(void)

    {

       bit ackbit;

       SGP30_SDA = 1;

       SGP30_SCL = 1;

       SGP30_IIC_Delay(DELAY_TIME);

       ackbit = SGP30_SDA;

       SGP30_SCL = 0;

       SGP30_IIC_Delay(DELAY_TIME);

       return ackbit;

    }

    发送一个字节:SCL低电平期间,主机将数据位依次放到SDA线上(高位在前),然后拉高SCL,主机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可发送一个字节。

    代码如下:

    /****

    *******I2C总线发送一个字节数据

    *****/

    void SGP30_IIC_SendByte(uchar byte)

    {

       uchar i;

       SGP30_SCL = 0;

       for(i=0; i<8; i++)

       {

          if(byte & 0x80)

             SGP30_SDA = 1;

          else

             SGP30_SDA = 0;

          SGP30_IIC_Delay(DELAY_TIME);

          SGP30_SCL = 1;

          SGP30_IIC_Delay(DELAY_TIME);

          SGP30_SCL = 0;

          SGP30_IIC_Delay(DELAY_TIME);

          byte <<= 1;

       }

       SGP30_IIC_WaitAck();

    }

    接收一个字节:SCL低电平期间,从机将数据位依次放到SDA总线上(高位在前),然后拉高SCL,从机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可接收一个字节(主机在接收之前,需要释放SDA)

    代码如下:

    /****

    *******I2C总线接收一个字节数据

    *****/

    uchar SGP30_IIC_RecByte(bit ackbit)

    {

       uchar i, dat;

       SGP30_SDA = 1;

       for(i=0; i<8; i++)

       {

          SGP30_SCL = 1;

          SGP30_IIC_Delay(DELAY_TIME);

          dat <<= 1;

          if(SGP30_SDA)

             dat |= 1;

          SGP30_SCL = 0;

          SGP30_IIC_Delay(DELAY_TIME);

       }

       SGP30_IIC_SendAck(ackbit);

       return dat;

    }

    4、SGP30读取数据

    I2C从机地址是0X58,由于地址只用到了7bit,最高位未使用,最低位为判断是读还是写,为0是读,为1是写,所以:

    • 对于写SGP30,地址为(0X58 << 1) = 0XB0
    • 对于读SGP30,地址为((0X58 << 1)) | 0X01 = 0XB1

    SGP30的命令都是双字节的,先发高位,有如下命令:

    常用的有两个,一个是0x2003为初始化SGP30命令,另一个0x2008为获取空气质量值命令。

    SGP30获取的数据格式为:2位CO2数据+1位CO2的CRC校验+2位TVOC数据+1位TVOC的CRC校验。模块上电需要15s左右初始化,在初始化阶段读取的CO2浓度为400ppm,TVOC为0ppd且恒定不变。因此上电后一直读,直到TVOC不为0并且CO2不为400,SGP30模块才初始化完成。

    初始化完成后刚开始读出数据会波动比较大,属于正常现象,一段时间后会逐渐趋于稳定。气体类传感器比较容易受环境影响,测量数据出现波动是正常的,可以添加滤波函数进行滤波。

    代码如下:

    /****

    *******向SGP30的地址address中写入一个字节的数据

    *****/

    void SGP30_Write_Data(uchar address,uchar dat)

    {

       SGP30_IIC_Start();

       SGP30_IIC_SendByte(SGP30_SlaveAddress);

       SGP30_IIC_SendByte(address);

       SGP30_IIC_SendByte(dat);

       SGP30_IIC_Stop();

    }

    /****

    *******从SGP30的地址address中读取一个字节的数据

    *****/

    ulong SGP30_Read_Data()

    {

       ulong dat;

       uint crc;

       SGP30_IIC_Start();

       SGP30_IIC_SendByte(SGP30_SlaveAddress + 1);

       dat = SGP30_IIC_RecByte(SGP30_ACK);               //CO2高位数据

       dat <<= 8;

       dat += SGP30_IIC_RecByte(SGP30_ACK);              //CO2低位数据

       crc = SGP30_IIC_RecByte(SGP30_ACK);                //CRC校验值

       dat <<= 8;

       dat += SGP30_IIC_RecByte(SGP30_ACK);              //TVOC高位数据

       dat <<= 8;

       dat += SGP30_IIC_RecByte(SGP30_ACK);              //TVOC低位数据

       crc = SGP30_IIC_RecByte(SGP30_NACK);               //CRC校验值

       SGP30_IIC_Stop();

       return(dat);

    }

    /****

    *******SGP30初始化函数

    *****/

    void SGP30_Init(void)

    {

       SGP30_Write_Data(0x20,0x03);

    }

    /****

    *******SGP30获取CO2和TVOC值函数

    *****/

    void SGP30_Get_Co2_Tvoc_Value(uint *co2_value, uint *tvoc_value)

    {

       ulong sgp30_value;

       SGP30_Write_Data(0x20,0x08);

       sgp30_value = SGP30_Read_Data();

       *co2_value = (sgp30_value & 0xffff0000) >> 16;

       *tvoc_value = sgp30_value & 0x0000ffff;

    }

    六、流程设计

    首先初始化引脚,然后发送初始化指令0x2003。接着发送读取数据指令0x2008,然后开始获取数据,先获取CO2高8位数据,再获取CO2低8位数据,再获取一次CRC校验值;然后再获取TVOC高8位数据,再获取TVOC低8位数据,再获取一次CRC校验值。数据获取好后,将CO2的高8位数据和低8位数据整合为一个数据即为CO2值,将TVOC的高8位数据和低8位数据整合为一个数据即为TVOC值。

  • 相关阅读:
    2022杭电多校第七场题解
    Mysql高阶语句
    ps[001] 初学创建剪切蒙版
    Shell脚本详解
    Linux 安装 miniconda
    CSS:层叠规则
    【我不是熟悉的javascript】使用postMessage+iframe实现授权登录
    GnuTLS recv error (-110): The TLS connection was non-properly terminated
    领域驱动设计——领域的整体设计
    数字信号处理8:利用Python进行数字信号处理基础
  • 原文地址:https://blog.csdn.net/weixin_61121477/article/details/127763211