スマートホーム向け汎用トリガーを作る(ESP32使用):接点1入力版

📅
これまでESP32ボードを使う準備を進めてきました:
いよいよ今回はスマートホーム向け汎用トリガー(接点1入力版)の作成です!\(^o^)/


■ESP32ボードを用いてスマートホーム向け汎用トリガー(接点1入力版)を作る

以下は『汎用トリガー(接点1入力版)の作成と、IFTTTでの動作確認(ルームライトの点灯まで』です。

使用するESP32ボードは前回と同じ『DOIT ESP32 DEVKIT V1』です。
(PCとボードの接続方法、プログラム(スケッチ)の書き込み方法はこちら『ESP32モジュールボードを使ってみる - その1:『PCセットアップ(Lチカまで)』編』を参照ください。)

●汎用トリガー(接点1入力版)の作成

1. 回路 - 汎用トリガー(接点1入力版)

汎用性を出すために接点入力部分については、
  • 入力接点の極性対応(Lアクディブだけでなく、Hアクディブへの対応)
  • 入力電圧幅を増加
の2項目に対応できるようにして、これまでの準備編の回路から大幅に変更しています。
回路図(汎用トリガー(接点1入力版))

実装例(汎用トリガー(接点1入力版):動作確認用ブレッドボード)


1-1. 接点入力(入力ポート)

ESP32ボードのIOポート22(D22)をセンサーの接点の入力ポートとして使用します。

センサーの出力は以下の2種類のケースが考えられます。
  • センサーが検知した時の出力がLOW電圧(Lアクティブ)
  • センサーが検知した時の出力がHigh電圧(Hアクティブ)
Lアクティブの方が一般的な出力だと思いますが、ここで作成するトリガーは汎用性を重視して、Hアクティブ出力のセンサーにも対応できるようにしました。
(対応可能なセンサーの出力仕様(電圧等)は上記回路図、または下記仕様書(データシート)を参照ください。)


1-2. LED表示(出力ポート)

ESP32ボードのIOポート23(D23)とLED表示用の出力ポートとして使用します。

ポートとGNDの間にLEDと電流制限抵抗(220Ω)を接続します。
Arduinoの出力は3.3V、LED(緑)のVFは2V程度なので、LEDに流れる電流は(3.3V ー 2V) ÷ 220Ω = 6mAとなります(LEDの明るさを変えるにはこの抵抗値を調整してください)。


- 【参考】ボードの電源

ボードに元からついているmicro USBコネクタ(プログラム書き込み・シリアル通信用)を使います。
スケッチ(プログラム)書き込んだ後はこのmicro USBコネクタにUSB電源(USB充電器等)を接続して動作させることができます(動作確認済み。但し、この場合PCとは繋がっていないので当然ですがシリアル通信は機能しません)。


2. プログラム(スケッチ) - 汎用トリガー(接点1入力版)

参照元のプログラム(スケッチ)は経過時間のオーバーフローに対応していないので、その部分を追加しています(オーバーフローまでに約50日間かかるのでまだ動作確認はできていません😅)。

プログラムの動き:
  • LED表示:
    • 起動後、Wi-Fiに接続するまではLEDを点滅。接続が完了したらLEDは消灯。
    • 接点信号を検出したらLEDは点灯
  • シリアル通信:
    • 起動後、Wi-Fiに接続が完了したらその旨をPCに送信
    • 接点信号を検出したらその旨をPCに送信
  • Webhooks:
    • 接点信号を検出したら、Webhooksに任意のテキスト(プログラムで設定可能)を発行。
(以下のサンプルプログラム中の” WiFi_ssid ”と” Password ”は接続するWi-FiネットワークのSSIDとパスワードに書き換えてください。
また、" Private_key "はWebhooksのプライベートキーに書き換えてください(Webhooksについてとプライベートキーの取得方法は下で紹介しています)。

そしてWebhooksに発行するテキスト(イベント名)は任意に設定可能です。" button_pressed "を書き換えてください。)

ーーーサンプルプラグラム(汎用トリガー(接点1入力版))ーーー
 (" // ... "と" /* ... */ "の部分(黄色)はコメントです。)
#include <WiFi.h>

// Wi-Fi接続先のSSIDとパスワードの設定
const char *ssid     = "WiFi_ssid";   // WiFi_ssidには接続するWi-FiのSSIDを設定
const char *password = "Password";    // Passwordには接続するWiFiのパスワードを設定

// Webhooks(IFTTT)の設定
const char *host = "maker.ifttt.com";      // WebhooksのホストURL
const char *privateKey = "Private_key";  // Private_keyにはWebhooksのあなたのプライベートキーを設定

// ハード定義
const int buttonPin = 22;     // スイッチを割り当てるポート
const int ledPin = 23;        // LEDを割り当てるポート

// 変数定義
int buttonState;             // スイッチの今回状態
int lastButtonState = LOW;   // スイッチの前回状態

// 以下はタイマーとして使う変数で、代入するmillis()と同じ型の"unsigned long"で定義
unsigned long lastDebounceTime = 0;  // スイッチ出力が切り替わってからのタイマー
unsigned long debounceDelay = 50;    // スイッチの押下か? or ノイズか? の判定基準時間(50m秒)


void setup() {    // setup():スケッチ実行時の最初に1回だけ実行
  
  // IOポートのモード設定
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
  
  // シリアル通信のデータ転送レートの設定
  Serial.begin(115200);
  delay(10);
  
  // Wi-Fi接続の開始
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  
  // Wi-Fi接続確立中はLEDが点滅
  int led = HIGH;  
  while (WiFi.status() != WL_CONNECTED) {
    delay(200);
    digitalWrite(ledPin, led);
    led = !led;
  }
  
  // Wi-Fi接続が確立したらLEDは消灯
  digitalWrite(ledPin, LOW);
  
 // Wi-Fi接続が確立したらシリアル通信でIPアドレスを送信
  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}


void loop() {    // loop():スケッチ実行時にsetup()実行後、繰り返し実行
  
  // スイッチの現状の読み込み
  int reading = digitalRead(buttonPin);
  
  // millis()がオーバーフローしたらタイマーをリセット
  if (lastDebounceTime > millis()) {
    // タイマーのリセット
    lastDebounceTime = millis();
  }
  
  // 以下はスイッチの現状(reading)を監視して、信号がノイズか本当の
  // 押下かの判定
  
  // スイッチの現状(reading)が前回状態(lastButtonState)からすぐに
  // 変わってしまったらノイズと見なしてタイマーをリセットします
  if (reading != lastButtonState) {
    // タイマーのリセット
    lastDebounceTime = millis();
  }
  
  // スイッチの現状(reading)が判定基準時間以上前回状態(lastButtonState)
  // 変化がない場合はノイズではないと見なします
  if ((millis() - lastDebounceTime) > debounceDelay) {
    
    // スイッチの状態が今回状態(buttonState)から変化がある場合の処理
    if (reading != buttonState) {
      Serial.print("Button now ");
      Serial.println(HIGH == reading ? "HIGH" : "LOW");
      buttonState = reading;
      
      // スイッチの今回状態(buttonState)がLOWの場合はスイッチ
      // 押下とみなしてWebhooksを発行する
      if (buttonState == LOW) {
        send_event("button_pressed");  // 発行するテキスト(イベント名)は"button_pressed"
      }
    }
  }
  
  // スイッチの前回状態(lastButtonState)に現状(reading)を保存する
  lastButtonState = reading;
}


/**
 * サブルーチン:Webhooksにテキスト発行(send_event
 */
void send_event(const char *event) {
  
  // Webhooksにテキスト発行中はLEDを点灯
  digitalWrite(ledPin, HIGH);
  
  // Webhooksにテキスト発行中はシリアル通信で接続したホストを送信
  Serial.print("Connecting to ");
  Serial.println(host);
  
  // TCP接続を行うためにWiFiClientを使用する
  WiFiClient client;
  const int httpPort = 80;
  
  // 接続が失敗した場合にはその旨をシリアル通信で送信する
  if (!client.connect(host, httpPort)) {
    Serial.println("Connection failed");
    return;
  }
  
  // Webhooks発行用のURLを作成する
  String url = "/trigger/";
  url += event;
  url += "/with/key/";
  url += privateKey;
  
  Serial.print("Requesting URL: ");
  Serial.println(url);
  
  // 指定したURLにHTTP GETリクエストを送信する
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" + 
               "Connection: close\r\n\r\n");
  
  // サーバーからの全ての返信データをシリアル通信で送信する
  // サーバーからの全ての返信データを受信したら接続を終了(切断)する
  while(client.connected()) {
    if(client.available()) {
      String line = client.readStringUntil('\r');
      Serial.print(line);
    } else {
      // サーバーからのデータがまだあるかも知れないので少し待つ
      delay(50);
    };
  }
  
  // すべてが完了したらその旨をシリアル通信で送信する
  Serial.println();
  Serial.println("closing connection");
  
  client.stop();
  
  // シリアル通信が完了したらLEDを消灯する
  digitalWrite(ledPin, LOW);
}
ーーーサンプルプラグラム [おわり]ーーー

【参照サイト】CONNECT MAKER TO ANYTHING - IFTTT

※ このプログラムはヘッダファイル『 WiFi.h 』を使用していますが、この『 WiFi.h 』はArduino IDEに標準で用意されているようです。別途用意する必要はありませんでした。


- 【参考】Webhooksについて(プライベートキーの取得)

Webhooksはアプリではありません。IFTTTのトリガー用にIFTTTが提供しているサービスのひとつです。IFTTTに登録されていないアプリ・サービスをIFTTTのトリガーにするためには必要不可欠なサービスです。

上記のプログラム(スケッチ)でこのサービスを利用するにはプライベートキーの取得が必要になります。以下に紹介します(事前にIFTTTの登録が必要です)。

IFTTTのPC版ページにあるWebhooksのページを開き『Documentation』を選択します。

開いた画面の『Your key is:』に記載されているのがあなたのプライベートキーです。この部分を保存し、上記のプログラム(スケッチ)で使用します。

以上です。


3. 動作確認用のIFTTTアプレット

このアプレットは『Webhooksに発行されるテキスト(イベント名)"button_pressed"受け取ったら、Nature Remo経由でルームライトをONにする』という内容です。

トリガー(IF)にWebhooksを、アクション(THEN)にNature Remoを設定します。

トリガー(IF)としてはWebhooksを選択し、『Event Name』には上記プログラム(スケッチ)でWebhooksに発行されるテキスト(イベント名)『button_pressed』を入力します。

アクション(THEN)としてはNature Remoで"ライトを点灯する"(我が家の場合『ライト - 全灯』)を選択します。

以上でIFTTTアプレットの設定は完了で、全ての準備が完了です。


4. 動作確認 - 汎用トリガー(接点1入力版)

以下の動作確認はESP32ボードをPCとUSB接続した状態で行います(シリアル通信を確認するためです)。


4-1. Wi-Fi接続確立時

Wi-Fi接続確立中はLEDが点滅し、確率後は以下のメッセージがシリアル通信でPCに送信されます。


4-2. 接点信号検出時

接点信号検出時は、①LEDが点灯し、②以下のメッセージがシリアル通信でPCに送信され、③Webhooksにテキスト(今回の場合は"button_pressed")が発行されます。

発行されたWebhooksのテキスト(今回の場合は"button_pressed")に応じて④IFTTTのアプレットが実行されます(今回の場合、上記のアプレットの通りにNature Remo経由でライトが点灯します。)


●汎用トリガー(接点1入力版)の仕様書(データシート)

今回作成した汎用トリガーの仕様書を作ってみました。
汎用トリガー(接点1入力版)仕様書(データシート)


【おまけ情報】
上記回路図および仕様書において、Hアクティブの時のOFF電圧(LOW電圧)を0.2V以下と定義していますが、これは使用しているデジタルトランジスタのデータを杓子定規に引用しているだけで、現実的には1V程度以下でOFFすると思います。


『汎用トリガー(接点1入力版)』の説明は以上になります。
次は拡張編として入力数を増やした『汎用トリガー(接点多入力版)』にトライしますね。

【2021.9.2追記】
本記事の拡張編として入力数を増やした『スマートホーム向け汎用トリガーを作る(ESP32使用) - 接点多入力版』の記事をアップしました(3入力以上にも容易に対応可能です)。御覧ください。
リンク:『スマートホーム向け汎用トリガーを作る(ESP32使用) - 接点多入力版


●参照サイト

CONNECT MAKER TO ANYTHING - IFTTT(プログラム(スケッチ))

Arduino 日本語リファレンス




0 件のコメント: