マニアック記事です。
Co2センサー、数年前から急にネットで様々な種類が出回りましたね。
アウトドアなんかでも活躍してくれそうなのはSwitchBotのCo2センサーです。
ただ、今回は自作してみたくてチャレンジしてみることにしました。
自作Co2センサー
完成品がこちら。
100均の木のケースに収納した自作Co2センサーです。
小さいモニターにAQI(空気質指数)、TVOC(総揮発性有機化合物)、eCO2(二酸化炭素濃度)、温度、湿度を表示するようにしてみました。
また、以下のレベルに到達するとメロディー(アラーム)でお知らせしてくれる機能を追加しました。
種類 | 閾値 | アラーム音 |
---|---|---|
AQI | 4 以上 | こいぬのマーチ |
TVOC | 660 ppb 以上 | 茶色の小瓶 |
eCO2 | 1,000 ppm 以上 | きらきら星 |
AQI、TVOCの閾値チェックは外す or 閾値をあげてしまっても良いと思います。
(すぐピーピーなって煩いです)
1度閾値を超えると1分待機するようにしています。
私用したもの
あとは100均の木箱、ELEGOOのキットに入っていたケーブルです。
二酸化炭素チェック器を作成するのにかかった費用はこちら。
パーツ | 費用 |
---|---|
マイコン | \ 998 |
モニター | \ 500 |
センサー | \ 982 |
ブザー | \ 35 |
ブレッドボード | \ 125 |
木箱 | \ 110 |
合計 | \ 2,739 |
センサー代が高い。。
お勉強用とはいえ結構かかってしまいました。
作成したコード
以下、作成したコードです。
#include <Wire.h>
#include <Adafruit_GFX.h> //SSD1306 画像描画用
#include <Adafruit_SSD1306.h> //SSD1306 モニタ用
#include <SparkFun_ENS160.h> //ENS160 ガスセンサ用
#include <AHTxx.h> //AHT21 温湿度用
#define TEMPERATURE_CORRECTION -4 // ENS160 温度補正 -4 ℃
SparkFun_ENS160 myENS; //ENS160
const int SCREEN_WIDTH = 128; //ディスプレイのサイズ指定
const int SCREEN_HEIGHT = 64; //ディスプレイのサイズ指定
const int SCREEN_ADDRESS = 0x3C; //I2Cのアドレス指定
// ENS160
int ensStatus;
int alertlevelAqi = 5;
int alertlevelTvoc = 660;
int alertlevelCo2 = 1001;
int pinBuzzer = 8;
int do2 = 262;
int re2 = 294;
int mi2 = 330;
int fa2 = 349;
int so2 = 392;
int ra2 = 440;
int si2 = 494;
int do3 = 523;
int re3 = 587;
int mi3 = 659;
int cooltime = 0;
bool flag = false;
// AHT21
AHTxx AHT21(AHTXX_ADDRESS_X38, AHT2x_SENSOR);
// ディスプレイ制御用のインスタンスを作成。この時にサイズを渡す
Adafruit_SSD1306 display( SCREEN_WIDTH, SCREEN_HEIGHT, &Wire);
float calcMaxVaperPressure(float temp)
{
// 飽和水蒸気圧
return 6.1078 * pow(10, 7.5 * temp / (temp + 237.3));
}
float recalculateHumidity(float temp, float rh)
{
// 温度を補正して湿度を再計算
float temp2 = temp + TEMPERATURE_CORRECTION;
return rh * calcMaxVaperPressure(temp) * (temp2 + 273.15) / ((temp + 273.15) * calcMaxVaperPressure(temp2));
}
void setup() {
// BUILTIN LEDの消灯
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
Wire.begin();
Serial.begin(115200);
// 起動音
buzzer(do2, 200);
buzzer(re2, 200);
buzzer(mi2, 200);
// SSD1306
//ディスプレイを初期化。この時にI2Cアドレスを渡す
display.begin( SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS );
display.clearDisplay(); //画面描写エリアを削除。
display.display(); //画面描写エリアをディスプレイに転送。ここで全画面を削除。
delay(1000); //1秒待機
// ENS160
if( !myENS.begin() )
{
display.setCursor( 0, 22 );
display.setTextColor( SSD1306_WHITE, SSD1306_BLACK );
display.setTextSize( 1 );
display.println("Did not begin.");
display.display();
while(1);
}
// Reset the indoor air quality sensor's settings.
if( myENS.setOperatingMode(SFE_ENS160_RESET) )
{
display.setCursor( 0, 22 );
display.setTextColor( SSD1306_WHITE, SSD1306_BLACK );
display.setTextSize( 1 );
display.println("Ready.");
display.display();
}
delay(1000);
myENS.setOperatingMode(SFE_ENS160_STANDARD);
// There are four values here:
// 0 - Operating ok: Standard Operation
// 1 - Warm-up: occurs for 3 minutes after power-on.
// 2 - Initial Start-up: Occurs for the first hour of operation.
// and only once in sensor's lifetime.
// 3 - No Valid Output
ensStatus = myENS.getFlags();
display.setCursor( 0, 22 );
display.setTextColor( SSD1306_WHITE, SSD1306_BLACK );
display.setTextSize( 1 );
display.println(" Gas Sensor ");
display.print(" Status Flag: ");
display.println(ensStatus);
display.display();
}
void loop() {
//ENS
if( myENS.checkDataStatus() )
{
// AHT21センサーから温度と湿度を取得
float rawTemperature = AHT21.readTemperature();
float rawHumidity = AHT21.readHumidity();
// 温湿度補正
float temperature = rawTemperature + TEMPERATURE_CORRECTION;
float humidity = recalculateHumidity(rawTemperature, rawHumidity);
// SSD
display.clearDisplay();
display.setTextSize( 1 ); //フォントサイズ指定。
display.setTextColor( SSD1306_BLACK, SSD1306_WHITE ); //display.setTextColor( 文字本体の色, 背景の色)
display.setCursor( 15, 10 ); //描写開始座標(X.Y)
if (flag == false) {
display.print( " Air Check " );
} else {
display.print( " Cool Time : " );
display.print( cooltime );
}
display.setCursor( 0, 22 );
display.setTextColor( SSD1306_WHITE, SSD1306_BLACK );
display.setTextSize( 1 );
display.print( " AQI : " );
display.println(myENS.getAQI());
display.print( " TVOC : " );
display.print(myENS.getTVOC());
display.println(" ppb ");
display.print( " eCO2 : " );
display.print(myENS.getECO2());
display.println(" ppm ");
display.print( " Temp : " );
//display.print(rawTemperature);
display.print(temperature);
display.println(" C ");
display.print( " Humi : " );
//display.print(humidity);
display.print(rawHumidity);
display.println(" % ");
// 5min wait
if (flag == true && cooltime < 300) {
cooltime = cooltime + 1;
delay(1000); // 1 sec
} else {
flag = false;
cooltime = 0;
//checkAqi(myENS.getAQI()); // AQI チェック
//checkTvoc(myENS.getTVOC()); // TVOC チェック
checkCo2(myENS.getECO2()); // Co2 チェック
}
display.display();
}
}
void buzzer (int oto, int time) {
tone(pinBuzzer, oto, time);
delay(time);
}
int checkAqi (int x) {
if (x >= alertlevelAqi) {
buzzer(mi2, 500);
buzzer(do2, 500);
buzzer(mi2, 500);
buzzer(do2, 500);
buzzer(mi2, 500);
buzzer(so2, 500);
buzzer(so2, 1000);
buzzer(fa2, 500);
buzzer(re2, 500);
buzzer(re2, 1000);
buzzer(mi2, 500);
buzzer(do2, 500);
buzzer(do2, 1000);
flag = true;
}
}
int checkTvoc (int x) {
if (x >= alertlevelTvoc) {
buzzer(mi2, 500);
buzzer(so2, 500);
buzzer(so2, 500);
buzzer(so2, 500);
buzzer(fa2, 500);
buzzer(ra2, 500);
buzzer(ra2, 500);
buzzer(ra2, 500);
buzzer(si2, 500);
buzzer(si2, 500);
buzzer(ra2, 500);
buzzer(si2, 500);
buzzer(do3, 500);
buzzer(re3, 500);
buzzer(mi3, 500);
flag = true;
}
}
int checkCo2 (int x) {
if (x >= alertlevelCo2) {
buzzer(do2, 500);
buzzer(do2, 500);
buzzer(so2, 500);
buzzer(so2, 500);
buzzer(ra2, 500);
buzzer(ra2, 500);
buzzer(so2, 1000);
buzzer(fa2, 500);
buzzer(fa2, 500);
buzzer(mi2, 500);
buzzer(mi2, 500);
buzzer(re2, 500);
buzzer(re2, 500);
buzzer(do2, 1000);
flag = true;
}
}
以上、自作してみたCo2(二酸化炭素)測定器のお話でした。
コメントを残す