編集履歴一覧に戻る
misoのアイコン画像

miso が 2024年06月23日19時42分09秒 に編集

コメント無し

本文の変更

今回は、コンパクトで高性能なM5AtomS3と精密なENV4センサーを使って、自作の環境モニターを作る方法をご紹介します。温度、湿度、気圧を測定し、視覚的に分かりやすく表示する、実用的なガジェットを一緒に作りましょう。 ## プロジェクトの始まり このプロジェクトは、ある暑い夏の日の経験から生まれました。室内環境をより快適に保つために、正確な環境データが必要だと感じたのがきっかけです。 「環境をリアルタイムでモニターして、最適な状態を維持できれば...」 そんな思いから、M5AtomS3とENV4センサーを使ったプロジェクトを始めることにしました。 ## 必要な機材とソフトウェア - M5AtomS3 - ENV4センサー - Arduino IDE 2.3.2 - 必要なライブラリ(M5AtomS3, M5UnitENV) ## プログラムの Arduino IDEを使って、以下の機能を持つプログラムを作成します。 ```cpp #include "M5AtomS3.h" #include "M5UnitENV.h" #include <SPI.h> SHT4X sht4; BMP280 bmp; #define GRAPH_HEIGHT 85 #define GRAPH_WIDTH 128 #define GRAPH_LEFT 25 #define TEMP_MIN 0 #define TEMP_MAX 40 const uint32_t BACKGROUND_COLOR = M5.Lcd.color565(10, 20, 30); // Dark blue-gray const uint32_t TEXT_COLOR = M5.Lcd.color565(200, 200, 200); // Light gray const uint32_t GRID_COLOR = M5.Lcd.color565(40, 60, 80); // Lighter blue-gray const uint32_t TEMP_COLOR = M5.Lcd.color565(255, 100, 100); // Soft red void setup() { M5.begin(); // Initialize AtomS3 Serial.begin(115200); if (!sht4.begin(&Wire, SHT40_I2C_ADDR_44, 2, 1, 400000U)) { Serial.println("Couldn't find SHT4x"); while (1) delay(1); } sht4.setPrecision(SHT4X_HIGH_PRECISION); sht4.setHeater(SHT4X_NO_HEATER); if (!bmp.begin(&Wire, BMP280_I2C_ADDR, 2, 1, 400000U)) { Serial.println("Couldn't find BMP280"); while (1) delay(1); } bmp.setSampling(BMP280::MODE_NORMAL, BMP280::SAMPLING_X2, BMP280::SAMPLING_X16, BMP280::FILTER_X16, BMP280::STANDBY_MS_500); drawBackground(); } void drawBackground() { M5.Lcd.fillScreen(BACKGROUND_COLOR); // Draw vertical grid lines for (int x = GRAPH_LEFT; x < GRAPH_WIDTH; x += 25) { M5.Lcd.drawLine(x, 0, x, GRAPH_HEIGHT, GRID_COLOR); } // Draw horizontal grid lines and labels M5.Lcd.setTextSize(1); M5.Lcd.setTextColor(TEXT_COLOR); for (int i = 0; i <= 4; i++) { int y = map(i * 10, TEMP_MIN, TEMP_MAX, GRAPH_HEIGHT - 5, 5); M5.Lcd.drawLine(GRAPH_LEFT, y, GRAPH_WIDTH, y, GRID_COLOR); M5.Lcd.setCursor(2, y - 3); M5.Lcd.printf("%2d", i * 10); } } void drawGraph(float temperature) { static int x = GRAPH_LEFT; static int lastTempY = -1; int tempY = map(temperature, TEMP_MIN, TEMP_MAX, GRAPH_HEIGHT - 5, 5); if (x == GRAPH_LEFT) { drawBackground(); lastTempY = tempY; } if (lastTempY != -1) { M5.Lcd.drawLine(x-1, lastTempY, x, tempY, TEMP_COLOR); } lastTempY = tempY; x++; if (x >= GRAPH_WIDTH) x = GRAPH_LEFT; } float calculateDiscomfortIndex(float temperature, float humidity) { return 0.81 * temperature + 0.01 * humidity * (0.99 * temperature - 14.3) + 46.3; } void drawDiscomfortIcon(float di, int x, int y) { uint32_t color; if (di < 70) color = M5.Lcd.color565(0, 255, 0); // Green (Comfortable) else if (di < 75) color = M5.Lcd.color565(255, 255, 0); // Yellow (Slightly uncomfortable) else if (di < 80) color = M5.Lcd.color565(255, 128, 0); // Orange (Uncomfortable) else color = M5.Lcd.color565(255, 0, 0); // Red (Very uncomfortable) // Draw face outline M5.Lcd.drawRect(x, y, 16, 16, color); // Draw eyes M5.Lcd.drawPixel(x+4, y+4, color); M5.Lcd.drawPixel(x+11, y+4, color); // Draw mouth based on discomfort index if (di < 70) { // Very happy M5.Lcd.drawLine(x+4, y+11, x+11, y+11, color); M5.Lcd.drawPixel(x+3, y+10, color); M5.Lcd.drawPixel(x+12, y+10, color); M5.Lcd.drawPixel(x+4, y+12, color); M5.Lcd.drawPixel(x+11, y+12, color); } else if (di < 75) { // Happy M5.Lcd.drawLine(x+4, y+11, x+11, y+11, color); M5.Lcd.drawPixel(x+3, y+10, color); M5.Lcd.drawPixel(x+12, y+10, color); } else if (di < 80) { // Neutral M5.Lcd.drawLine(x+4, y+11, x+11, y+11, color); } else if (di < 85) { // Unhappy M5.Lcd.drawLine(x+4, y+12, x+11, y+12, color); M5.Lcd.drawPixel(x+3, y+13, color); M5.Lcd.drawPixel(x+12, y+13, color); } else { // Very unhappy M5.Lcd.drawLine(x+4, y+13, x+11, y+13, color); M5.Lcd.drawPixel(x+3, y+12, color); M5.Lcd.drawPixel(x+12, y+12, color); M5.Lcd.drawPixel(x+4, y+14, color); M5.Lcd.drawPixel(x+11, y+14, color); } // Display discomfort index value M5.Lcd.setTextSize(1); M5.Lcd.setTextColor(color); M5.Lcd.setCursor(x, y - 10); M5.Lcd.printf("%.0f", di); } void displayValues(float temperature, float humidity, float pressure) { M5.Lcd.fillRect(0, GRAPH_HEIGHT, GRAPH_WIDTH, 128 - GRAPH_HEIGHT, BACKGROUND_COLOR); M5.Lcd.setTextSize(1); M5.Lcd.setTextColor(TEXT_COLOR); M5.Lcd.setCursor(2, GRAPH_HEIGHT + 5); M5.Lcd.printf("Temp: %.1f C", temperature); M5.Lcd.setCursor(2, GRAPH_HEIGHT + 20); M5.Lcd.printf("Humi: %.1f %%", humidity); M5.Lcd.setCursor(2, GRAPH_HEIGHT + 35); M5.Lcd.printf("Pres: %.1f hPa", pressure); float di = calculateDiscomfortIndex(temperature, humidity); drawDiscomfortIcon(di, 100, GRAPH_HEIGHT + 15); } void loop() { M5.update(); // Update button state float temperature = 0; float humidity = 0; float pressure = 0; if (sht4.update()) { temperature = sht4.cTemp; humidity = sht4.humidity; drawGraph(temperature); } if (bmp.update()) { pressure = bmp.pressure / 100.0; // Convert Pa to hPa } displayValues(temperature, humidity, pressure); // Output data for serial plotter with custom labels Serial.print("Temp:"); Serial.print(temperature); Serial.print(","); Serial.print("Humi:"); Serial.print(humidity); Serial.print(","); Serial.print("Pres:"); Serial.println(pressure); delay(1000); } ``` ## グラフ表示機能 温度の変化を視覚的に捉えるため、リアルタイムでグラフを描画する機能を実装しました。 ```cpp void drawGraph(float temperature) { // ... (drawGraph関数の中身) } ``` この機能により、温度変化のトレンドが一目で分かります。 ## 不快指数の視覚化 数値だけでなく、直感的に理解できるよう、不快指数を表情アイコンで表現しました。 ```cpp void drawDiscomfortIcon(float di, int x, int y) { // ... (drawDiscomfortIcon関数の中身) } ``` これにより、環境の快適さが一目で判断できます。 ## データ分析のためのシリアル出力 ```cpp Serial.print("Temp:"); Serial.print(temperature); // ... (以下、シリアル出力の部分) ``` このコードで、Arduino上でデータをシリアルプロッタを使って可視化し、直感的な分析が可能になります。 ![キャプションを入力できます](https://camo.elchika.com/63f5d82b2da35998c280f80537362221aa06b519/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f32646132616164352d373663382d343562642d393434382d3262306431663736653138352f35396663313131362d633537632d343566332d396430302d613039626563373333313439/) ## 実際の動作 ![キャプションを入力できます](https://camo.elchika.com/274f64a24005626640d387bf167ced59775be3f4/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f32646132616164352d373663382d343562642d393434382d3262306431663736653138352f62323763303466302d393239302d343133342d616233622d386265636563363933373063/) 1. M5AtomS3の画面に温度のグラフがリアルタイムで描画されます。 2. 画面下部に現在の温度、湿度、気圧が表示されます。 3. 右下に不快指数を表すアイコンが表示されます。 4. PCに接続すると、詳細なデータがグラフで確認できます。

-

## 今後の改良点

+

## デスクトップアプリで温度等を表示できるようにしてみた

-

- Wi-Fi接続追加トフォンでも確認できるようにする - 長期的なデータ保存分析機能の実装 - 適範囲を外た際のアラート機能の追加

+

シリアルからの内容表示てくれるデクトップアプリも、作例として作ってみた。 ウスオバーする詳細表示されるにしてみた、不指数も表示してくる。

+

![キャプションを入力できます](https://camo.elchika.com/a04f18fa8b3a73f2d27748f08daf11157691e2e9/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f32646132616164352d373663382d343562642d393434382d3262306431663736653138352f36643936653337312d346233622d346538642d613865352d333032313836623130633230/) いちおう右クリックするとメニューが表示されて、自動接続設定や自動スタートアップを設定できるように作り込んであったりする。 ![キャプションを入力できます](https://camo.elchika.com/3055bcbd1fde9fb693df8fda4c11ddb669958430/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f32646132616164352d373663382d343562642d393434382d3262306431663736653138352f33313763396465622d636638372d343138642d383335312d623463396237316264616261/)

## まとめ M5AtomS3とENV4センサー、そして適切なプログラミングにより、私たちの生活をより快適にするツールを作ることができました。 このプロジェクトを通じて、IoTデバイスの可能性と、身の回りの環境をより良く理解することの重要性を実感しました。 皆さんも、自分専用の環境モニターを作ってみませんか?きっと、新しい気づきや発見があるはずです。 さあ、あなたのIoTプロジェクト、始めましょう!