
🔧 この装置でできること
機能 説明
✅ 温度測定 DS18B20センサーで周囲の温度を測定します。
✅ 異常通知 設定温度を超えたら Discord に通知が飛びます。
✅ データ記録 Ambient に自動的に温度を送信して記録されます。
✅ 省電力動作 測定と送信が終わると自動でスリープ状態になります。
✅ スマホ設定 スマホからWi-Fi接続・Discord通知・測定時間などが設定できます。
📱 スマホでの設定方法(初心者向けステップ)
ESP32の設定モードを起動する
ESP32に付いている「設定ボタン(GPIO10)」を押したまま電源を入れます。
赤色LEDが点灯したら「設定モード」になった合図です。
スマホでESP32に接続
スマホのWi-Fi設定を開き、「ESP32_Config」というWi-Fiに接続します(パスワード不要)。
接続するとインターネットは切れますが問題ありません。
ブラウザを開く
SafariやChromeを開いて、以下のアドレスを入力:
http://192.168.4.1
設定ページが表示されます
スマホ向けに見やすくデザインされた画面が出てきます。
各項目を入力・変更できます:
項目 | 説明 |
個体ID | 識別用の名前(例:センサーA) |
異常温度しきい値(℃) | 超えたらDiscord通知される温度 |
測定間隔(秒) | 何秒ごとに測定・送信を繰り返すか |
Wi-Fi SSID | ご家庭のWi-Fi名 |
Wi-Fiパスワード | パスワード(非表示入力) |
Ambient UserKey | Ambientのキー(クラウド送信用) |
Discord Webhook | Discordの通知URL(送信先) |
Discord送信を有効にする | 通知を送るかON/OFF |

[保存] ボタンを押す
入力後、ページ下部の「保存」をタップ。
スマホ画面に「保存しました。再起動します...」と大きく表示されます。
その後ESP32は自動的に再起動し、測定運用が開始されます。
🧠 ESP32の内部の動作流れ(概要)
起動直後、ボタンが押されていたら設定モードへ(LED点灯)。
そうでなければ:
センサーに電源ON → 温度測定 → 電源OFF
異常温度や読み取り失敗ならDiscordに通知(有効な場合のみ)
Wi-Fi接続後、Ambientに温度を送信
すべて終わったらDeepSleepで省電力モードへ移行
💡 ヒント・注意事項
Ambient UserKey や Discord Webhook は最初に一度取得・設定すれば以後は不要。
測定間隔を短くしすぎると電池が早く切れます。5分(300秒)以上が推奨です。
Discord通知をOFFにしたい場合は、チェックボックスのチェックを外すだけ。
🛠️ 活用シーン例
農業現場でのハウス内温度モニタリング
倉庫の温度監視
サーバールームの簡易温度アラートシステム
メールではなくDiscordでリアルタイム通知したい用途
#include <WiFi.h> #include <WebServer.h> #include <Preferences.h> #include <OneWire.h> #include <DallasTemperature.h> #include <Discord_WebHook.h> #include <Ambient.h> #include <esp_sleep.h> #define CONFIG_BUTTON_PIN 10 #define LED_PIN 5 Preferences preferences; WebServer server(80); Discord_Webhook discord; Ambient ambient; WiFiClient client; const int SENSOR_POWER_PIN = 20; const int ONE_WIRE_PIN = 4; OneWire oneWire(ONE_WIRE_PIN); DallasTemperature sensors(&oneWire); String kotaiID; float thresholdTemp; unsigned long sleepSec; String WIFI_SSID; String WIFI_PASSWORD; String ambientUserKey; String DISCORD_WEBHOOK; bool ENABLE_DISCORD = true; void handleRoot() { String html = "<!DOCTYPE html><html><head><meta charset='UTF-8'>"; html += "<meta name='viewport' content='width=device-width, initial-scale=1'>"; html += "<style>"; html += "body, form, label, input, h2 { font-family: sans-serif; }"; html += "body { padding: 20px; background-color: #f9f9f9; }"; html += "form { background: #fff; padding: 20px; border-radius: 10px; box-shadow: 0 0 10px rgba(0,0,0,0.1); max-width: 600px; }"; html += ".row { display: flex; align-items: center; margin-bottom: 12px; }"; html += ".row label { width: 200px; font-weight: bold; }"; html += ".row input[type='text'], .row input[type='number'], .row input[type='password'] { width: 200px; padding: 5px; }"; html += "#discord { width: 100%; font-size: 12px; font-family: monospace; }"; html += "</style>"; html += "</head><body>"; html += "<h2>ESP32温度センサー設定</h2><form method='POST' action='/save'>"; html += "<div class='row'><label>個体ID</label><input type='text' name='id' value='" + kotaiID + "'></div>"; html += "<div class='row'><label>異常温度閾値(℃)</label><input type='number' step='0.1' name='threshold' value='" + String(thresholdTemp) + "'></div>"; html += "<div class='row'><label>測定間隔(秒)</label><input type='number' name='sleep' value='" + String(sleepSec) + "'></div>"; html += "<div class='row'><label>WiFi SSID</label><input type='text' name='ssid' value='" + WIFI_SSID + "'></div>"; html += "<div class='row'><label>WiFi パスワード</label><input type='password' name='pass' value='" + WIFI_PASSWORD + "'></div>"; html += "<div class='row'><label>Ambient UserKey</label><input type='text' name='ambient' value='" + ambientUserKey + "'></div>"; html += "<div class='row'><label>Discord Webhook</label></div>"; html += "<div class='row'><input type='text' id='discord' name='discord' value='" + DISCORD_WEBHOOK + "'></div>"; html += "<label style='margin-top:15px;'>Discord送信を有効にする</label><br>"; html += "<input type='checkbox' name='enable_discord' value='1'"; if (ENABLE_DISCORD) html += " checked"; html += "> 有効"; html += "<br><br><input type='submit' value='保存'>"; html += "</form></body></html>"; server.send(200, "text/html", html); } void handleSave() { kotaiID = server.arg("id"); thresholdTemp = server.arg("threshold").toFloat(); sleepSec = server.arg("sleep").toInt(); WIFI_SSID = server.arg("ssid"); WIFI_PASSWORD = server.arg("pass"); ambientUserKey = server.arg("ambient"); DISCORD_WEBHOOK = server.arg("discord"); ENABLE_DISCORD = server.hasArg("enable_discord"); preferences.begin("config", false); preferences.putString("kotaiID", kotaiID); preferences.putFloat("threshold", thresholdTemp); preferences.putULong("sleep", sleepSec); preferences.putString("ssid", WIFI_SSID); preferences.putString("pass", WIFI_PASSWORD); preferences.putString("ambient", ambientUserKey); preferences.putString("discord", DISCORD_WEBHOOK); preferences.putBool("enable_discord", ENABLE_DISCORD); preferences.end(); server.send(200, "text/html; charset=UTF-8", "<!DOCTYPE html><html><head><meta charset='UTF-8'><meta name='viewport' content='width=device-width, initial-scale=1'><style>body{font-family:sans-serif;text-align:center;padding:40px;font-size:1.5em;}</style></head><body>保存しました。<br>再起動します...</body></html>"); delay(1000); ESP.restart(); } void startConfigPortal() { digitalWrite(LED_PIN, HIGH); WiFi.softAP("ESP32_Config"); IPAddress IP = WiFi.softAPIP(); server.on("/", handleRoot); server.on("/save", HTTP_POST, handleSave); server.begin(); Serial.print("設定モード開始: "); Serial.println(IP); while (true) { server.handleClient(); delay(10); } } void loadSettings() { preferences.begin("config", true); kotaiID = preferences.getString("kotaiID", ""); if (kotaiID == "") kotaiID = "1"; DISCORD_WEBHOOK = preferences.getString("discord", ""); if (DISCORD_WEBHOOK == "") DISCORD_WEBHOOK = "https://discord.com/api/webhooks/YOURWEBHOOK"; WIFI_SSID = preferences.getString("ssid", ""); if (WIFI_SSID == "") WIFI_SSID = "YOURSSID"; WIFI_PASSWORD = preferences.getString("pass", ""); if (WIFI_PASSWORD == "") WIFI_PASSWORD = "YOURPASSWORD"; ambientUserKey = preferences.getString("ambient", ""); if (ambientUserKey == "") ambientUserKey = "YOURUSERKEY"; sleepSec = preferences.getULong("sleep", 0); if (sleepSec == 0) sleepSec = 300; thresholdTemp = preferences.getFloat("threshold", -999.0); if (thresholdTemp < -100.0) thresholdTemp = 28.0; ENABLE_DISCORD = preferences.getBool("enable_discord", true); preferences.end(); } void setup() { pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); Serial.begin(115200); loadSettings(); pinMode(CONFIG_BUTTON_PIN, INPUT_PULLUP); pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); pinMode(SENSOR_POWER_PIN, OUTPUT); digitalWrite(SENSOR_POWER_PIN, LOW); pinMode(ONE_WIRE_PIN, INPUT_PULLUP); delay(100); if (digitalRead(CONFIG_BUTTON_PIN) == LOW) { Serial.println("設定ボタンが押されたため設定モードへ"); startConfigPortal(); } digitalWrite(SENSOR_POWER_PIN, HIGH); delay(100); sensors.begin(); sensors.requestTemperatures(); delay(750); float temperature = sensors.getTempCByIndex(0); Serial.println(String(temperature) + "℃"); digitalWrite(SENSOR_POWER_PIN, LOW); bool sendToDiscord = false; String msg = ""; if (temperature == -127.0) { msg = "⚠️ DS18B20 read failed. Temp: -127.0°C. Check sensor!"; sendToDiscord = true; } else if (temperature > thresholdTemp) { msg = "🔥 異常温度: " + String(temperature) + "°C (ID:" + kotaiID + ")"; sendToDiscord = true; } Serial.print("Wi-Fi接続中..."); WiFi.begin(WIFI_SSID.c_str(), WIFI_PASSWORD.c_str()); unsigned long t = millis(); while (WiFi.status() != WL_CONNECTED && millis() - t < 10000) { delay(100); } if (WiFi.status() == WL_CONNECTED) { Serial.println("接続成功!"); if (ENABLE_DISCORD && sendToDiscord && DISCORD_WEBHOOK.length() > 0) { Serial.println("Discordへ送信: " + msg); discord.begin(DISCORD_WEBHOOK); discord.send(msg); } else { Serial.println("Discord送信なし(無効または条件不一致)"); } if (ambientUserKey.length() > 0) { char devKey[32], writeKey[20]; uint8_t mac[6]; esp_read_mac(mac, ESP_MAC_WIFI_STA); sprintf(devKey, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); //Serial.printf("Device MAC (devKey): %s\r\n", devKey); unsigned int channelId; // Ambientのチャンネル情報を取得 if (!ambient.getchannel(ambientUserKey.c_str(), devKey, channelId, writeKey, sizeof(writeKey), &client)) { Serial.printf("Ambient: チャンネル情報が取得できませんでした。デバイスキー (%s) を登録してください。\r\n", devKey); while (true) { delay(1000); } } for (int i = 0; i < sizeof(writeKey); i++) { if (writeKey[i] == '}' || writeKey[i] == '"') writeKey[i] = '\0'; } ambient.begin(channelId, writeKey, &client); ambient.set(1, temperature); if (ambient.send()) { Serial.println("Ambient送信成功"); } else { Serial.println("Ambient送信失敗"); } } else { Serial.println("Ambient送信なし(UserKey未設定)"); } } else { Serial.println("Wi-Fi接続失敗"); } WiFi.disconnect(true); WiFi.mode(WIFI_OFF); digitalWrite(LED_PIN, LOW); // 念のため明示的に消灯 esp_sleep_enable_timer_wakeup(sleepSec * 1000000ULL); esp_deep_sleep_start(); } void loop() {}
コメント
この記事へのトラックバックはありません。
この記事へのコメントはありません。