空気品質センサとサーボモータで環境の悪化を通知する

 前回ひとまず空気品質センサ CCS811 で二酸化炭素濃度などを測定してみました。今回は二酸化炭素濃度が閾値を超えたら何か目に見える形で通知するようにしてみたいと思います。オフィスの二酸化炭素濃度は業務のパフォーマンスにも影響するということで、チームラボさんも測定して改善されているようなので、二酸化炭素濃度が高くなっていることがわかるようにしてみたいと思います。

ch.nicovideo.jp

サーボモータを使ってみる

 二酸化炭素濃度が閾値を超えたら Slack に通知するというのをそのうちやりたいとは思ってるんですが、それ自体には自分としてはそんなに目新しさもなかったので、もうちょっとギミック的なものが作れないかなと、サーボモータを使ってみることにしました。

www.switch-science.com

 サーボモータは今まで使ったことなかったのですが、使い方は簡単で、 Arduino ではサーボモータ用のライブラリが標準で用意されているので、それを使用します。まずは servo.attach() で制御用のピンを指定して、 servo.write() で角度を指定するだけです。

#include <Servo.h>

Servo servo;

servo.attach(3); // 制御ピンに 3番ピンを指定する例
servo.write(90); // サーボの角度を 90度に指定する例

 今回はサーボモータに LED を組み合わせて、二酸化炭素濃度が閾値を超えたら LED が点灯しつつ持ち上がるようにしてみたいと思います。

回路図

 だいぶごちゃっとしてしまいましたが、回路図は下記のようになりました。

f:id:akanuma-hiroaki:20180619003533p:plain

 CCS811 の配線については基本は前回と同じですが、今回はサーボモータを使う都合で Seeeduino の動作電圧を 5V にしたので、 CCS811 の NOT_WAK ピンへの入力電圧が 3.3V 以下になるように、4.7kΩ の抵抗を使用して分圧しています。

 サーボモータの電源は 5V 出力から取り、制御ピンは 3番ピンを使用しています。

 LED には 330Ωの抵抗を使用しています。

ファームウェア

 ファームウェアも基本的には前回と同様で、サーボモータと LED の初期化と、二酸化炭素濃度の測定値によってサーボモータと LED を制御する処理を追加しています。

#include <SparkFunCCS811.h>
#include <Servo.h>

#define CCS811_ADDR 0x5B

#define PIN_NOT_WAKE 5
#define PIN_NOT_INT 6
#define PIN_SERVO 3
#define PIN_LED 4

#define DEGREE_CLEAN_AIR 90
#define DEGREE_DIRTY_AIR 0
#define CO2_THRESHOLD 1000

CCS811 myCCS811(CCS811_ADDR);
Servo servo;

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

  CCS811Core::status returnCode;
  
  returnCode = myCCS811.begin();
  Serial.print("CCS811 begin exited with: ");
  printDriverError( returnCode );
  Serial.println();
  
  returnCode = myCCS811.setDriveMode(2);
  Serial.print("Mode request exited with: ");
  printDriverError( returnCode );
  Serial.println();
  
  pinMode(PIN_NOT_INT, INPUT_PULLUP);
  returnCode = myCCS811.enableInterrupts();
  Serial.print("Interrupt configuation exited with: ");
  printDriverError( returnCode );
  Serial.println();
  
  pinMode(PIN_NOT_WAKE, OUTPUT);
  digitalWrite(PIN_NOT_WAKE, 1);
  
  servo.attach(PIN_SERVO);
  servo.write(90);
  
  pinMode(PIN_LED, OUTPUT);
}

void loop() {
  if (digitalRead(PIN_NOT_INT) == 0)
  {
    digitalWrite(PIN_NOT_WAKE, 0);
    delay(1);
    myCCS811.readAlgorithmResults();
    
    Serial.print("CO2[");
    Serial.print(myCCS811.getCO2());
    Serial.print("] tVOC[");
    Serial.print(myCCS811.getTVOC());
    Serial.print("] millis[");
    Serial.print(millis());
    Serial.print("]");
    Serial.println();
    
    if (myCCS811.getCO2() >= CO2_THRESHOLD)
    {
      digitalWrite(PIN_LED, HIGH);
      servo.write(DEGREE_DIRTY_AIR);
    }
    else
    {
      digitalWrite(PIN_LED, LOW);
      servo.write(DEGREE_CLEAN_AIR);
    }
    
    digitalWrite(PIN_NOT_WAKE, 1);
    delay(1);
  }
}

void printDriverError( CCS811Core::status errorCode )
{
  switch ( errorCode )
  {
    case CCS811Core::SENSOR_SUCCESS:
      Serial.print("SUCCESS");
      break;
    case CCS811Core::SENSOR_ID_ERROR:
      Serial.print("ID_ERROR");
      break;
    case CCS811Core::SENSOR_I2C_ERROR:
      Serial.print("I2C_ERROR");
      break;
    case CCS811Core::SENSOR_INTERNAL_ERROR:
      Serial.print("INTERNAL_ERROR");
      break;
    case CCS811Core::SENSOR_GENERIC_ERROR:
      Serial.print("GENERIC_ERROR");
      break;
    default:
      Serial.print("Unspecified error.");
  }
}

動作時の様子

 だいぶ雑多な感じですが、とりあえず組んでみた回路は下記のようになりました。

f:id:akanuma-hiroaki:20180619075828j:plain

 二酸化炭素濃度が閾値を超えると下記画像のようにサーボモータが 90度回転して、 LED も点灯します。

f:id:akanuma-hiroaki:20180619075858j:plain

まとめ

 今回はとりあえず配線した感じでしたが、もっと配線をすっきりさせて筐体に入れて、サーボが動いた時だけ筐体から出て見えるようにしたり、何か工夫できると面白そうかなと思いました。また、 LED はワニ口クリップで配線してるのですが、下手をするとショートする可能性もあるので、継続的に使うにはこの辺の安全性も改善したいところです。