Arduino UNO R4 Minimaでセンサ・インターフェーシング ㉖ 空気質センサSGP40
Adafruitから入手した空気質センサ SGP40(Sensirion)を利用します。
揮発性有機化合物(VOC)ベースの屋内空気質データの出力(VOXインデックス)が測定できます。
前回のCO2センサのSCD41、第18回で掲載したボッシュBME688の気圧センサとの比較を次に示します。
型名 | 電源電圧 [V] |
気圧測定範囲 [hPa] |
温度[℃] | 湿度[%] | 空気測定の機能 |
SGP40 | 1.7~3.6 | - | - | - | 屋内に存在する一般的なVOCガスをもとにディジタル値を出力 |
---|---|---|---|---|---|
SCD41 | 2.4~5.5 | - | -10~+60 確度;± 0.8℃ |
0~100 |
CO2 |
BME688 | 1.7~3.6 | 300~1100 | -40~+85℃ 確度;±0.5℃ |
0~100% 確度;±3% |
MOX (金属酸化物)センサで、各種空気のにおいを検知 |
SGP40には、I2Cインターフェース、温度制御マイクロホットプレート、湿度補正室内空気質信号を備えた単一のチップにセンサ・システムすべてが搭載されています。センサ信号をそのまま使用すれば、空気処理機器のファンを段階的に制御する場合などに室内空気質を評価できます。
●AdafruitのStemma QT/Qwiicボード
Stemma QT/Qwiic(JST SH 4ピン)コネクタは2か所に装着されていて、どちらにつないでもかまいません。このコネクタを使ってI2Cで制御する場合、特に、ジャンパ線をつなぐなどは不要です。
コネクタは、表と裏のどちらも差し込めそうですが、ピンが内部の上部に並んでいるので、差し込める方向は一意です。ロック機構はないですが、すぐに抜けるということはありません。
●空気質センサSGP40のおもなスペック
- 電源電圧 1.7~3.6V
- 動作時消費電流 2.6mA
- 動作条件 温度;-10~+50℃、湿度;0~90%RH
- VOXインデックス 1~500、実測値(SRAW);0~65535 tick(感知層の抵抗の対数に比例した数値)
- インターフェース I2C(100~400kHz)
- スレーブ・アドレス 0x59
●使用環境
- Arduino UNO R4 Minima
- Arduino IDE 2.2.1
- Windows10 22H2
●接続
Arduino UNO R4 MinimaのI2C信号とセンサ・ボードをJSTコネクタでつなぎます(Stemma QT/Qwiicボードの写真の比率は異なる)。
●スレーブ・アドレスを確認
従来からよく使われているi2cScanner.inoを動かしてスレーブ・アドレスを確認します。電源は5Vです。
0x59を見つけてきました。
以降のスケッチは3.3Vで動作させます。
●ライブラリの用意
SGP40で検索して、見つかったAdafruit SGP40 Sensorライブラリをインストールします。
インストールを始めたとき、関連のライブラリや依存関係をインストールするかというパネルが出た場合は、全てをインストールを選びます。
●サンプル・スケッチ①
メニューのファイル->スケッチ例、Adafruit SGP40 Sensorからsgp40test.inoを選択し、コンパイル、実行します。
●サンプル・スケッチ②
メニューのファイル->スケッチ例、Adafruit SGP40 Sensorから、もう一つのサンプルsgp40_voc.inoを選択します。温度と湿度の測定をSHT31を利用しています。ここでは、連載の第7回で利用したSHT45をつなぎ、スケッチを変更します。
#include "Adafruit_SGP40.h"
#include "Adafruit_SHT4x.h"
Adafruit_SGP40 sgp;
Adafruit_SHT4x sht4 = Adafruit_SHT4x();
void setup() {
Serial.begin(115200);
while (!Serial) { delay(10); } // Wait for serial console to open!
Serial.println("SGP40 test with SHT45 compensation");
if (! sgp.begin()){
Serial.println("SGP40 sensor not found :(");
while (1);
}
if (! sht4.begin(&Wire)) {
Serial.println("Couldn't find SHT45");
while (1);
}
Serial.print("Found SHT45 + SGP40 serial #");
Serial.print(sgp.serialnumber[0], HEX);
Serial.print(sgp.serialnumber[1], HEX);
Serial.println(sgp.serialnumber[2], HEX);
}
int counter = 0;
void loop() {
uint16_t sraw;
int32_t voc_index;
sensors_event_t humidity, temp;
sht4.getEvent(&humidity, &temp);// populate temp and humidity objects with fresh data
float t = temp.temperature;
Serial.print("\nTemp *C = "); Serial.print(t); Serial.print("\t\t");
float h = humidity.relative_humidity;
Serial.print("Hum. % = "); Serial.println(h);
sraw = sgp.measureRaw(t, h);
Serial.print("Raw measurement: ");
Serial.println(sraw);
voc_index = sgp.measureVocIndex(t, h);
Serial.print("Voc Index: ");
Serial.println(voc_index);
delay(2000);
}
コンパイル、実行します。
●グラフィック・ディスプレイに測定結果を表示
次の記事を参考に、グラフィック・ディスプレイに測定した温度、湿度、VOX Indexの値を表示します。
Arduino UNO R4 Minimaでセンサ・インターフェーシング ⑤ 温湿度センサSi7021の測定結果をグラフィック・ディスプレイに表示
接続です。
スケッチです。
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "Adafruit_SGP40.h"
#include "Adafruit_SHT4x.h"
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3D ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
Adafruit_SGP40 sgp;
Adafruit_SHT4x sht4 = Adafruit_SHT4x();
void setup() {
Serial.begin(115200);
while (!Serial) { delay(10); } // Wait for serial console to open!
Serial.println("SGP40 test with SHT45 compensation");
Wire.begin();
if (! sgp.begin()){
Serial.println("SGP40 sensor not found :(");
while (1);
}
if (! sht4.begin(&Wire)) {
Serial.println("Couldn't find SHT45");
while (1);
}
Serial.print("Found SHT45 + SGP40 serial #");
Serial.print(sgp.serialnumber[0], HEX);
Serial.print(sgp.serialnumber[1], HEX);
Serial.println(sgp.serialnumber[2], HEX);
display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS);
display.clearDisplay();
display.drawRect(0, 0, display.width(), display.height(), SSD1306_WHITE);
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(3,3);
display.println("Temperature:");
display.setCursor(79,3);
display.println("Humidity");
display.setCursor(4,34);
display.println("VOX Index:");
display.display();
display.setCursor(73,34);
display.println("Raw :");
delay(200);
}
int counter = 0;
void loop() {
uint16_t sraw;
int32_t voc_index;
sensors_event_t humidity, temp;
sht4.getEvent(&humidity, &temp);// populate temp and humidity objects with fresh data
float t = temp.temperature;
Serial.print("\nTemp *C = "); Serial.print(t); Serial.print("\t\t");
float h = humidity.relative_humidity;
Serial.print("Hum. % = "); Serial.println(h);
sraw = sgp.measureRaw(t, h);
Serial.print("Raw measurement: ");
Serial.println(sraw);
voc_index = sgp.measureVocIndex(t, h);
Serial.print("Voc Index: ");
Serial.println(voc_index);
display.setTextSize(2); // Draw 2X-scale text
display.setCursor(10,17);
display.fillRect(10, 17, 70, 16, SSD1306_BLACK);
display.println(t);
display.setCursor(80,17);
display.fillRect(80, 17, 46, 16, SSD1306_BLACK);
display.println(h,1);
display.setCursor(10, 46);
display.fillRect(10, 46, 50, 16, SSD1306_BLACK);
display.println(voc_index);
display.setCursor(68, 46);
display.fillRect(68, 46, 58, 16, SSD1306_BLACK);
display.println(sraw);
display.display();
delay(2000);
}
実行例です。
机の上において実験をしています。電源が入った直後、VOX Indexの値は0からゆっくりと上昇します。人がいる状態では、100前後まで上がって安定します。席を外して戻ると50ぐらいまで下がっています。息を吹きかけるとゆっくりと200ぐらいに上昇します。