工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

ESP32で作るIoT環境モニター:温湿度・気圧・CO2をWebダッシュボードで可視化

部品と用品

ESP32開発ボード(DevKit V1等) 1
BME280 温湿度・気圧センサー 1
MH-Z19B CO2センサー(UART接続) 1
SSD1306 OLEDディスプレイ(128x64 I2C) 1
ブレッドボード・ジャンパーワイヤー 1式
USBケーブル・電源アダプター 1

必要な工具

このプロジェクトについて

ESP32のWiFi/Bluetooth機能と豊富なGPIOを活かし、室内環境を総合的にモニタリングするIoTデバイスを作ります。温度・湿度・気圧・CO2濃度を測定し、ローカルWebダッシュボードとOLEDディスプレイの両方でリアルタイム表示。さらにデータをクラウド(InfluxDB + Grafana、またはThingsBoard)に送信して長期トレンド分析も可能です。

センサー構成

アーキテクチャ

[センサー群] → [ESP32] → [OLED表示]
                    ↓
              [WiFi] → [Web Server (ポート80)]
                    ↓
              [HTTP/MQTT] → [クラウド: InfluxDB/Grafana 等]

Webダッシュボード機能

コード

メインスケッチ


#include <WiFi.h>
#include <WebServer.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <ArduinoJson.h>

// WiFi設定
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";

// センサー
Adafruit_BME280 bme;
#define MH_Z19_RX 16
#define MH_Z19_TX 17
HardwareSerial mhz19(2);

// OLED
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

// Webサーバー
WebServer server(80);

// データ構造体
struct SensorData {
  float temperature;
  float humidity;
  float pressure;
  int co2;
  unsigned long timestamp;
} sensorData;

void setup() {
  Serial.begin(115200);
  
  // I2C初期化
  Wire.begin(21, 22);
  
  // BME280
  if (!bme.begin(0x76)) {
    Serial.println("BME280 not found!");
  }
  
  // MH-Z19B
  mhz19.begin(9600, SERIAL_8N1, MH_Z19_RX, MH_Z19_TX);
  
  // OLED
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println("OLED init failed!");
  }
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  
  // WiFi接続
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi connected: " + WiFi.localIP().toString());
  
  // Webサーバールート設定
  server.on("/", handleRoot);
  server.on("/api/data", handleAPI);
  server.begin();
  Serial.println("HTTP server started");
}

void loop() {
  server.handleClient();
  readSensors();
  updateDisplay();
  delay(2000);
}

void readSensors() {
  // BME280読み取り
  sensorData.temperature = bme.readTemperature();
  sensorData.humidity = bme.readHumidity();
  sensorData.pressure = bme.readPressure() / 100.0F; // hPa
  
  // MH-Z19B読み取り
  byte cmd[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
  mhz19.write(cmd, 9);
  delay(100);
  if (mhz19.available() >= 9) {
    byte response[9];
    mhz19.readBytes(response, 9);
    if (response[0] == 0xFF && response[1] == 0x86) {
      sensorData.co2 = (response[2] << 8) | response[3];
    }
  }
  
  sensorData.timestamp = millis();
}

void updateDisplay() {
  display.clearDisplay();
  display.setCursor(0, 0);
  display.printf("Temp: %.1f C", sensorData.temperature);
  display.setCursor(0, 16);
  display.printf("Hum: %.1f %%", sensorData.humidity);
  display.setCursor(0, 32);
  display.printf("Press: %.0f hPa", sensorData.pressure);
  display.setCursor(0, 48);
  display.printf("CO2: %d ppm", sensorData.co2);
  display.display();
}

void handleRoot() {
  String html = R"rawliteral(



  
  
  ESP32 Environment Monitor
  
  


  

🌡️ Environment Monitor

--
Temperature
°C
--
Humidity
%
--
Pressure
hPa
--
CO2
ppm
)rawliteral"; server.send(200, "text/html", html); } void handleAPI() { StaticJsonDocument<256> doc; doc["temperature"] = sensorData.temperature; doc["humidity"] = sensorData.humidity; doc["pressure"] = sensorData.pressure; doc["co2"] = sensorData.co2; doc["timestamp"] = sensorData.timestamp; String output; serializeJson(doc, output); server.send(200, "application/json", output); }

クラウド連携(InfluxDB + Grafana)

データを継続的に蓄積・可視化するには、以下の手順でセットアップ:

  1. DockerでInfluxDBとGrafanaを起動
  2. ESP32側でHTTP POSTまたはMQTTでInfluxDBに書き込み
  3. Grafanaでダッシュボード作成

// InfluxDB書き込み例(loop内で定期実行)
void sendToInfluxDB() {
  if (WiFi.status() != WL_CONNECTED) return;
  
  HTTPClient http;
  http.begin("https://YOUR_INFLUXDB:8086/api/v2/write?org=YOUR_ORG&bucket=YOUR_BUCKET&precision=ms");
  http.addHeader("Authorization", "Token YOUR_TOKEN");
  http.addHeader("Content-Type", "text/plain");
  
  String line = "environment,device=esp32_01 temperature=" + String(sensorData.temperature, 2) +
                ",humidity=" + String(sensorData.humidity, 2) +
                ",pressure=" + String(sensorData.pressure, 2) +
                ",co2=" + String(sensorData.co2);
  
  http.POST(line);
  http.end();
}

筐体・設置

トラブルシューティング

症状原因・対処
BME280が見つからないI2Cアドレス確認(0x76/0x77)、配線チェック、プルアップ抵抗
MH-Z19Bが0ppm固定TX/RX逆接続、電源電圧不足(5V必要)、プレヒート未完了(3分待機)
OLED真っ白I2Cアドレス(0x3C/0x3D)、リセットピン配線
WiFi接続失敗SSID/パスワード確認、2.4GHz帯のみ対応、電源容量不足

製造プロセス

  1. 家庭用の低コストワイヤレスセンサーネットワークを構築
  2. K30 CO2センサで室内空気質をリアルタイム監視する
  3. デジタル身長計の自作:Arduino Nanoとレーザー距離センサーで成長記録
  4. Arduinoでシンプルな障害物センサーを自作 – IR LEDとフォトダイオード入門
  5. DFRobot静電容量式指紋センサーをArduino/ESP8266で使う – 登録・認証・削除の完全ガイド
  6. Arduino Nanoで作るスマートな動体検知水鉄砲
  7. コンパクトなArduinoレーダーシステム – HC-SR04超音波センサー & 1.8インチST7735ディスプレイ搭載
  8. ArduinoセンサーデータをPHPMyAdmin経由でMySQLにアップロードする手順
  9. Arduino UNOで作る静電容量式タッチLEDスイッチ - 簡単DIY
  10. MKR GSM 1400で実現するリアルタイムIoT圧力監視:Arduino Cloud+Google Sheets連携
  11. Arduinoセンサー:種類、応用、実世界プロジェクト