見出し画像

在宅勤務中の換気、ちゃんとしてますか?

今週なんかさむくないですか?エンジニアの伊藤です。
IoTっぽいことをやってるtoyチームに所属してます。遊び心を大切にしてるチームです。

5月に仕事と家庭の両立的な話を書いてから、ワイフが職場復帰したり、変化がありました。

その話を書こうかなと思ったのですが、すでにdaiさんNさんがとても共感できる記事を書いてくれました。
なので、僕は、在宅勤務の課題に取り組んだ内容を書こうかなと思います。技術要素多めです。

在宅勤務

さて、みなさんは、リモートワークしてますか?
僕は、在宅勤務メインで仕事してます。

在宅勤務のメリットはたくさんあって、とても気に入っています。
ACALLの働き方の自由を享受しております。ありがたや、ありがたや。
ただ、困ることもそこそこあります。
今回はその中でも、冬場に気になる「換気忘れがち問題」について取り組んでみました。

換気忘れがち問題

最近、感染症対策で換気大事ってなってますよね。
会社で働いてると空調が良いように換気してくれてたり、気の利く同僚が換気してくれたり、窓を開けっ放しにしたりで対応していると思います。
ただ、家にいると、窓開けっ放しは光熱費的に難しいし、空調もそんなにやし、気の利く同僚もいないので、換気が心配ですよね。
感染症的にはリスク小さいと思いますが、冬場は換気をしないと空気がこもって、能率落ちてる気がしてます。
なので、家でも空気の状態をセンシングしたいなぁと思ってました。

作りたいもの

まず、ユーザーストーリーと仕様を考えました。
こんな感じ?

ユーザーストーリー
・在宅勤務ワーカーとして、現在の空気の状態を知ることができる。なぜなら、空気がこもったさいに換気をすることで、仕事能率の低下を防ぎたいからだ。
・在宅勤務ワーカーとして、現在の空気の状態が悪くなったさいに通知をなんらかの受け取ることができる。なぜなら、空気がこもったさいに換気をすることで、仕事能率の低下を防ぎたいからだ。
・在宅勤務ワーカーとして、過去の空気の状態を知ることができる。なぜなら、能率とCO2の関係を振り返りたいからだ。

仕様
・液晶に色付きの数字でCO2濃度を表示する
・CO2濃度が高いときは色を変えて表示する
・ブラウザ経由でCO2濃度の時間変化を表示する

材料の選定

ハードウェア
料理は材料大事ですよね。電子製品も同じです。知らんけど。

空気の状態って言ってもいろいろあると思いますが、仕事の能率や健康を考える際は、二酸化炭素(CO2)の量を測定したら、良いのかなと考えました。調べるとセンサーもたくさん売られてます。ただ、どれも高い。安いもあるけど評価が低い。悩ましい。
ということで、部品買って、自分で作ってみることにしました。

検索しているとAmbientさんのすばらしい記事を発見しました。

入手しやすいセンサーの性能を比較してくれています。
どうも、NDIR方式のCO2センサーとMOXガスセンサーがあるようです。
精度は判断しにくいですが、それっぽいです。
直接測りたいので、NDIR方式のCO2センサーにしました。
また、値段的にMH-Z19Bを使うことにしました。2,000円ちょい。

マイコン側は、ちょうど手元にあったM5StickCを使うことにしました。2,000円くらい。Wi-FiもBluetoothも使えて、小さいし液晶もついて、コミュニティーも盛んで、すごく優秀です。

検索すると、先人たちもたくさんいて、この組み合わせは安心感ばつぐんです。
たくさん出てくるのでぜひ検索してください。

画像1

クラウド
クラウド側、悩ましいですが、AWS IoTとAWS CloudWatchを使うことにしました。
理由は、ACALLはAWSを使っててそれになれてるからです。
Googleのスプレッドシートとかを使う方法も考えてみましたが、そっちのほうが大変そうだし管理めんどいなとなりました。
なれてるのを使うの大事。

AWSだけで完結するので、シンプルですね。

作り方

ハードウェア
どうやってつなごうかなと思いましたが、コネクタケーブルがついてたので、それを2.54mmのピンヘッダにつないで、接続しました。

コネクタ端子がわからなかったので、プローブをあててしらべました。こんな感じでした。

画像2

ハンダは、キングギドラみたいなの(名前がわからん)を使うと楽できます。

画像3

まじめに熱収縮チューブも使って接続しました。ちょっとケーブル長かった。

画像4

ソフトウェア

Arduino環境で書き込みました。MacのBig Surに多少苦しめられましたが、基本、コピペのつぎはぎで動きました。

CO2濃度を読み込む部分はnara256さんて方が公開してるこのライブラリを使いました。

LCDの表示はM5StickCのライブラリを使いました。
ここを参考にしました。

AWS IoTの接続はここを参考にしました。

AWS CloudWatchを使った表示はここを参考にしました。

最終的に、こんなコードになりました。

#include "secrets.h"
#include <WiFiClientSecure.h>
#include <MQTTClient.h>
#include <ArduinoJson.h>
#include "WiFi.h"
#include <M5StickC.h>
#include <MHZ19_uart.h>

const int rx_pin = 36;  //Serial rx pin no
const int tx_pin = 26;  //Serial tx pin no

MHZ19_uart mhz19;

// The MQTT topics that this device should publish/subscribe
#define AWS_IOT_PUBLISH_TOPIC   "esp32/pub"
#define AWS_IOT_SUBSCRIBE_TOPIC "esp32/sub"

unsigned long startDispMillis;
unsigned long startPubMillis;
unsigned long currentMillis;

// Publish messages every 5 mins
const unsigned long pubInterval = 300000;
// Display messages every 10 sec
const unsigned long dispInterval = 10000;

WiFiClientSecure net = WiFiClientSecure();
MQTTClient client = MQTTClient(256);

void initM5Lcd() {
 M5.begin();
 M5.Lcd.setRotation(3);
 M5.Axp.ScreenBreath(9);
}

void connectAWS()
{
 WiFi.mode(WIFI_STA);
 WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

 Serial.println("Connecting to Wi-Fi");

 while (WiFi.status() != WL_CONNECTED) {
   delay(500);
   Serial.print(".");
 }

 // Configure WiFiClientSecure to use the AWS IoT device credentials
 net.setCACert(AWS_CERT_CA);
 net.setCertificate(AWS_CERT_CRT);
 net.setPrivateKey(AWS_CERT_PRIVATE);

 // Connect to the MQTT broker on the AWS endpoint we defined earlier
 client.begin(AWS_IOT_ENDPOINT, 8883, net);

 // Create a message handler
 client.onMessage(messageHandler);

 Serial.print("Connecting to AWS IOT");

 while (!client.connect(THINGNAME)) {
   Serial.print(".");
   delay(100);
 }

 if (!client.connected()) {
   Serial.println("AWS IoT Timeout!");
   return;
 }

 // Subscribe to a topic
 client.subscribe(AWS_IOT_SUBSCRIBE_TOPIC);

 Serial.println("AWS IoT Connected!");
}

void publishMessage(int co2ppm)
{
 StaticJsonDocument<200> doc;
 doc["time"] = millis();
 doc["co2"] = co2ppm;
 char jsonBuffer[512];
 serializeJson(doc, jsonBuffer); // print to client
 client.publish(AWS_IOT_PUBLISH_TOPIC, jsonBuffer);
 Serial.println("Published");
}

void messageHandler(String &topic, String &payload) {
 Serial.println("incoming: " + topic + " - " + payload);

 StaticJsonDocument<200> doc;
 deserializeJson(doc, payload);
 const char* message = doc["co2"];
}

void printM5Lcd(int co2ppm) {
 if (co2ppm >= 1500) {
   M5.Lcd.fillScreen(TFT_RED);
   M5.Lcd.setTextColor(TFT_WHITE);
 } else if (co2ppm >= 1000) {
   M5.Lcd.fillScreen(TFT_YELLOW);
   M5.Lcd.setTextColor(TFT_BLACK);
 } else {
   M5.Lcd.fillScreen(TFT_BLACK);
   M5.Lcd.setTextColor(TFT_WHITE);
 }
 M5.Lcd.setTextSize(5);
 M5.Lcd.setCursor(3, 22);
 M5.Lcd.printf("%4d", co2ppm);

 M5.Lcd.setTextSize(2);
 M5.Lcd.setCursor(121, 44);
 M5.Lcd.printf("ppm");
}

void setup() {

 mhz19.begin(rx_pin, tx_pin);
 mhz19.setAutoCalibration(false);
 delay(100);

 initM5Lcd();
 delay(100);

 Serial.begin(9600);
 delay(100);

 connectAWS();
 delay(100);
}

void loop() {
 currentMillis = millis();

 if (currentMillis - startDispMillis >= dispInterval)
 {
   int co2ppm = mhz19.getPPM();
   int temp = mhz19.getTemperature();

   Serial.print("co2: "); Serial.println(co2ppm);
   Serial.print("temp: "); Serial.println(temp);

   printM5Lcd(co2ppm);
   startDispMillis = currentMillis;
 }

 if (currentMillis - startPubMillis >= pubInterval)
 {
   int co2ppm = mhz19.getPPM();
   int temp = mhz19.getTemperature();

   Serial.print("co2: "); Serial.println(co2ppm);
   Serial.print("temp: "); Serial.println(temp);

   publishMessage(co2ppm);
   startPubMillis = currentMillis;
 }

 client.loop();
}

セキュリティ的な部分は、secrets.hファイルに書いてます。ここ参照。 

クラウドの設定​

ここを参考にしました。

AWS IoT Policyはこんな感じ

{
 "Version": "2012-10-17",
 "Statement": [
   {
     "Effect": "Allow",
     "Action": "iot:Connect",
     "Resource": "arn:aws:iot:xxx:client/python"
   },
   {
     "Effect": "Allow",
     "Action": "iot:Publish",
     "Resource": "arn:aws:iot:xxx:topic/esp32/pub"
   },
   {
     "Effect": "Allow",
     "Action": "iot:Receive",
     "Resource": "arn:aws:iot:xxx:topic/esp32/sub"
   },
   {
     "Effect": "Allow",
     "Action": "iot:Subscribe",
     "Resource": "arn:aws:iot:xxx:topicfilter/esp32/sub"
   }
 ]
}

ルールのクエリはこんな感じ。

SELECT * FROM 'esp32/pub'

CloudWatchの設定(ダッシュボードのソース)は、こんな感じ。

"widgets": [
       {
           "type": "log",
           "x": 0,
           "y": 0,
           "width": 24,
           "height": 6,
           "properties": {
               "query": "SOURCE 'mhz19' | stats avg(co2) by bin(10m)",
               "region": "us-east-2",
               "stacked": false,
               "title": "ロググループ: mhz19",
               "view": "timeSeries"
           }
       }
   ]
}

完成形

そんな感じでコツコツ作って、最終的にこんな感じになりました。いまこそ、3Dプリンターの出番なのですが、故障中なので、このままにしました。残念。

画像5

裏面が無骨。両面テープで貼りました。

画像6

1,000ppmを超えると黄色くなります。これくらいから換気したほうが良いらしいです。

画像7

1,500ppmを超えると赤色になります。

画像8

ブザーとかで通知する機能も考えましたが、運用すると、うざいやろうなと思って、色だけ変えました。

ブラウザから見たグラフはこんな感じ。まだ、データがたまってない・・・。

画像9

通信の接続が切れた場合、リトライしたり、通信切断を表示したりしたいけど、力尽きたので、気が向いたらやろうと思ってます。

最後に

良い感じに機能しています。ワイフやチルドレンからも割と好評な気がします。
今まで感覚で「空気のこもり具合」をセンシングして、なんとなく換気してましたが、見える化できて、自信を持って換気できるようになりました。自信のある換気大事です!飽きずに使い続けられるかは引き続き検証しようと思います。

ACALLでは、IoTプラットフォームを提供しているMODEさんと連携し、「はたらく」や「くらし」に関係する情報をデジタル化することで、より働きやすいワークプレイスを実現しようとしています。
その中で、もっと良い感じにCO2のセンシングも実施しています。ご興味のある方はご連絡ください!!


みんなにも読んでほしいですか?

オススメした記事はフォロワーのタイムラインに表示されます!