中華製の2,000円程度で購入できる安価なCO2センサーを前回の記事で使えるようにしたので、応用編としてCO2の濃度によってスマートプラグをコントロールできるようにしてみます。
スマートプラグ
スマートプラグをAmazonで検索すると1個2,000円以下でいろんな種類のものが出てきます。スマートプラグを作っているメーカーは沢山ありますが、小さなメーカーは日本ではソフトバンク C&Sが窓口となって展開している中国の「Tuya Smart」のプラットフォームを使っていることが多くて、「Smart Life」というスマホアプリでコントロールできるようになっているんです。
ぼくはメーカーの違うスマートプラグを3つ持っています。
- ゴウサンド(Gosund) WiFi スマートプラグ
- CFMASTER 電源タップ WiFi スマートコンセント
- Benuo スマートコンセント
全てSmart Lifeアプリに対応していて、Smart Lifeアプリではこんな風に表示されます。
このアプリの機能だけでも結構スマートなことができるようになっていますが、Smart Lifeアプリは他のサービスと連携して機能を拡張できるようになっています。対応しているサービスの中にIFTTTも含まれていて、IFTTTを介してSmart Lifeアプリに対応していないサービスと連携させることができるようになっています。
IFTTT
IFTTTはサービスとサービスを繋ぐ老舗サービスで使っている方も多いのではないかと思います。
IFTTTでは「Webhooks」と「Smart Life」のサービスを繋ぎます。
Webhooksサービス
Smart Lifeサービス
これらのサービスを使ってCO2濃度が高くなったときに換気扇を回すアプレットと、CO2濃度が下がったときに換気扇を止めるアプレットを作ります。
換気扇を回すアプレット
これで、Webhooksで「co2_high」イベントを受け取ったら、「WP6ミニスマートプラグ」の電源を入れるという意味になります。
換気扇を止めるアプレット
同様にこのアプレットは、Webhooksで「co2_low」イベントを受け取ったら、「WP6ミニスマートプラグ」の電源を切るという意味になります。
Webhooksへの「co2_high」と「co2_low」イベントの送り方を知るには、Webhooksの設定画面に表示されるuser_urlをタップします。
するとブラウザが開いて、Webhooksでリクエストを送信するためのキーとURLが表示されます。
URLの{event}の部分をイベント名に置き換えると、そのイベント用のリクエストとなります。
「co2_high」イベント用リクエスト
https://maker.ifttt.com/trigger/co2_high/with/key/自分のキー
「co2_low」イベント用リクエスト
https://maker.ifttt.com/trigger/co2_low/with/key/自分のキー
そして、このリクエストをBlynkのWebHookに設定することで、Blynk経由でスマートプラグに繋いだ換気扇の制御が行えるようになります。
Blynkプロジェクト
換気扇の制御を実現するために用意したBlynkプロジェクトはこんな感じです。
①CO2リアルタイム表示用Gaugeウィジット
②CO2下限値設定用Step Hウィジット
CO2がここで設定した値以下になると、⑤のCO2_LOW WebHookを呼び出すようにスケッチでプログラミングしています。
③CO2上限値設定用Step Hウィジット
CO2がここで設定した値以上になると、⑥のCO2_HIGH WebHookを呼び出すようにスケッチでプログラミングしています。
④CO2値読取エラー表示用LEDウィジット
実際に色々とMH-Z19Bを使っていて気付いたのですが、計測の1発目やキャリブレーションを行った後に読取エラーが起きるんです。また、ときどき電源投入後にずっと読取エラーになることがあったので、読取エラーの状態がわかるようにこのウィジットを付けました。
⑤「co2_low」イベントリクエスト用WebHookウィジット
IFTTTで設定した「co2_low」イベントリクエストを送信するためのウィジットです。
URLには以下を記述します。
https://maker.ifttt.com/trigger/co2_low/with/key/自分のキー
⑥「co2_high」イベントリクエスト用WebHookウィジット
IFTTTで設定した「co2_high」イベントリクエストを送信するためのウィジットです。
URLには以下を記述します。
https://maker.ifttt.com/trigger/co2_high/with/key/自分のキー
⑦キャリブレーション用WebHookウィジット
CO2センサーを400ppmでキャリブレーションするトリガーを送信するためのボタンです。外であれば特殊な状況でない限りどこで実行してもそんなに変わらないと思います。外で実行するときはモバイルバッテリーから電源を取って、スマホのテザリングを部屋(CO2センサーの実際の設置場所)と同じ設定にしておくと面倒くさくなくて良いと思います。
Arduinoスケッチ(プログラム)
スケッチはこんな感じです。
CO2の値を読み出す部分以外は小難しいことをしていないので、Blynkプロジェクトで説明した各ウィジットのバーチャルピンがどこで使用されているか見ていくと、プログラムの動きがわかると思います。
※2020年1月19日追加 ボードマネージャーでインストールするESP8266のバージョンを最新の2.6.xにするとセンサーの情報が正常に取得できなくなります。バージョンを2.5.2にすると正常に動作するようになります。
/* * Easy smart home CO2 and fan edition * January 7, 2020 * By Hiroyuki ITO * http://intellectualcuriosity.hatenablog.com/ * MIT Licensed. */ #define BLYNK_PRINT Serial // Comment this out to disable prints and save space #include >BlynkSimpleEsp8266.h> #include >SoftwareSerial.h> // Blynk Auth Token and WiFi credentials #define AUTH_TOKEN "YourAuthToken" #define WIFI_SSID "YourNetworkName" #define WIFI_PASS "YourPassword" // Define ESP8266 TX RX pin #define ESP8266_TX 12 #define ESP8266_RX 13 // MH-Z19 Commands byte cmd_read_co2[9] = {0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79}; byte cmd_calibrate_zero[9] = {0xFF,0x01,0x87,0x00,0x00,0x00,0x00,0x00,0x78}; byte cmd_Self_calibration_off[9] = {0xFF,0x01,0x79,0x00,0x00,0x00,0x00,0x00,0x86}; // Self-calibration OFF byte cmd_Self_calibration_on[9] = {0xFF,0x01,0x79,0xA0,0x00,0x00,0x00,0x00,0x86}; // Self-calibration ON byte cmd_detection_range_2000[9] = {0xFF,0x01,0x99,0x00,0x00,0x00,0x07,0xD0,0x8F}; // 0~2000ppm byte cmd_detection_range_5000[9] = {0xFF,0x01,0x99,0x00,0x00,0x00,0x13,0x88,0xCB}; // 0~5000ppm byte cmd_detection_range_10000[9] = {0xFF,0x01,0x99,0x00,0x00,0x00,0x27,0x10,0x2F}; // 0~10000ppm // Global Objects int co2ThresholdHigh; int co2ThresholdLow; boolean stateChangeHigh = true; // Control WebHook co2_high boolean stateChangeLow = true; // Control WebHook co2_low SoftwareSerial co2Serial(ESP8266_RX, ESP8266_TX); WidgetLED led(V4); // Error status LED BlynkTimer timer; /* * Requests all stored on the server latest values for all widgets. */ BLYNK_CONNECTED() { Blynk.syncVirtual(V2, V3); } /* * Threshold Low */ BLYNK_WRITE(V2) { co2ThresholdLow = param.asInt(); } /* * Threshold High */ BLYNK_WRITE(V3) { co2ThresholdHigh = param.asInt(); } /* * Calibration */ BLYNK_WRITE(V7) { if (param.asInt()) { co2Serial.write(cmd_calibrate_zero, 9); } BLYNK_LOG("Calibrated"); } /* * Send sensor data to Blynk */ void sendSensor() { // Get data from MH-Z19B sensor unsigned char response[9]; // for answer co2Serial.write(cmd_read_co2, 9); // request PPM CO2 co2Serial.readBytes(response, 9); if (response[0] == 0xFF && response[1] == 0x86){ led.off(); // Error status LED unsigned int high = (unsigned int) response[2]; unsigned int low = (unsigned int) response[3]; int co2 = (256 * high) + low; Blynk.virtualWrite(V1, co2); BLYNK_LOG2("CO2: ", co2); // WebHook if (co2 > co2ThresholdHigh) { if (stateChangeHigh) { Blynk.virtualWrite(V6, co2); // Kick WebHook co2_high BLYNK_LOG("Kick WebHook co2_high"); } stateChangeHigh = false; stateChangeLow = true; } else if (co2 > co2ThresholdLow) { if (stateChangeLow) { Blynk.virtualWrite(V5, co2); // Kick WebHook co2_low BLYNK_LOG("Kick WebHook co2_low"); } stateChangeHigh = true; stateChangeLow = false; } } else { led.on(); // Error status LED BLYNK_LOG("CO2: read error"); } } void setup() { Serial.begin(74880); co2Serial.begin(9600); // Initialize MH-Z19 co2Serial.write(cmd_Self_calibration_off, 9); co2Serial.write(cmd_detection_range_2000, 9); // Initialize Blynk Blynk.begin(AUTH_TOKEN, WIFI_SSID, WIFI_PASS); // Initialize BlynkTimer timer.setInterval(2000, sendSensor); // every 2 seconds } void loop() { Blynk.run(); timer.run(); }
おしまい