今回は、コンパクトで高性能なM5AtomS3と精密なENV4センサーを使って、自作の環境モニターを作る方法をご紹介します。温度、湿度、気圧を測定し、視覚的に分かりやすく表示する、実用的なガジェットを一緒に作りましょう。
プロジェクトの始まり
このプロジェクトは、ある暑い夏の日の経験から生まれました。室内環境をより快適に保つために、正確な環境データが必要だと感じたのがきっかけです。
「環境をリアルタイムでモニターして、最適な状態を維持できれば...」
そんな思いから、M5AtomS3とENV4センサーを使ったプロジェクトを始めることにしました。
必要な機材とソフトウェア
- M5AtomS3
- ENV4センサー
- Arduino IDE 2.3.2
- 必要なライブラリ(M5AtomS3, M5UnitENV)
プログラムの
Arduino IDEを使って、以下の機能を持つプログラムを作成します。
#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);
}
グラフ表示機能
温度の変化を視覚的に捉えるため、リアルタイムでグラフを描画する機能を実装しました。
void drawGraph(float temperature) {
// ... (drawGraph関数の中身)
}
この機能により、温度変化のトレンドが一目で分かります。
不快指数の視覚化
数値だけでなく、直感的に理解できるよう、不快指数を表情アイコンで表現しました。
void drawDiscomfortIcon(float di, int x, int y) {
// ... (drawDiscomfortIcon関数の中身)
}
これにより、環境の快適さが一目で判断できます。
データ分析のためのシリアル出力
Serial.print("Temp:");
Serial.print(temperature);
// ... (以下、シリアル出力の部分)
このコードで、Arduino上でデータをシリアルプロッタを使って可視化し、直感的な分析が可能になります。
実際の動作
- M5AtomS3の画面に温度のグラフがリアルタイムで描画されます。
- 画面下部に現在の温度、湿度、気圧が表示されます。
- 右下に不快指数を表すアイコンが表示されます。
- PCに接続すると、詳細なデータがグラフで確認できます。
デスクトップアプリで温度等を表示できるようにしてみた
シリアルからの内容を表示してくれるデスクトップアプリも、作例として作ってみた。
マウスオーバーすると詳細表示されるにしてみた、不快指数も表示してくれる。
いちおう右クリックするとメニューが表示されて、自動接続設定や自動スタートアップを設定できるように作り込んであったりする。
まとめ
M5AtomS3とENV4センサー、そして適切なプログラミングにより、私たちの生活をより快適にするツールを作ることができました。
このプロジェクトを通じて、IoTデバイスの可能性と、身の回りの環境をより良く理解することの重要性を実感しました。
皆さんも、自分専用の環境モニターを作ってみませんか?きっと、新しい気づきや発見があるはずです。
さあ、あなたのIoTプロジェクト、始めましょう!
投稿者の人気記事
-
miso
さんが
2024/06/22
に
編集
をしました。
(メッセージ: 初版)
-
miso
さんが
2024/06/23
に
編集
をしました。
ログインしてコメントを投稿する