ESP32C3でDS18B 20温度センサーを使用して、AmbientとDiscordにデーターを送信する

Line Notifyのサービス終了に伴う代替手段としてのDiscord導入について

Line Notifyは、IoTデバイスや各種サービスから通知を受け取る手軽な手段として利用されてきました。しかし、サービス終了により、新たな通知手段の確立が求められる状況となりました。この状況に対応するため、本コードでは、Line Notifyの代替サービスとしてDiscordのWebHook機能を利用し、通知メッセージを送信する仕組みを実装しました。


Discordを選んだ理由

  1. 無料で利用可能
    Discordは基本的な利用が無料で提供されており、通知機能を含む多くの機能をコストゼロで利用できます。
  2. WebHook機能の柔軟性
    DiscordのWebHook機能は、HTTPリクエストを通じて簡単にメッセージを送信できるため、既存のIoTデバイスやプログラムとの統合が容易です。
  3. リッチな通知
    Discordでは、単なるテキストメッセージだけでなく、埋め込みメッセージやファイル添付も可能なため、通知内容を柔軟に拡張できます。
  4. 信頼性とサポート
    世界中で広く利用されているプラットフォームであるため、安定した通知サービスとして期待できます。

本コードの概要

このコードでは、温度センサー(DS18B20)を使用して取得したデータをDiscordのWebHookを通じて通知します。また、データはAmbientにも送信されるため、履歴管理や可視化も可能です。

具体的な機能は以下の通りです:

  1. 温度データの取得
    • DS18B20センサーを使用して温度データを読み取ります。
    • センサーの省電力運用のため、必要なタイミングでセンサーの電源をオン・オフします。
  2. 異常値検知
    • 温度が特定の閾値(例: 28°C以上またはエラー値)を超える場合に、通知を送信します。
  3. 通知の送信
    • DiscordのWebHookを使用して、温度データやアラートをテキストメッセージとして送信します。
    • 通知内容には、デバイスIDや具体的な測定値が含まれます。
  4. 省電力設計
    • 温度測定後、デバイスを一定時間ディープスリープ状態にすることで、電力消費を最小限に抑えます。

DiscordのWebHook機能の仕組み

DiscordのWebHookは、特定のチャネルにデータを投稿するためのエンドポイント(URL)を提供します。このエンドポイントに対してHTTPリクエストを送信するだけで、メッセージを簡単に投稿できます。本コードでは、この仕組みを利用して、温度センサーから取得したデータや警告メッセージをリアルタイムで送信します。


実装のポイント

  1. WebHookの設定
    • DiscordでWebHookを作成し、エンドポイントURLを取得します。このURLは本コード内でDISCORD_WEBHOOKとして指定します。
  2. センサーの省電力制御
    • センサーの電源を操作するピンを設定し、必要なときだけセンサーを有効化します。
  3. エラーハンドリング
    • センサーのデータ読み取りが失敗した場合や、通信が失敗した場合にも、適切にエラーメッセージを送信します。
  4. ディープスリープの活用
    • デバイスを測定後にスリープさせることで、バッテリー駆動時の運用効率を向上させています。

動作概要
このプログラムは、DS18B20温度センサーを使用して温度データを読み取り、それをDiscordとAmbientに送信します。電源効率のため、センサーの電源は必要な時のみオンにし、使用後にオフにします。また、デバイスはデータ送信後にディープスリープ状態に入り、5分後に再起動します。

/*
  DS18B20センサーの値をDiscordおよびAmbientにWebHookを使用して送信します。
  OneWire、DallasTemperature、Ambientライブラリが必要です。
*/

#include <OneWire.h>
#include <DallasTemperature.h>
#include <Discord_WebHook.h>
#include <Ambient.h>
#include <WiFiClient.h>
#include <esp_wifi.h>
#include <esp_sleep.h>

Discord_Webhook discord;
Ambient ambient;
WiFiClient client;

// 個体ごとのID
const char* kotaiID = "1";

// Discord Webhook URL
String DISCORD_WEBHOOK = "https://discord.com/api/webhooks/";

// **電源制御ピン (XIAO ESP32C3: GPIO20 = D7)**
const int SENSOR_POWER_PIN = 20;

// **DS18B20 のデータ線 (XIAO ESP32C3: GPIO4 = D2)**
const int ONE_WIRE_PIN = 4;

// Deep Sleep 時間(5分)
const uint64_t SLEEP_DURATION_US = 5 * 60 * 1000000ULL;

// OneWire & DS18B20
OneWire oneWire(ONE_WIRE_PIN);
DallasTemperature sensors(&oneWire);

// WiFi設定
const char* WIFI_SSID = "SSID";
const char* WIFI_PASSWORD = "PASS";

// Ambient設定
const char* userKey = "ユーザーキー";
char devKey[20];
unsigned int channelId;
char writeKey[20];

void setup() {
    Serial.begin(115200);

    // **GPIO 初期化**
    pinMode(SENSOR_POWER_PIN, OUTPUT);
    digitalWrite(SENSOR_POWER_PIN, LOW);
    pinMode(ONE_WIRE_PIN, INPUT_PULLUP);

    // **WiFiはDeep Sleep後オフの状態に**
    WiFi.mode(WIFI_OFF);
    esp_wifi_stop();

    // **MACアドレス取得**
    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]);

    // **センサーの電源ON**
    digitalWrite(SENSOR_POWER_PIN, HIGH);
    delay(500);
    sensors.begin();

    // **温度測定(リトライ付き)**
    float temperature = -127.0;
    int retries = 3;
    for (int i = 0; i < retries && temperature == -127.0; i++) {
        sensors.requestTemperatures();
        delay(1000);
        temperature = sensors.getTempCByIndex(0);
    }
    
    Serial.print("Temperature: ");
    Serial.println(temperature);
    
    // **Discord 送信判定**
    bool sendToDiscord = false;
    String discordMessage = "";

    if (temperature == -127.0) {
        discordMessage = "⚠️ DS18B20 read failed. Temp: -127.0°C. Check sensor connection!";
        sendToDiscord = true;
    } else if (temperature > 28.0) {
        discordMessage = "🔥  異常温度検出: " + String(temperature) + "°C. ID: " + String(kotaiID);
        sendToDiscord = true;
    }

    // **WiFi接続(温度が取得できた場合のみ)**
    WiFi.mode(WIFI_STA);
    WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
    unsigned long startAttemptTime = millis();
    while (WiFi.status() != WL_CONNECTED && millis() - startAttemptTime < 10000) {
        delay(100);
    }

    if (WiFi.status() == WL_CONNECTED) {
     // Serial.println("WiFi Connected, IP: " + WiFi.localIP().toString());
        // **Discord通知**
        if (sendToDiscord) {
            discord.begin(DISCORD_WEBHOOK);
            discord.send(discordMessage);
        }

        // **Ambient初期化**
        if (!ambient.getchannel(userKey, devKey, channelId, writeKey, sizeof(writeKey), &client)) {
            Serial.println("Failed to get Ambient channel!");
        } else {
            // **writeKey の終端を正しく設定(`}` や `"` が余分についていた場合、削除)**
            for (int i = 0; i < sizeof(writeKey); i++) {
                if (writeKey[i] == '}' || writeKey[i] == '"') {
                    writeKey[i] = '\0';
                    break;
                }
            }
            
     // Serial.printf("channelId: %d, writeKey: %s\r\n", channelId, writeKey);
     // Serial.print("Corrected WriteKey: ");
     // Serial.println(writeKey);
        
            // **Ambientへ温度送信**
            ambient.begin(channelId, writeKey, &client);
            ambient.set(1, temperature);
         // Serial.print("Sending to Ambient - d1: ");

            if (ambient.send()) {
                Serial.println("Ambient send OK");
                delay(2000);  // WiFi切断前に2秒待機(確実に送信完了するため)
            } else {
                Serial.println("Failed to send data to Ambient");
            }
        }
    } else {
        Serial.println("WiFi connection failed!");
    }

    // **WiFi OFF**
    WiFi.disconnect(true);
    WiFi.mode(WIFI_OFF);
    esp_wifi_stop();

    // **センサー電源OFF**
    digitalWrite(SENSOR_POWER_PIN, LOW);

    // **UART OFF(省電力化)**
    Serial.end();

    // **Deep Sleep**
    esp_sleep_enable_timer_wakeup(SLEEP_DURATION_US);
    esp_deep_sleep_start();
}

void loop() {
    // Deep Sleep後は setup() が再実行されるため、loop() は不要
}
コードの詳細な説明:
  1. ライブラリのインクルード
    以下のライブラリを使用しています:
    • OneWire: センサーとの通信をサポート。
    • DallasTemperature: DS18B20センサーの温度読み取りに使用。
    • Discord_WebHook: Discord WebHookでデータを送信。
    • Ambient: Ambientプラットフォームにデータを送信。
    • WiFiClient: Wi-Fi通信のため。
  2. 設定項目
    • kotaiID: デバイスの個体識別用ID。
    • DISCORD_WEBHOOK: Discord WebHookのURL
    • SENSOR_POWER_PIN: センサーの電源制御ピン(GPIO7)。
    • ONE_WIRE_PIN: OneWire通信用ピン(GPIO6)。
    • userKey: Ambientユーザキー。

📌 処理の流れ
1️⃣ 初期設定
SENSOR_POWER_PIN (GPIO7) を 温度センサーの電源制御用 に設定し、最初は OFF にする
ONE_WIRE_PIN (GPIO6) を DS18B20 のデータ通信ピン として設定
WiFi を OFF にして、無駄な電力を消費しないようにする

2️⃣ 温度測定
センサーの電源を ON (digitalWrite(SENSOR_POWER_PIN, HIGH))
750ms 以上の待機時間 を確保し、センサーの起動を待つ
温度を取得 (sensors.getTempCByIndex(0))
3回までリトライ可能(最初の測定で失敗することがあるため)

3️⃣ Discord への通知
センサーが測定に失敗した(-127.0℃)場合
Discord に「⚠️ DS18B20 read failed.」を通知
温度が 28.0℃ 以上の場合
Discord に「🔥 異常温度検出: 〇〇°C.」を通知

4️⃣ WiFi接続
Discord へ通知または Ambient へ送信が必要な場合のみ WiFi を ON にして接続
WiFi 接続を最大 10秒間待機(失敗時はスキップ)

5️⃣ Ambient へ温度データを送信
Ambient に接続し、温度データを送信
WiFi 切断前に 2秒待機して、送信を確実に完了させる

6️⃣ 電力を節約するための処理
WiFi を OFF(WiFi.disconnect(true); & esp_wifi_stop();)
温度センサーの電源を OFF(digitalWrite(SENSOR_POWER_PIN, LOW);)
シリアル通信(UART)を OFF(Serial.end();)
ESP32-C3 を Deep Sleep(スリープモード)にする(esp_deep_sleep_start();)
5分後に再起動し、再び温度測定を開始

📌 このコードの特徴
✅ バッテリー駆動向けに省電力最適化 
✅ 温度異常時のみ Discord に通知し、無駄なアラートを削減 
✅ WiFi の使用時間を最小限にし、不要な接続を防ぐ 
✅ Deep Sleep を活用して動作間隔を 5分ごとに設定 
✅ 温度測定のリトライ処理を実装し、信頼性向上

専用基板

DS18B20を2本実装可能 その他BME280搭載 温湿度・気圧センサモジュール用ピン、バッテリー電圧監視用ピンを取り出した。

Discordの画面

今後の展望

DiscordのWebHook機能を使用した通知システムは柔軟性が高いため、将来的には以下のような拡張も可能です:

  • 複数のデータフィールドやセンサーを統合して、より詳細な通知を実現。
  • データの可視化や分析のために、他のクラウドサービスと連携。
  • 通知内容の多言語化やカスタマイズ。

Line Notifyからの移行に伴い、今回のコードは代替手段として適切な機能を提供するものです。Discordを活用することで、今後も信頼性の高い通知システムを維持することが期待されます。

  • このエントリーをはてなブックマークに追加
  • follow us in feedly

この記事の著者

momo

1966年訓子府町生まれの訓子府育ち。玉葱や米、メロンを栽培する農家です。一眼レフを本格的に始めたのは2005年。仕事の時でもいつでもカメラを持ち歩く自称農場カメラマン。普段の生活を撮るのが主で、その他ストロボを使っての商品撮影、スタジオ撮影も。愛好家グループで年1回写真展を行っている。農機具の改造や作製、電子工作など、モノづくりが大好きです。

この著者の最新の記事

関連記事

コメント

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

  1. この記事へのトラックバックはありません。

2025年3月
 12
3456789
10111213141516
17181920212223
24252627282930
31  

カテゴリー

ページ上部へ戻る