Arduino UNO R4 Minimaでセンサ・インターフェーシング ㉕ CO2センサSCD41

 Adafruitから入手したCO2センサ SCD41(Sensirion)を利用します。

 温度湿度、そしてCO2が測定できます。

 第18回で掲載したボッシュBME688の気圧センサとの比較を次に示します。

型名 電源電圧
[V]
気圧測定範囲
[hPa]
温度[℃] 湿度[%] 空気測定の機能
SCD41 2.4~5.5 - -10~+60
確度;± 0.8℃

0~100
確度;± 6% 

CO2
BME688 1.7~3.6  3001100 -40~+85℃
確度;±0.5℃
0~100%
確度;±3%
MOX (金属酸化物)センサで、各種空気のにおいを検知

<二つのモデル>

(SCD40 は低コスト、400~2000ppm、確度は±50 ppm + 読み取り値の5%)
(SCD41 はより高価、400~5000ppm、確度は±40 ppm + 読み取り値の5%)

AdafruitのStemma QT/Qwiicボード

 SCD41ボード解説のページ

 Stemma QT/Qwiic(JST SH 4ピン)コネクタは2か所に装着されていて、どちらにつないでもかまいません。このコネクタを使ってI2Cで制御する場合、特に、ジャンパ線をつなぐなどは不要です。

 コネクタは、表と裏のどちらも差し込めそうですが、ピンが内部の上部に並んでいるので、差し込める方向は一意です。ロック機構はないですが、すぐに抜けるということはありません。

CO2センサSCD41のおもなスペック

 SCD41のデータシート

  • 電源電圧 2.4~5.5V
  • 消費電流 17mA
  • 温度測定範囲 -10~+60℃、確度;±0.8℃
  • CO2測定範囲 400~5000ppm、確度;±(40ppm + 読み取り値の5%)
  • 湿度測定範囲 0~100%、確度;±6%
  • インターフェース I2C(最大400kHz)
  • スレーブ・アドレス 0x62

使用環境

  • Arduino UNO R4 Minima
  • Arduino IDE 2.2.1
  • Windows10 22H2

接続

 Arduino UNO R4 MinimaのI2C信号とセンサ・ボードをJSTコネクタでつなぎます(Stemma QT/Qwiicボードの写真の比率は異なる)。

スレーブ・アドレスを確認

 従来からよく使われているi2cScanner.inoを動かしてスレーブ・アドレスを確認します。電源は3.3Vです。

  0x62を見つけてきました。

(正常に動作しないときは、ボード上のリセットを押します。一度で動かない場合は、何度か押し直す)

 


ライブラリの用意

 SCD4で検索して、見つかったSensirion I2C SCD4Xライブラリをインストールします。

 インストールを始めたとき、関連のライブラリや依存関係をインストールするかというパネルが出た場合は、全てをインストールを選びます。

サンプル・スケッチ

 メニューのファイル->スケッチ例から、Sensirion I2C SCD4XからexampleUsage.inoを選択し、コンパイル、実行します。

 

4桁の7セグメントLED表示器をつないで測定結果を表示する

 連載の第4回目の記事を参照しながら表示器を接続します。

Arduino UNO R4 Minimaでセンサ・インターフェーシング ④ 温湿度センサSi7021の測定結果を7セグメントLEDに表示


 スケッチです。

 7セグメントLED表示器は、第12回 温湿度センサ SHTC3でスレーブ・アドレスが重なったので、デフォルトの0x70から、ジャンパのA0をショートして0x71に変更してあります。デフォルトのまま使うときは0x70で使ってください。


// Copyright (c) 2021, Sensirion AG

#include <Wire.h>
#include <Adafruit_GFX.h>
#include "Adafruit_LEDBackpack.h"
#include <Arduino.h>
#include <SensirionI2CScd4x.h> Adafruit_7segment matrix = Adafruit_7segment(); SensirionI2CScd4x scd4x; void printUint16Hex(uint16_t value) { Serial.print(value < 4096 ? "0" : ""); Serial.print(value < 256 ? "0" : ""); Serial.print(value < 16 ? "0" : ""); Serial.print(value, HEX); } void printSerialNumber(uint16_t serial0, uint16_t serial1, uint16_t serial2) { Serial.print("Serial: 0x"); printUint16Hex(serial0); printUint16Hex(serial1); printUint16Hex(serial2); Serial.println(); } void setup() { Serial.begin(115200); while (!Serial) { delay(100); } Serial.println("SCD41 + 7segment LED"); Wire.begin(); uint16_t error; char errorMessage[256]; scd4x.begin(Wire); // stop potentially previously started measurement error = scd4x.stopPeriodicMeasurement(); if (error) { Serial.print("Error trying to execute stopPeriodicMeasurement(): "); errorToString(error, errorMessage, 256); Serial.println(errorMessage); } uint16_t serial0; uint16_t serial1; uint16_t serial2; error = scd4x.getSerialNumber(serial0, serial1, serial2); if (error) { Serial.print("Error trying to execute getSerialNumber(): "); errorToString(error, errorMessage, 256); Serial.println(errorMessage); } else { printSerialNumber(serial0, serial1, serial2); } // Start Measurement error = scd4x.startPeriodicMeasurement(); if (error) { Serial.print("Error trying to execute startPeriodicMeasurement(): "); errorToString(error, errorMessage, 256); Serial.println(errorMessage); } Serial.println("Waiting for first measurement... (5 sec)"); matrix.begin(0x71); matrix.setBrightness(0x05); // default 0x0E } void loop() { uint16_t error; char errorMessage[256]; delay(100); // Read Measurement uint16_t co2 = 0; float temperature = 0.0f; float humidity = 0.0f; bool isDataReady = false; error = scd4x.getDataReadyFlag(isDataReady); if (error) { Serial.print("Error trying to execute getDataReadyFlag(): "); errorToString(error, errorMessage, 256); Serial.println(errorMessage); return; } if (!isDataReady) { return; } error = scd4x.readMeasurement(co2, temperature, humidity); if (error) { Serial.print("Error trying to execute readMeasurement(): "); errorToString(error, errorMessage, 256); Serial.println(errorMessage); } else if (co2 == 0) { Serial.println("Invalid sample detected, skipping."); } else { Serial.print("Co2:"); Serial.print(co2); Serial.print("\t"); Serial.print("Temperature:"); Serial.print(temperature); Serial.print("\t"); Serial.print("Humidity:"); Serial.println(humidity); matrix.print(co2, DEC); matrix.writeDisplay(); delay(2000); matrix.print(temperature, DEC); matrix.writeDisplay(); delay(2000); matrix.print(humidity, DEC); matrix.writeDisplay(); delay(3000); } }


 実行例です。CO2の測定値を表示しています。机の上では400~500ppm、息を吹きかけるとゆっくり上昇に、千ppmを越えます。

グラフィック・ディスプレイに測定結果を表示

 次の記事を参考に、グラフィック・ディスプレイに測定した温度、湿度、CO2の値を表示します。

  Arduino UNO R4 Minimaでセンサ・インターフェーシング ⑤ 温湿度センサSi7021の測定結果をグラフィック・ディスプレイに表示

 スケッチです。


// Copyright (c) 2021, Sensirion AG

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Arduino.h>
#include <SensirionI2CScd4x.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); SensirionI2CScd4x scd4x; void printUint16Hex(uint16_t value) { Serial.print(value < 4096 ? "0" : ""); Serial.print(value < 256 ? "0" : ""); Serial.print(value < 16 ? "0" : ""); Serial.print(value, HEX); } void printSerialNumber(uint16_t serial0, uint16_t serial1, uint16_t serial2) { Serial.print("Serial: 0x"); printUint16Hex(serial0); printUint16Hex(serial1); printUint16Hex(serial2); Serial.println(); } void setup() { Serial.begin(115200); while (!Serial) { delay(100); } Serial.println("SCD41 + SSD1306"); Wire.begin(); uint16_t error; char errorMessage[256]; scd4x.begin(Wire); // stop potentially previously started measurement error = scd4x.stopPeriodicMeasurement(); if (error) { Serial.print("Error trying to execute stopPeriodicMeasurement(): "); errorToString(error, errorMessage, 256); Serial.println(errorMessage); } uint16_t serial0; uint16_t serial1; uint16_t serial2; error = scd4x.getSerialNumber(serial0, serial1, serial2); if (error) { Serial.print("Error trying to execute getSerialNumber(): "); errorToString(error, errorMessage, 256); Serial.println(errorMessage); } else { printSerialNumber(serial0, serial1, serial2); } // Start Measurement error = scd4x.startPeriodicMeasurement(); if (error) { Serial.print("Error trying to execute startPeriodicMeasurement(): "); errorToString(error, errorMessage, 256); Serial.println(errorMessage); } Serial.println("Waiting for first measurement... (5 sec)"); 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.setTextColor(SSD1306_WHITE); display.setCursor(79,3); display.println("Humidity"); display.setTextColor(SSD1306_WHITE); display.setCursor(4,34); display.println("CO2:"); display.display(); delay(200); } void loop() { uint16_t error; char errorMessage[256]; delay(100); // Read Measurement uint16_t co2 = 0; float temperature = 0.0f; float humidity = 0.0f; bool isDataReady = false; error = scd4x.getDataReadyFlag(isDataReady); if (error) { Serial.print("Error trying to execute getDataReadyFlag(): "); errorToString(error, errorMessage, 256); Serial.println(errorMessage); return; } if (!isDataReady) { return; } error = scd4x.readMeasurement(co2, temperature, humidity); if (error) { Serial.print("Error trying to execute readMeasurement(): "); errorToString(error, errorMessage, 256); Serial.println(errorMessage); } else if (co2 == 0) { Serial.println("Invalid sample detected, skipping."); } else { Serial.print("Co2:"); Serial.print(co2); Serial.print("\t"); Serial.print("Temperature:"); Serial.print(temperature); Serial.print("\t"); Serial.print("Humidity:"); Serial.println(humidity); display.setTextSize(2); // Draw 2X-scale text display.setCursor(10,17); display.fillRect(10, 17, 70, 16, SSD1306_BLACK); display.println(temperature); display.setCursor(80,17); display.fillRect(80, 17, 46, 16, SSD1306_BLACK); display.println(humidity,1); display.setCursor(10, 46); display.fillRect(10, 46, 100, 16, SSD1306_BLACK); display.println(co2); display.display(); } }

 実行例です。

前へ

Arduino UNO R4 Minimaでセンサ・インターフェーシング ㉔ 距離センサ VL53L4CX

次へ

Arduino UNO R4の登場で広がるArduinoの世界(5)RTCで現在時刻を得て時刻を表示