简介
Sipeed有很多有趣且高质量的传感器, 其所有的传感器都是采用的Grove 接口. 随着Grove生态的发展, 现在很多不同公司的开发板都开始支持Grove接口. 比如说瑞萨的RA6M5开发板. 更或者是Sipeed的官方开发板. 比如说WIO terminal 同样集成了两个Grove接口.

上图为瑞萨RA6M5开发板

Wio terminal 背面

Wio terminal 的Grove接口
所以对Grove生态的传感器就非常方便连接了. 比如说同样来自Sipeed的SGP30, 空气质量传感器和光照传感器.

SGP30简介
SGP30是瑞士Sensirion公司推出的一款微型智能气体传感器,采用I2C数字接口,工作电压仅需1.8V。它能精准检测室内空气中的TVOC(总挥发性有机物)和CO₂等效浓度,主要被应用在了和空气净化器、新风系统等产品中来实现真正感知环境质量。这款传感器集高灵敏度、低功耗和小尺寸于一身,无需复杂校准即可输出可靠数据.

上图为Sipeed的SGP30传感器

Gas Sensing Performance

空气信号质量规格表
对应的PINOUT也比较简单, 唯一需要注意的就是这个传感器的驱动电压只有1.8V, 不能将这个传感器直接接到3.3v上的, 如果需要使用这个传感器, 那么在设计中最好需要包含一个降压电路.

VDDH可以直接和VDD连接在一起, VSS 和 R接地. SCL和SDA连接开发板的SCL和SDA即可.

推荐的应用电路
驱动测量的步骤也比较简单, 首先初始化SGP30传感器, 然后选择是否要校准绝对湿度、 和是否校准baseline. 之后便可以发送测量命令给SGP30, 等待一秒后将会返还测量的结果.

测量命令图

I2C命令和通讯时序
我们可以着重关注 init的命令和触发测量measure_iaq的命令. 由于采用的i2C通讯, 所以在传输命令时需要分MSB和LSB进行两次发送. 如果发送的是测量命令measure_iaq 那么, 它将会返回6个字节. 由于是TVOC和Co2的数据, 所有带上CRC校验数据, 一共是6个字节. 顺序为CO₂eq(2Bytes + CRC) + TVOC(2Bbytes + CRC)
对于传感器的驱动, 官方也提供了详细的驱动库. 其驱动库是C语言编写的, 因此非常容易进行移植.

如果使用的是Wio terminal进行驱动的话(Arduino环境), 将会变的更加简单.
1- 首先在库管理器中搜索sgp30 并且下载
2- 固定的初始化代码对传感器进行初始化
void initSGP30() {
s16 err;
u16 scaled_ethanol_signal, scaled_h2_signal;
/* Init SGP30 module */
while (sgp_probe() != STATUS_OK) {
Serial.println("SGP failed");
tft.drawString("SGP30 Init Failed!", 10, TITLE_Y);
delay(1000);
}
/* Read H2 and Ethanol signal */
err = sgp_measure_signals_blocking_read(&scaled_ethanol_signal, &scaled_h2_signal);
if (err == STATUS_OK) {
Serial.println("get ram signal!");
} else {
Serial.println("error reading signals");
}
err = sgp_iaq_init();
}3- 测量和读取
// 读取空气质量数据
s16 err;
u16 tvoc_ppb, co2_eq_ppm;
err = sgp_measure_iaq_blocking_read(&tvoc_ppb, &co2_eq_ppm);
if (err != STATUS_OK) {
Serial.println("error reading IAQ values");
return;
}简单的画了一个界面使其可以将空气的数据显示在屏幕上.
#include <Arduino.h>
#include "TFT_eSPI.h"
#include "Free_Fonts.h"
#include "sensirion_common.h"
#include "sgp30.h"
TFT_eSPI tft;
// 定义颜色
#define BACKGROUND_COLOR TFT_BLACK
#define TITLE_COLOR TFT_CYAN
#define VALUE_COLOR TFT_GREEN
#define UNIT_COLOR TFT_YELLOW
#define BORDER_COLOR TFT_NAVY
// 定义UI布局
#define TITLE_Y 10
#define TVOC_Y 100
#define CO2_Y 150
#define VALUE_X 160
#define UNIT_X 220
#define DIVIDER_HEIGHT 3
void initSGP30() {
s16 err;
u16 scaled_ethanol_signal, scaled_h2_signal;
while (sgp_probe() != STATUS_OK) {
Serial.println("SGP failed");
tft.drawString("SGP30 Init Failed!", 10, TITLE_Y);
delay(1000);
}
err = sgp_measure_signals_blocking_read(&scaled_ethanol_signal, &scaled_h2_signal);
if (err == STATUS_OK) {
Serial.println("get ram signal!");
} else {
Serial.println("error reading signals");
}
err = sgp_iaq_init();
}
void drawUI() {
tft.fillScreen(BACKGROUND_COLOR);
// 绘制标题
tft.setTextColor(TITLE_COLOR, BACKGROUND_COLOR);
tft.setFreeFont(FSB12);
tft.drawString("Air Quality Monitor", 10, TITLE_Y);
// 绘制分隔线
tft.fillRect(0, 40, tft.width(), DIVIDER_HEIGHT, BORDER_COLOR);
// 绘制TVOC标签
tft.setFreeFont(FSB9);
tft.setTextColor(TITLE_COLOR, BACKGROUND_COLOR);
tft.drawString("TVOC:", 10, TVOC_Y);
// 绘制CO2标签
tft.drawString("CO2:", 10, CO2_Y);
// 绘制单位
tft.setTextColor(UNIT_COLOR, BACKGROUND_COLOR);
tft.setFreeFont(FS9);
tft.drawString("ppb", UNIT_X, TVOC_Y);
tft.drawString("ppm", UNIT_X, CO2_Y);
}
void setup() {
Serial.begin(115200);
tft.begin();
tft.setRotation(3);
drawUI();
initSGP30();
}
void loop() {
static uint32_t lastUpdate = 0;
static u16 last_tvoc = 0, last_co2 = 0;
if (millis() - lastUpdate >= 500) {
lastUpdate = millis();
s16 err;
u16 tvoc_ppb, co2_eq_ppm;
err = sgp_measure_iaq_blocking_read(&tvoc_ppb, &co2_eq_ppm);
if (err != STATUS_OK) {
Serial.println("error reading IAQ values");
return;
}
if (tvoc_ppb != last_tvoc) {
tft.setTextColor(VALUE_COLOR, BACKGROUND_COLOR);
tft.setFreeFont(FSB9);
tft.drawNumber(tvoc_ppb, VALUE_X, TVOC_Y);
last_tvoc = tvoc_ppb;
}
if (co2_eq_ppm != last_co2) {
tft.setTextColor(VALUE_COLOR, BACKGROUND_COLOR);
tft.setFreeFont(FSB9);
tft.drawNumber(co2_eq_ppm, VALUE_X, CO2_Y);
last_co2 = co2_eq_ppm;
}
Serial.print("TVOC: ");
Serial.print(tvoc_ppb);
Serial.print("ppb | CO2eq: ");
Serial.print(co2_eq_ppm);
Serial.println("ppm");
}
delay(100);
}实验效果

附件
我要赚赏金
