简介
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); }
实验效果
附件