STM32驱动SGP30气体传感器CO2/TVOC检测

简介

SGP30是一款单一芯片,上具有多个传感元件的金属氧化物气体传感器,内集成4个气体传感元件,具有完全校准的空气质量输出信号。另外,SGP易于集成,能够将金属氧化物气体传感器集成到移动设备中,为智能家居、家电和物联网应用中的环境监测开辟了新的可能性。SGP30模块通常包括一个集成的传感器芯片和相应的电路,使其能够方便地与微控制器连接。它通常通过I2C总线与微控制器通信,可以轻松地集成到各种不同的嵌入式系统中。
在这里插入图片描述

电气特征

1.供电电压3.3V或5V ;
2.IIC通信接口,输出TVOC和CO2eq信号
3.采用进口高灵敏SGP30甲醛传感器,芯片供电电压为1.8V;
4.功耗40mA;
5.板载1.8V LDO芯片为SGP30供电,所以输入电源可为3.3V或5V。

原理图

在这里插入图片描述

信号输出

SGP30是一款单一芯片,上具有多个传感元件的金属氧化物气体传感器,内集成4个气体传感元件,具有完全校准的空气质量输出信号,主要输出参数如下:

在这里插入图片描述

其中挥发有机物-TVOC测量范围:0-60000ppb;
CO2浓度测量范围:400-60000ppm。

设备通信

通讯时序

在这里插入图片描述
从传感器可以看到SDA方向。粗体SDA线由传感器控制;普通SDA线由微控制器控制。
注意,SDA有效读取时间是由前一个开关的下降沿触发的。

设备IIC地址

在这里插入图片描述
SGP30 I2C从机地址为0X58,则SGP30写地址为(0X58<<1)|0X00=0XB0,读地址为(0X58<<1)|0X01=0XB1。

测量通信

测量通信序列由START条件、I2C写头(7位I2C设备地址加上0作为写位)和16位测量命令组成。每个字节的正确接收由传感器指示。它把SDA引脚低(ACK位)后下降沿的第8 SCL时钟表示接收。接收到测量命令后,SGP30开始测量。
在传感器完成测量后,主机可以通过发送START条件和l2C读头来读取测量结果。传感器将确认接收到读报头,并以数据进行响应。响应数据长度如(测量命令)图所示,以数据字为单位,其中一个字由两个字节的数据和一个字节的CRC校验和组成。每个字节必须由微控制器以ACK条件确认,以便传感器继续发送数据。如果传感器在任何字节的数据之后没有收到来自主机的ACK,它将不会继续发送数据。
在接收到数据最后一个字的校验和后,必须发送XCK和STOP条件(如下图)。如果I2C主机对后续数据(例如CRC字节或后续数据字节)不感兴趣,则可以在任何数据字节之后使用XCK和STOP条件终止读取传输,以节省时间。

在这里插入图片描述

测量命令

在这里插入图片描述
上面测量命令中,主要用的两个:一个是0X2003为初始化命令,另一个是0X2008为获取采集数据。SGP获取数据的过程为:模块上电后发送0X2003进行初始化,初始化期间,CO2和TVOC固定为400和0,需要的时间在15秒左右,接着发送0X2008进行数据采集,采集时间也是差不多15秒左右,最后采集到的数据格式为:2位CO2数据+1位CO2CRC校验+2位TVOC数据+1位CRC校验。

校验和计算

在这里插入图片描述

硬件连接

STM32SGP30OLED
VCCVCCVCC
GNDGNDGND
PB9SCL-
PB8SDA-
PB6-SCL
PB5-SDA

代码

main.c

#include "stm32f10x.h"
#include "OLED_I2C.h"
#include "delay.h"
#include "SGP30.h"
#include "SGP30_IIC.h"
#include "bsp_usart.h"
#include <stdio.h>
uint16_t TVOC = 0, CO2 = 0;
uint8_t TVOC_Buf[20] = {0}, CO2_Buf[20] = {0};
uint8_t ID[6]={0};
uint8_t i = 0;
int main(void)
{
 
	USART_Config();
	DelayInit();
	I2C_Configuration();
	OLED_Init();
	OLED_Fill(0x00);//全屏灭
	SGP30_GPIO_Init();
 	SGP30_init();

    SGP30_get_serial_id(ID); 
	for( i = 0; i < 6; i++) 
	{	
		printf("%02X", ID[i]);
	}
	printf("\r\n");	
	while(1)
	{
	      
				SGP30_read(&CO2, &TVOC);
				sprintf(CO2_Buf,"CO2:%d dppm ",CO2);
				sprintf(TVOC_Buf,"TVOC:%d dppb ",TVOC);
		        printf("SGP30---");
				Usart_SendString(DEBUG_USARTx,CO2_Buf);
				Usart_SendString(DEBUG_USARTx,TVOC_Buf);
		        OLED_ShowString(2,0,CO2_Buf,2);
				OLED_ShowString(4,2,TVOC_Buf,2);
        DelayMs(500);	


	}
}

SGP 30.c

#include "SGP30.h"
#include "delay.h"

uint8_t SGP30_checksum(const uint8_t* buf, uint32_t len)
{
	const uint8_t Polynomial = 0x31;
	uint8_t Initialization = 0XFF;
    uint8_t i = 0, k = 0;
	while(i < len)
	{
		Initialization ^= buf[i++];
		for(k = 0; k < 8; k++)
		{
			if(Initialization & 0X80)
				Initialization = (Initialization << 1) ^ Polynomial;
			else
				Initialization = (Initialization << 1);
		}
	}
	return Initialization;
}

int SGP30_get_serial_id(uint8_t id[6])
{
		uint8_t CMD[2];
    uint8_t buf[10];
    uint8_t crc[3];

    CMD[0] = (SGP30_CMD_GET_SERIAL_ID & 0XFF00) >> 8;
    CMD[1] = (SGP30_CMD_GET_SERIAL_ID & 0X00FF);

//    IIC_WriteBuf(SGP30_ADDR, CMD, 2);
//        DELAY_US(500);
		IIC_ReadDataBuf(SGP30_ADDRESS, CMD,buf, 9); 
    //IIC_ReadDataBlock(SGP30_ADDR, buf, 9);
    // return -2;

    crc[0] = buf[2];
    crc[1] = buf[5];
    crc[2] = buf[8];

    id[0]  = buf[0];
    id[1]  = buf[1];
    id[2]  = buf[3];
    id[3]  = buf[4];
    id[4]  = buf[6];
    id[5]  = buf[7];
    if(
        SGP30_checksum(&id[0], 2) != crc[0] ||
        SGP30_checksum(&id[2], 2) != crc[1] ||
        SGP30_checksum(&id[4], 2) != crc[2]
    )
    return -3;

    return 0;
}


void SGP30_soft_reset(void)  
{
	IIC_WriteReg(SGP30_ADDRESS, 0x00, 0x06);
//			uint8_t CMD[2];
//    // uint8_t buf[10];
//	   CMD[0] = (SGP30_CMD_REAST & 0XFF00) >> 8;
//     CMD[1] = (SGP30_CMD_REAST & 0X00FF);
//    IIC_WriteBuf(SGP30_ADDR, CMD, 2);
    
}

int SGP30_init(void)
{
    	uint8_t CMD[2];

    // 软件复位
//    sgp30_soft_reset();
//       
//    // 等待复位完成
//    DELAY_MS(50);

    CMD[0] = (SGP30_CMD_INIT_AIR_QUALITY & 0XFF00) >> 8;
    CMD[1] = (SGP30_CMD_INIT_AIR_QUALITY & 0X00FF);

	// 初始化控制测量参数
    IIC_WriteBuf(SGP30_ADDRESS, CMD, 2);
	// IIC_WriteReg(SGP30_ADDR, 0x00, 0x06);
    return 0;
}

int SGP30_read(uint16_t* CO2, uint16_t* TVOC)
{
		uint8_t CMD[2];
    uint8_t buf[8] = {0};

    CMD[0] = (SGP30_CMD_MEASURE_AIR_QUALITY & 0XFF00) >> 8;
    CMD[1] = (SGP30_CMD_MEASURE_AIR_QUALITY & 0X00FF);

   IIC_WriteBuf(SGP30_ADDRESS, CMD, 2);

    // 等待测量完成
    DelayMs(10);

    // 读取收到的数据
		IIC_ReadDataBuf(SGP30_ADDRESS, CMD,buf, 6); 
  
    // 校验CRC
//    if (sgp30_checksum(&buf[3], 2) != buf[5])
//        return -3;

   *CO2  = ((uint16_t)buf[0] << 8) | buf[1];
   *TVOC = ((uint16_t)buf[3] << 8) | buf[4];

    return 0;
}

结果

串口打印数据:
在这里插入图片描述

OLED显示数据:

在这里插入图片描述

总结

以上是基于STM32驱动SGP30传感器进行空气质量检测的一个原理应用和代码展示,使用时需要注意的是,上电初始化过程中,CO2和TVOC固定为400和0,直到CO2和TVOC不为400和0时才算初始化完成。此外,刚开始读取数据时,可能会有较大的波动,这是正常的,因为气体传感器较容易受环境影响,过一会就会趋于稳定。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值