1.3インチTFT液晶ディスプレイモジュール(ICST7789) に変更してコンパクトにまとめてみました。
コードは AI におまかせですみません。

#include <Adafruit_GFX.h> // Adafruitのグラフィック基本ライブラリ
#include <Adafruit_ST7789.h> // ST7789用ライブラリ
#include <SPI.h>
// --- ピン配置の設定 ---
#define TFT_RST 1 // XIAO D1 (GPIO1)
#define TFT_DC 2 // XIAO D2 (GPIO2)
#define DSM501A_PIN 21 // XIAO D3 (GPIO3)
// ディスプレイ初期化(CSなしのため -1)
Adafruit_ST7789 tft = Adafruit_ST7789(-1, TFT_DC, TFT_RST);
// --- 測定用変数 ---
unsigned long duration;
unsigned long starttime;
unsigned long sampletime_ms = 30000; // 30秒ごとに集計
unsigned long lowpulseoccupancy = 0;
float ratio = 0;
float concentration = 0;
void setup() {
Serial.begin(115200);
pinMode(DSM501A_PIN, INPUT);
tft.init(240, 240, SPI_MODE3);
tft.setRotation(2);
tft.fillScreen(ST77XX_BLACK);
// --- 初回画面レイアウト構築 ---
// 上部ヘッダーバー
tft.fillRect(0, 0, 240, 38, tft.color565(40, 40, 50));
tft.drawFastHLine(0, 38, 240, ST77XX_CYAN); // 区切り線
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(2);
tft.setCursor(45, 12);
tft.print("AIR MONITOR");
// ウォーミングアップ中の案内表示
tft.setCursor(20, 110);
tft.setTextColor(ST77XX_ORANGE);
tft.print("Sensor Warming up");
tft.setCursor(50, 140);
tft.setTextSize(1);
tft.setTextColor(ST77XX_WHITE);
tft.print("Please wait for 30s...");
// 下部ステータスバー初期状態
tft.fillRect(0, 205, 240, 35, tft.color565(30, 30, 30));
starttime = millis();
}
void loop() {
duration = pulseIn(DSM501A_PIN, LOW);
lowpulseoccupancy = lowpulseoccupancy + duration;
if ((millis() - starttime) > sampletime_ms) {
ratio = lowpulseoccupancy / (sampletime_ms * 10.0);
concentration = 1.1 * pow(ratio, 3) - 3.8 * pow(ratio, 2) + 520 * ratio + 0.62;
// ステータスに応じたカラー判定
uint16_t statusColor;
String statusText;
if (concentration < 1000) {
statusColor = tft.color565(46, 204, 113); // エメラルドグリーン (Clean)
statusText = "CLEAN";
} else if (concentration < 3000) {
statusColor = tft.color565(241, 196, 15); // サンフラワーイエロー (Normal)
statusText = "NORMAL";
} else {
statusColor = tft.color565(231, 76, 60); // アルザリンレッド (DIRTY)
statusText = "DIRTY!";
}
// --- チラつき防止のため、文字背景色を指定して一気に上書き ---
// 1. メインの測定値 (大文字)
tft.setTextSize(6);
tft.setTextColor(ST77XX_WHITE, ST77XX_BLACK);
// 桁数に応じた簡易センタリング (4桁、5桁などで位置調整)
int displayCount = (int)concentration;
if (displayCount < 100) tft.setCursor(80, 80);
else if (displayCount < 1000) tft.setCursor(65, 80);
else tft.setCursor(50, 80);
// 位置ズレ防止のために数値表示部分の背景を一度クリア
tft.fillRect(0, 75, 240, 50, ST77XX_BLACK);
tft.print(displayCount);
// 2. 単位表示
tft.setTextSize(1);
tft.setTextColor(tft.color565(150, 150, 150), ST77XX_BLACK);
tft.setCursor(85, 140);
tft.print("particles / 0.01cf");
// 3. サブ情報 (Ratio %) の表示
tft.fillRect(40, 165, 160, 20, ST77XX_BLACK); // 前の数値をクリア
tft.setTextSize(2);
tft.setTextColor(tft.color565(200, 200, 200));
tft.setCursor(55, 165);
tft.print("Ratio: ");
tft.print(ratio, 1);
tft.print("%");
// 4. 下部ステータスバーの更新(ベタ塗り+文字)
tft.fillRect(0, 205, 240, 35, statusColor);
tft.setTextSize(2);
tft.setTextColor(ST77XX_WHITE);
// 文字数による簡易センタリング
if(statusText == "CLEAN") tft.setCursor(90, 215);
else if(statusText == "NORMAL") tft.setCursor(80, 215);
else tft.setCursor(85, 215);
tft.print(statusText);
// 次の計測へリセット
lowpulseoccupancy = 0;
starttime = millis();
}
}
センサーの回りで埃をたてると確かに数値が上がります。センサーは垂直にして空気が下方から上方に流すように設置するようです。


コメント