mono が 2020年06月15日09時21分09秒 に編集
初版
タイトルの変更
ESP8266で部屋の湿度を最適に保つ
タグの変更
IFTTT
ESP8266
Arduino
DHT11
記事種類の変更
セットアップや使用方法
本文の変更
(某共有サイトに投稿していた元記事を移動してきた記事です。真冬に書いたので時期外れな記事です…) **はじめに** 加湿器を自動的にオンオフ切り替えて部屋の湿度を適正に保ちたい!ということで湿度を適正に保つために温度湿度を30分おきに測定し、iftttを使い、一定湿度を下回っていたら加湿器をオンにし、一定湿度を上回っていたら加湿器をオフにする便利?なものを作ります。 ※ ・加湿器自体にオン/オフを制御する仕組みはないので加湿器のスイッチはオンにした状態でスマートプラグを通じて加湿器のオン/オフを制御します。(そのためにはスイッチが簡素なタイプの加湿器が必要) ・適正湿度は、厚生労働省令によって定められた事務所衛生基準規則第2章第5条3によると「40%以上70%以下」としていますが、ここでは湿度40%を下回っていたら加湿器をオンにし、湿度45%を上回っていたら加湿器をオフにすることにします。(湿度45%に特に根拠はないです。なんとなく) ・冗長的で見づらく、拙いコードだとは思いますが、生暖かく見守っていただければ幸いです。 **作ってみる** まずiftttでアプレットを2つ作る。(加湿器オン用/オフ用) 作り方は[こちら](https://elchika.com/article/80b5bc1c-6b88-4aff-98ec-5fdfa4bd4695/)の記事してください。 連携先チャンネルは、使用するスマートプラグによって違います。(自分の場合はSmart Lifeを使用しました。) こんな感じで作ります。 ![キャプションを入力できます](https://camo.elchika.com/5cce01aba9027e5d84859dd4fffcc5b88669f2ef/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f34623535663234372d343264612d346463342d383136312d3465313134383033653664362f31313362343861352d393233342d346137662d613539322d383233343633613863376435/) ![キャプションを入力できます](https://camo.elchika.com/65752795f9f70578bea85a330d26b8cbf66d7e0f/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f34623535663234372d343264612d346463342d383136312d3465313134383033653664362f63323239373161332d613730642d343830372d393364392d306634613364316537646666/) **コード** まずはwifiやiftttの設定 ※Ambientによるグラフ作成もあったら便利なのでグラフ作成の機能もついています。詳しくは[こちらの記事](https://elchika.com/article/80b5bc1c-6b88-4aff-98ec-5fdfa4bd4695/)を参照てください。 ```arduino: #include <ESP8266WiFi.h> #include <WiFiUdp.h> #include <Ambient.h> #include "DHT.h" // DHT11の設定 #define DHTPIN 12 // 使用するGPIOピン #define DHTTYPE DHT11 // DHT 11 #define channelId 15158 // Ambientのチャネル番号 #define writeKey "writeキー" // Ambient の書き込みキーをセット DHT dht(DHTPIN, DHTTYPE); WiFiClient client; Ambient ambient; //WiFiのIDとPASS const char *WIFI_SSID = "WiFiのID"; const char *WIFI_PASSWORD = "WiFiのパスワード"; // ITFFFの設定 const char* host = "maker.ifttt.com"; const char* secretkey = "iftttのイベントキー"; const int LED_PIN = 5; //LEDの設定 const float Second = 1000; //1秒 //float型にして小数点にも対応 //ifttt用のURL作成,動作させたいiftttのイベント名、温度、湿度の値を入れて呼び出す String iftttURL(String event, float t, float h){ //t=temperature,h=humidity String ifttt = "/trigger/"+event+"/with/key/"+secretkey+"?value1=" +String(t)+"&value2="+String(h); return ifttt; } //LED点滅用,数値を入れて呼び出すと数値分点滅する void LED(int ledInt){ for(int i=0;i<ledInt;i++){ digitalWrite( LED_PIN, HIGH ); //点灯 delay(Second * 0.2); digitalWrite( LED_PIN, LOW ); //消灯 delay(Second * 0.2); } } void setup() { Serial.begin(115200); // WiFiに接続 Serial.println(WIFI_SSID); Serial.print("Waiting for Wi-Fi connection"); WiFi.mode(WIFI_STA); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); while (WiFi.status() != WL_CONNECTED) { delay(Second*0.5); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); pinMode( LED_PIN, OUTPUT ); ambient.begin(channelId, writeKey, &client); // チャネルIDとライトキーを指定してAmbientの初期化 dht.begin(); //LED5回点滅で接続確認 LED(5); } ``` LEDをつけて動作してるのか確認していますが、不必要ならLEDに係る部分はいらないです。 続いてメインの動作部分 ```arduino: void loop() { String url = ""; //url初期化 // DHT11から読み込み float t = dht.readTemperature(); float h = dht.readHumidity(); delay(Second); //取得にラグがあるので1秒遅延 if (isnan(t) || isnan(h)) { Serial.println("Failed to read from DHT sensor!"); return; } Serial.println("Temperature: " + String(t) + "C H timeClient.begin();umidity: " + String(h) + "%"); const int httpPort = 80; //http接続なので、ポート80を使用。https接続はしない。 if (!client.connect(host, httpPort)) { Serial.println("connection failed"); return; } // IFTTTに温度と湿度を送る if(40.0>h){ Serial.println("on"); url = iftttURL("加湿器onイベント名",t,h); }else{ Serial.println("off"); url = iftttURL("加湿器offイベント名",t,h); } // IFTTTにリクエストを送る Serial.print("Requesting URL: "); Serial.println(url); client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); while (client.connected()) { String line = client.readStringUntil('\n'); if (line == "\r") { // ヘッダ部分の受取終了 break; } } //Ambientに温度と湿度を送る ambient.set(1, t); ambient.set(2, h); ambient.send(); // Ambientにデータを送信 //一通り動作が終了したことを知らせるため1分間LED点灯 digitalWrite( LED_PIN, HIGH ); delay( Second * 60 ); digitalWrite( LED_PIN, LOW ); delay( Second * 1739 ); //約30分停止、遅延分を除いた秒数 } ``` これでとりあえず完成です。 時間の計測に関しては結構ガバガバです。NTPサーバーから時間を取得して正確にな時間通りに動作させることも出来ますが、今回はとりあえず動けばいいので省略します。 **追記** かなり冗長的ですがNTPとの時間同期をしてある程度正確に30分おきに動作するようにしました。 ```arduino: #include <ESP8266WiFi.h> #include <NTPClient.h> #include <WiFiUdp.h> #include <Ambient.h> #include "DHT.h" // DHT11の設定 #define DHTPIN 12 // 使用するGPIOピン #define DHTTYPE DHT11 // DHT 11 #define channelId 15158 // Ambientのチャネル番号 #define writeKey "11ed2c071c1b8c9b" // Ambient の書き込みキーをセット DHT dht(DHTPIN, DHTTYPE); WiFiUDP ntpUDP; NTPClient timeClient(ntpUDP); WiFiClient client; Ambient ambient; //WiFiのIDとPASS const char *WIFI_SSID = "*****"; const char *WIFI_PASSWORD = "*****"; // ITFFFの設定 const char* host = "maker.ifttt.com"; const int LED_PIN = 5; const float Second = 1000; //1秒 void setup() { Serial.begin(115200); // WiFiに接続 Serial.println(WIFI_SSID); Serial.print("Waiting for Wi-Fi connection"); WiFi.mode(WIFI_STA); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); while (WiFi.status() != WL_CONNECTED) { delay(Second*0.5); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); pinMode( LED_PIN, OUTPUT ); ambient.begin(channelId, writeKey, &client); // チャネルIDとライトキーを指定してAmbientの初期化 dht.begin(); timeClient.begin(); for(int i=0;i<5;i++){ digitalWrite( LED_PIN, HIGH ); delay(Second*0.5); digitalWrite( LED_PIN, LOW ); } } //20秒ごとに時間確認 void MainProcess(int TimeMinutes){ Serial.println(TimeMinutes); //毎時30分ごとに処理 if(TimeMinutes == 00 || TimeMinutes == 30){ String url = ""; //url初期化 // DHT11から読み込み float t = dht.readTemperature(); float h = dht.readHumidity(); delay(200); if (isnan(t) || isnan(h)) { Serial.println("Failed to read from DHT sensor!"); return; } Serial.println("Temperature: " + String(t) + "C Humidity: " + String(h) + "%"); const int httpPort = 80; //http接続なので、ポート80を使用。https接続はしない。 if (!client.connect(host, httpPort)) { Serial.println("connection failed"); return; } // IFTTTに温度と湿度を送る if(40.0>h){ Serial.println("on"); url = iftttURL("test",t,h); }else{ Serial.println("off"); url = iftttURL("test2",t,h); } // IFTTTにリクエストを送る Serial.print("Requesting URL: "); Serial.println(url); client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); while (client.connected()) { String line = client.readStringUntil('\n'); if (line == "\r") { // ヘッダ部分の受取終了 break; } } //Ambientに温度と湿度を送る ambient.set(1, t); ambient.set(2, h); ambient.send(); // Ambientにデータを送信 digitalWrite( LED_PIN, HIGH ); delay( Second * 60 ); }else{ Serial.println("else"); LED(4); } forDelay(20); } void forDelay(int count){ for(int i=0; i<count; i++){ Serial.println(i); delay(Second); } return; } //URL作成 String iftttURL(String event, float t, float h){ String ifttt = "/trigger/"+event+"/with/key/*keyを入力*?value1=" +String(t)+"&value2="+String(h); return ifttt; } //LED点滅 void LED(int ledInt){ for(int i=0;i<ledInt;i++){ digitalWrite( LED_PIN, HIGH ); delay(Second * 0.2); digitalWrite( LED_PIN, LOW ); delay(Second * 0.2); } } void loop() { Serial.println("hello"); //時間取得 timeClient.update(); Serial.println(timeClient.getSeconds()); //秒表示 Serial.println(timeClient.getFormattedTime()); //分表示 int TimeSeconds = timeClient.getSeconds(); int TimeMinutes = timeClient.getMinutes(); Serial.println(TimeMinutes); //50分以降になったらMainProcess呼び出し それ以外は3分ごとに時間同期 if(TimeMinutes >= 50){ MainProcess(TimeMinutes); }else if(TimeMinutes == 00){ MainProcess(TimeMinutes); }else if(TimeMinutes >= 20 && TimeMinutes <= 30){ MainProcess(TimeMinutes); }else{ Serial.println("=================="); LED(2); //delay(Second * 180); forDelay(180); } } ``` **最後に** 普段の生活を少しでも便利にする物を作ってみたいという目標は、これでとりあえず達成! また、何かアイディアが思いついたら作ってみたいと思います。(センサー類がもっと欲しい…)