s51517765のアイコン画像
s51517765 2021年01月26日作成 (2021年02月26日更新)
製作品 製作品 閲覧数 953
s51517765 2021年01月26日作成 (2021年02月26日更新) 製作品 製作品 閲覧数 953

部屋の湿度を監視して警告するシステム

完成の図

きっかけ

関東地方(太平洋側)の冬は極度に乾燥します。
部屋の乾燥具合を監視して警告するシステムを作りました。
また、絶対湿度に触れている事例がなさそうなので絶対湿度基準で評価してみようと思いました。

つかったもの

・ESP32開発ボード
・DTH11(温湿度センサ)
・1602LCD
・抵抗、LEDなど

機能

・時計を表示
・温湿度を測定
・温度・湿度(相対)を表示
・絶対湿度を算出
・絶対湿度が閾値を下回ったらLEDを点灯
・閾値を変更可能

絶対湿度とは

一般に温湿度計等で表示される湿度は相対湿度というものです。
相対湿度はその室温での飽和湿度に対する湿度を%で表示したものです。
つまり、室温が変化すると「空気中の水分量の基準」が変わるため湿度具合が正しく見れているとは言えません。
同じ湿度40%でも夏のような気温の高いときより、冬のような気温の低いときのほうが静電気が起きやすいということを感覚として知っている人は少なくないのではないかと思いますが、このような現象は絶対湿度を使うことで正しく評価できます。

絶対湿度は、↓のページを参考に温度と相対湿度で算出できます。
https://komoriss.com/relative-humidity-volumetric-humidity/

回路図

Dxおよび、5V、3.3VはESP32のピンです。
また、ESP32の5VピンはUSB電源の5Vとつながっています。
これをブレッドボードとジャンパーワイヤーで構築します。
回路図

工夫したところ

①目標湿度調整機能
湿度のちょうどいいところ、というのは人によりけりなところがあります。
ですので、これをコードではなく調整できる仕組みを作りました。
具体的には可変抵抗VR2を調整することで、これを湿度に規格化しています。
D34のピンで電圧を読みますが、可変抵抗VR2の値によってこの電圧が変わります。
これを湿度に換算して目標値にしています。
また、抵抗を動かしたときだけ調整画面に自動で切り替わります。
目標調整画面
②OK/NG(湿度)をLEDで表示
LCDがあるからそれで湿度をみればいいじゃん、というところはありますが、これをわかりやすくLEDのON/OFFに表示しています。

③時計の代わりにもなる
ESPのネットワーク機能を使ってWebから時刻を取得して表示しています。
const char* ntpServer = "pool.ntp.org";
に接続することで時刻を取得します。

④短いジャンパーピンをありもので自作した
ブレッドボード上で回路を形成するとき、ジャンパーワイヤーが森のようになってしまうので、その辺に転がっているもので自作しました。
0.6mmの針金を適当な長さに切って熱収縮チューブをかぶせました。
0.6mmは少し太いです。0.2~0.3mmぐらいが本来はいいと思います。
こういうの、本当は売ってますけど。
自作したジャンパー

まとめ

温湿度計をつくりました。
LCDやら目標湿度調整やらあるものを載せまくった感じです。

ESP32.ino

#include <LiquidCrystal.h> #include <DHT.h> #include <WiFi.h> #include <WiFiClientSecure.h> const char* ssid = "************"; const char* password = "************"; const int TEMP_SNR = 33; const int HUM_VR = 34; const int LED_PIN = 5; int VR2 = 100; //可変抵抗読み取り値 float Temp = 25; float RH = 50; LiquidCrystal lcd(32, 25, 26, 27, 14, 13); DHT dht(TEMP_SNR, DHT11); // DHTクラスをインスタンス化 void wifiConnect() { int tryCount = 0; WiFi.disconnect(); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); // Wi-Fi接続 while (WiFi.status() != WL_CONNECTED) { // Wi-Fi 接続待ち delay(100); Serial.printf("."); tryCount += 1; if (tryCount > 30) { Serial.println("\nwifi connect NG"); return; }; } Serial.println("\nwifi connect OK"); } void setup() { wifiConnect(); lcd.begin(16, 2); dht.begin(); Serial.begin(9600); pinMode(HUM_VR, INPUT); pinMode(LED_PIN, OUTPUT); } void showTemp() { RH = dht.readHumidity(); Temp = dht.readTemperature(); lcd.setCursor(0, 1); lcd.print ("T: "); lcd.setCursor(2, 1); lcd.print (Temp); lcd.setCursor(8, 1); lcd.print ("H: "); lcd.setCursor(10, 1); lcd.print (RH); Serial.print( String(Temp) ); Serial.print( " / " ); Serial.println( String(RH) ); } void showTime() { const long gmtOffset_sec = 3600 * 9; //UTC + 9 const int daylightOffset_sec = 3600 * 0;//Summer Timeなし const char* ntpServer = "pool.ntp.org"; configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); struct tm timeinfo; if (!getLocalTime(&timeinfo)) { Serial.println("Failed to obtain time"); return; } Serial.println(&timeinfo, "%B %d %A %Y %H:%M:%S"); lcd.clear(); lcd.setCursor(0, 0); lcd.print(&timeinfo, "%d %a %H:%M"); return; } int Read_VR2() { int Hum_tgt = analogRead(HUM_VR); Serial.print("Hum_tgt:"); Serial.println(Hum_tgt / 100); //0~3055 return Hum_tgt/ 100 ; // g/m3 } float Abs_Hhm(float temp, float RH) { // https://komoriss.com/relative-humidity-volumetric-humidity/ return 217 * (6.1078 * pow(10, (7.5 * temp / (temp + 237.3)))) / (temp + 273.15) * RH / 100; } void showVR(int VR2) { lcd.clear(); lcd.setCursor(0, 0); lcd.print("Crnt="); lcd.setCursor(5, 0); lcd.print(Abs_Hhm(Temp, RH)); lcd.setCursor(9, 0); lcd.print("Tgt="); lcd.setCursor(13, 0); lcd.print(VR2); } void isLED_ON(int VR, int abs_hum) { if (VR > abs_hum) { digitalWrite(LED_PIN, HIGH); } else { digitalWrite(LED_PIN, LOW); } } void loop() { int tmp = Read_VR2(); float abs_hum = Abs_Hhm(Temp, RH); if ( abs( VR2 - tmp) != 0) { //抵抗変化があったら VR2 = tmp; showVR(VR2); delay(2000); } else { showTime(); showTemp(); isLED_ON(VR2, abs_hum); } delay(2000); }
s51517765のアイコン画像
https://s51517765.hatenadiary.jp/
ログインしてコメントを投稿する