2021-01-03に投稿

【obniz】MH-Z19B CO2センサーモジュールを使って二酸化炭素濃度を計測する

部屋の換気状態が適切かどうか調べてみたくて、MH-Z19Bとobnizを組みあわせて、計測した二酸化炭素濃度を表示するものを作成してみました。

コードはyukilabさんが作成したものを参考にしたので、自力で作成したのは回路くらいですね(笑)

↓こんな感じにobniz Boardにco2濃度が表示されます(コードを実行しているブラウザにも表示されます)
59777b175d25df873ff90170bc6d224b.jpg

用意したもの

MH-Z19Bとピンヘッダーのハンダ付け

MH-Z19Bはご覧のように、端子が穴になっているので、このままではジャンパワイヤで接続できません

77ab65800ae3f8d834658cd718304559.jpg

ピンヘッダーを適切にカットして、センサーの端子穴に入れてハンダ付けします
aa9bbf76e8e435a92efa402790d35024.jpg

完成です!
端子が結構小さいのでハヅキルーペがあると、見やすくなってハンダ付けが捗ります

3e33b9fdfee8feb973adc0efcd5288c6.jpg

obnizとセンサーの接続

9f99862cd26323ff9dfc40a814a57a8d.png

コード

obnizのオンラインエディタに入力します
今回参考にしたコードは、センサーが若干違うのか、ppmの計算式が手元のセンサーとデータシートと異なっていました。
データシート 7ページ目には、CO2 concentration = HIGH * 256 + LOW とのことなので以下のように修正しています。

修正前の部分

let level = data[2] * 100 + data[3];

修正後の部分

let level = data[2] * 256 + data[3];

完成したコード

ほぼ参考にしたコードのままなので、センサーの取得間隔は20秒、LEDが点滅するしきい値は1500ppmとなっています。

<html lang="ja">
<head>
    <title>CO2 level</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://obniz.io/js/jquery-3.2.1.min.js"></script>
    <script src="https://unpkg.com/[email protected]/obniz.js"></script>
    <style type="text/css">
        .sub {
            vertical-align: sub;
            font-size: smaller;
        }
    </style>
</head>
<body>

<div id="obniz-debug"></div>
<h1>CO<span class="sub">2</span> level</h1>
<button id="read" style="display:none">read</button>
<div id="print"></div>
<div id="app"></div>

<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<script>
    let obniz = new Obniz("OBNIZ_ID_HERE");
    let onconnect_func = async function () {
        let power = obniz.wired("USB", {gnd: 3, vcc: 2});
        let led = obniz.wired("LED", {anode: 10, cathode: 11});
        let co2history = [];
        obniz.keepWorkingAtOffline(true);

        power.on();
        let uart0 = obniz.getFreeUart();
        obniz.uart0.start({tx: 0, rx: 1, baud: 9600});

        led.on();
        await obniz.wait(3000);
        led.off();

        obniz.uart0.onreceive = function (data, text) {
            if (data[0] == 0xff && data[1] == 0x86) {
                let level = data[2] * 256 + data[3];
                co2history.push(level);
                if (co2history.length > 100) {
                    co2history.splice(0, 1);
                }

                ReactDOM.render(
                    React.createElement('h1', null, level.toString() + 'ppm'),
                    document.getElementById("app")
                );

                obniz.display.drawing(false);
                obniz.display.clear();

                // obnize display resolution is 128*64
                var x0 = 0;
                var y0 = 64 - co2history[0] / 40;
                for (let i = 0; i < co2history.length; i++) {
                    let val = 64 - co2history[i] / 40;
                    obniz.display.line(x0, y0, i, val);
                    x0 = i;
                    y0 = val;
                }
                obniz.display.line(0, 64 - 25, 128, 64 - 25);
                obniz.display.line(0, 64 - 50, 32, 64 - 50);

                obniz.display.font('Consolas', 20);
                obniz.display.pos(40, 2);
                obniz.display.print(level.toString() + 'ppm');

                obniz.display.font('Avenir', 8);
                obniz.display.pos(0, 64 - 25);
                obniz.display.print("1000");

                obniz.display.pos(0, 64 - 50);
                obniz.display.print("2000");

                obniz.display.drawing(true);

                if (level > 1500) {
                    high_alert(level / 100);
                }
            }
        };

        let read_co2 = function () {
            obniz.uart0.send([0xff, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79]);
        };

        let high_alert = async function (n) {
            for (let i = 0; i < n; i++) {
                led.on();
                await obniz.wait(300);
                led.off();
                await obniz.wait(300);
            }
        };

        $('#read').click(read_co2);
        setInterval(read_co2, 20 * 1000); // update every 20sec
    };

    obniz.onconnect = onconnect_func;

</script>
</body>
</html>

注意点

センサーのデータシートにはPreheat time 3minとあるので、コードを実行して3分経過しないと正確なCO2濃度にならないようです。
たしかに起動してしばらくは、いつも同じ数値が表示されている気がします。
もし、サーバレスで定期実行させたい場合は、センサーの電源を常時供給させないといけませんね。

ツイッターでシェア
みんなに共有、忘れないようにメモ

arohajiro

しがない元インフラエンジニアです

Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

有料記事を販売できるようになりました!

こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?

コメント