
🔧 この装置でできること
機能 説明
✅ 温度測定 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() {}コメント
この記事へのトラックバックはありません。






この記事へのコメントはありません。