DSM501A ホコリセンサーモジュール 3

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();
  }
}

センサーの回りで埃をたてると確かに数値が上がります。センサーは垂直にして空気が下方から上方に流すように設置するようです。

コメント