M5Stackでデータロガーのような温度・湿度計を作ってみた
結構前のことですが、↓のようなアイテムを気紛れに購入しました。いわばM5Stack用の充電スタンドですが、DHT12の温度・湿度センサを内蔵しており、M5Stackに差し込むだけで、それらが測定可能となる中々面白いアイテムです。
…と言いつつ、長らく買ったまま放置してしまっていたのですが、何か活用してみようと思い至り、データロガーのような温度・湿度計を作ってみました。
DHT12から拾った温度・湿度の値を、以下の過去記事でも触れたスプライトのスクロール機能を用いて、リアルタイムにグラフとして描画しています(あくまで見た目がデータロガーっぽいだけで、データを別途記録する機能などは実装していないですが)。
chemicalfactory.hatenablog.com
思い描いたイメージに結構近いものが作れたと感じましたので、どこかで誰かの参考になるかもと願い、ソースコードを公開してみたいと思います。目盛りの描画位置などは試行錯誤で調整した値を用いているなど、あまり美しいコードではありませんが…。
こちらはM5StackのDHT12サンプルスケッチを下敷きにしているので、まずはこれを開きます。
そしてサンプルスケッチの「DHT12」タブのコードを、以下のものに書き換えればOKです。
#include <M5Stack.h> #include "DHT12.h" #include <Wire.h> DHT12 dht12; //W、Hは画面の幅,高さ。GW、GHはグラフ領域の幅、高さ。 #define W 320 #define H 240 #define GW 280 #define GH 180 //グラフはスプライトを用いて描画する。初期化 TFT_eSprite graph = TFT_eSprite(&M5.Lcd); void setup() { M5.begin(); Wire.begin(); M5.Lcd.fillScreen(TFT_BLACK); //グラフ用スプライトの生成。setScrollRect関数を使用しない場合、 //スプライト全体がスクロール対象となる graph.setColorDepth(8); graph.createSprite(GW, GH + 1); graph.fillSprite(TFT_BLACK); } void loop() { //DHT12から温度、湿度の値を取得。 float temp = dht12.readTemperature(); float humid = dht12.readHumidity(); //グラフ用スプライトの配置、1ピクセルずつスクロールさせていく graph.pushSprite((W - GW)/2 - 1, 15); graph.scroll(-1, 0); //目盛り線の描画(1ピクセルのスクロール → 1ピクセル描画、の繰り返しで線になる) //y軸方向に10分割する for(int y = 0; y <= GH; y += GH/10) graph.drawPixel(GW-1, y, TFT_DARKGREEN); //温度用の目盛り。室温を想定して範囲は-10〜40'Cとし、目盛り線と合うように調整。 M5.Lcd.setTextColor(TFT_YELLOW); M5.Lcd.setTextSize(1); M5.Lcd.setCursor(0, 0); M5.Lcd.printf("Temp"); char tempScale[6][4] = {" 40", " 30", " 20", " 10", " 0", "-10"}; for(int i = 0; i < 6; i++){ M5.Lcd.setCursor(0, 12 + i * GH/10 * 2); M5.Lcd.printf("%s", tempScale[i]); } //湿度用の目盛り。範囲は0〜100 %とし、目盛り線と合うように調整。 M5.Lcd.setTextColor(TFT_BLUE); M5.Lcd.setTextSize(1); M5.Lcd.setCursor(W - 30, 0); M5.Lcd.printf("Humid"); char humidScale[6][4] = {"100", "80", "60", "40", "20", "0"}; for(int i = 0; i < 6; i++){ M5.Lcd.setCursor(GW + (W - GW)/2 + 1, 12 + i * GH/10 * 2); M5.Lcd.printf("%s", humidScale[i]); } //温度のグラフを描画。温度が目盛り範囲(-10〜40'C)から外れる場合は //強引に範囲内に収める(そんな環境で使うことは無いだろうけれど) if(temp > 40.0) temp = 40.0; if(temp < -10.0) temp = -10.0; float tc = -18.0 * (temp - 40.0) / 5.0; //実値をグラフ上の座標に変換 graph.drawFastVLine(GW - 1, (int)tc, 2, TFT_YELLOW); //湿度のグラフを描画。こちらは目盛り範囲(0〜100 %)から外れることはないはず float hc = -9.0 * (humid - 100.0) / 5.0; //実値をグラフ上の座標に変換 graph.drawFastVLine(GW-1, (int)hc, 2, TFT_BLUE); //グラフの真下に温度、湿度の実値を文字表示する M5.Lcd.setTextColor(TFT_WHITE, TFT_BLACK); //背景色を設定して、直前の表示が残らないようにする M5.Lcd.setTextSize(2); M5.Lcd.setCursor((W - GW)/2 - 1, H - 38); M5.Lcd.printf("Temperature('C):%5.1f", temp); M5.Lcd.setCursor((W - GW)/2 - 1, H - 19); M5.Lcd.printf("Humidity(%%): %5.1f", humid); //湿度の数値のx座標が、温度の数値と並ぶように調節 delay(50); }