BETA

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

投稿日:2020-08-13
最終更新:2020-08-17

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

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

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

用意したもの

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

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

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

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

obnizとセンサーの接続

コード

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/[email protected]/umd/react.production.min.js"></script>  
<script crossorigin src="https://unpkg.com/[email protected]/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濃度にならないようです。
たしかに起動してしばらくは、いつも同じ数値が表示されている気がします。
もし、サーバレスで定期実行させたい場合は、センサーの電源を常時供給させないといけませんね。

技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
or 外部アカウントで 登録 / ログイン する
クランチについてもっと詳しく

この記事が掲載されているブログ

しがないインフラエンジニア屋さんです。いままでローカルのメモ的なテキストでしかアウトプットしてなかったので、ちょっとずつここに記していくよ

よく一緒に読まれる記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう