Seeeduino XIAO と SGP30 でeCO2濃度測定器を作ってみた(OLED版)

前回小型マイコンボード**Seeeduino XIAO** と Sensirion エアクオリティセンサ**SGP30-2.5K**を使ったeCO2濃度[測定器(LEDアレイ版)](https://qiita.com/kaz19610303/items/1fd52583cbaa319adb91)を公開しましたが、今回は表示器をOLEDに変更したタイプとなります。

機器構成

| 名称 | 型名 | メーカー | データシート等 |
|:----|:----|:----|:----|
| マイコン | Seeeduino XIAO | Seeed |[Seeedウィキ](https://wiki.seeedstudio.com/jp/Seeeduino-XIAO/)
| センサー | SGP30-2.5K | Sensirion | [データシート](https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/9_Gas_Sensors/Datasheets/Sensirion_Gas_Sensors_SGP30_Datasheet.pdf)
| OLED | P-12031(秋月電子通販コード) | SUNHOKEY Electronics Co.,Ltd. | [SSD1306データシート](https://akizukidenshi.com/download/ds/solomon/ssd1306.pdf)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99249/96085643-236d-e37f-547c-9c1b0a391f93.png)


回路図
(LEDアレイ版と同じです)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99249/f48f3a1d-af95-c0ba-a269-91a5e88a00ad.png)


追加ライブラリ
[SparkFunのSPG30ライブラリ](https://github.com/sparkfun/SparkFun_SGP30_Arduino_Library)
[AdafruitのGFXライブラリ](https://github.com/adafruit/Adafruit-GFX-Library)
[AdafruitのSSD1306ライブラリ](https://github.com/adafruit/Adafruit_SSD1306)
以上のライブラリを Arduino IDE のライブラリに追加して下さい。

プログラム

```seeeduino_co2_OLED.ino
/*
  Library for the Sensirion SGP30 Indoor Air Quality Sensor
  By: Ciara Jekel
  SparkFun Electronics
  Date: June 28th, 2018
  License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license).

  SGP30 Datasheet: 
  https://cdn.sparkfun.com/assets/c/0/a/2/e/Sensirion_Gas_Sensors_SGP30_Datasheet.pdf

  Feel like supporting our work? Buy a board from SparkFun!
  https://www.sparkfun.com/products/14813

  This example reads the sensors calculated CO2 and TVOC values
*/

#include "SparkFun_SGP30_Arduino_Library.h" // Click here to get the library: https://github.com/sparkfun/SparkFun_SGP30_Arduino_Library
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

SGP30 mySensor; //create an object of the SGP30 class

void testdrawstyles(void) {
  display.clearDisplay();

  display.setTextSize(2);              // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE); // Draw white text
  display.setCursor(15,30);             // Start at top-left corner
  display.println(F("Next Step"));
  display.display();
}

void co2_data_display(uint16_t co2,uint16_t tvoc) {
  char disp_co2[10];
  char disp_tvoc[10];

  sprintf(disp_co2,"%4d",co2);
  sprintf(disp_tvoc,"%4d",tvoc);

  display.clearDisplay();
  display.setCursor(35,0);             // Start at top-left corner
  display.setTextSize(1);                      // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE);        // Draw white text
  display.println(F("CO2 Monitor"));

  display.setCursor(0,28);             // Start at top-left corner
  display.setTextSize(1);             // Draw 2X-scale text
  display.println(F("CO2")); 
  display.setTextSize(3);             // Draw 2X-scale text
  display.setCursor(35,15);
  display.print(disp_co2);
  display.setTextSize(1);             // Draw 2X-scale text
  display.setCursor(110,28);
  display.print("ppm");
  display.setCursor(0,53);             // Start at top-left corner
  display.println(F("TVOC"));
  display.setTextSize(3);             // Draw 2X-scale text
  display.setCursor(35,40);
  display.print(disp_tvoc);
  display.setTextSize(1);             // Draw 2X-scale text
  display.setCursor(110,53);
  display.print("ppb");
  display.display();
}  


void setup() {
  Serial.begin(115200);

  pinMode(LED_BUILTIN, OUTPUT);

  Wire.begin();

  if (mySensor.begin() == false) {
    for(int i=0; i<10 ; i++){
      digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
      delay(200);                        // wait for a second
      digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
      delay(200);
    }
    while (1);
  }
  delay(2000);

  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x64
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }

  Serial.println("SSD1306 allocation.");

  for(int i=0; i<3 ; i++){
    digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(200);                        // wait for a second
    digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
    delay(200);
  }
  //Initializes sensor for air quality readings
  //measureAirQuality should be called in one second increments after a call to initAirQuality
  mySensor.initAirQuality();
  display.clearDisplay();
  testdrawstyles();    // Draw 'stylized' characters
}

void loop() {
  uint16_t co2_data;
  uint16_t tvoc_data;

  //First fifteen readings will be
  //CO2: 400 ppm  TVOC: 0 ppb
  delay(800); //Wait 2 second
  //measure CO2 and TVOC levels
  mySensor.measureAirQuality();
  co2_data  = mySensor.CO2;
  tvoc_data = mySensor.TVOC;

  co2_data_display(co2_data,tvoc_data);

  Serial.print("CO2: ");
  Serial.println(mySensor.CO2);
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(200);                        // wait for a second
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
}
```
-------
LEDアレイ表示とOLED表示のCO2モニターの製作例を公開しました。
使ったプリント基板に温湿度センサー [AM2322](https://akizukidenshi.com/catalog/g/gM-10880/) を搭載出来るバージョンを設計中です。
基板が出来たらCO2+温湿度モニターを公開します。

2021/01/21 追記
AM2322 を搭載して、温湿度の計測を行えるようにした記事はこちらです。
[eCO2濃度測定器に温湿度センサーを追加しました](https://qiita.com/kaz19610303/items/f615f5dc82712429f0d6)
また基板上にはGROVEのIICコネクタが実装できるようになっていますので、これを使って他のセンサーの追加が出来ます。