文章目录
1.背景说明
SGP30可以检测空气中总有机气体含量(TVOC)和CO2含量。本文带你编写SGP30驱动程序,并使用ESP32进行测试验证。由于作者水平有限,软件设计架构难免有问题,欢迎批评指正。通用驱动代码托管到github上了(https://github.com/shengliwang/sgp30_driver),SGP30中英文手册也在此仓库中。
另外在树莓派上通过GPIO模拟I2C的驱动托管在https://github.com/shengliwang/VOC-dectect。本博客后续再对其说明,并移植到本仓库中。
2.代码实现
2.1定义跟开发平台相关的handle
由于驱动程序设计成可在各嵌入式芯片上移植,所以定义一个跟平台相关的数据结构。用户需要实现并指定I2C读写接口。
typedef int (*i2C_write_ptr)(uint8_t addr, const uint8_t *data, size_t data_len);
typedef int (*i2C_read_ptr)(uint8_t addr, uint8_t * data, size_t buf_len);
typedef void (*sleep_msec_ptr)(uint32_t mseconds);
typedef struct i2c_sgp30_t{
i2C_write_ptr i2c_write;
i2C_read_ptr i2c_read;
sleep_msec_ptr msleep;
uint8_t i2c_addr;
} *i2c_sgp30_handle_t;
在ESP32上具体实现时再说明。
2.2 初始化传感器
先定义两个宏用于提取uint16_t
类型的数据的MSB和LSB。
#define MSB_OF_UINT16_T(d) ( (uint8_t)(d >> 8) )
#define LSB_OF_UINT16_T(d) ( (uint8_t)(d & 0x00ff) )
根据SGP30传感器手册,基本上所有的I2C命令都要先发送命令,然后读取数据。把这段代码抽象出来实现如下:
static int s_i2c_sgp30_send_cmd(i2c_sgp30_handle_t handle, uint16_t cmd, uint32_t duration_ms){
uint8_t arr_cmd[2];
arr_cmd[0] = MSB_OF_UINT16_T(cmd);
arr_cmd[1] = LSB_OF_UINT16_T(cmd);
if (0 != handle->i2c_write(handle->i2c_addr, arr_cmd, sizeof(arr_cmd))){
return SGP30_ERR;
}
handle->msleep(duration_ms);
return SGP30_OK;
}
int i2c_sgp30_init(i2c_sgp30_handle_t handle){
uint16_t cmd = CMD_Init_air_quality;
uint32_t duration = CMD_Init_air_quality_MAX_DURATION_TIME_MS;
if ( SGP30_OK != s_i2c_sgp30_send_cmd(handle, cmd, duration)){
return SGP30_ERR;
}
return SGP30_OK;
}
其中cmd
参数支持的命令如下(具体可查看SGP30传感器手册)
// 命令字
#define CMD_Init_air_quality 0x2003
#define CMD_Measure_air_quality 0x2008
#define CMD_Get_baseline 0x2015
#define CMD_Set_baseline 0x201e
#define CMD_Set_humidity 0x2061
#