ドア開閉イベントをSlackへお知らせするセンサーを作る
公開日 更新日 2018/10/14
最近Raspberry Piを手に入れてから個人的にマイコンが流行っていて、WEBで情報収集をしています。
そのなかでもESP8266が安くて高機能という評判を耳にしました。
しばらくESP8266の実力を調べていると私もなにか作りたくなりましたので、ホームセキュリティの向上を目的として、ドア開閉センサーによるイベントをWiFiで通知させる装置を工作してみました。
その過程で色々つまずいていましたので、第2、第3の工作で忘れないように、この記事でメモを残したいと思います。
Contents
やりたいこと
作りたかった物のイメージは家に誰かいるかどうかを把握する事のできる装置です。
本人を特定することが出来ればなおいいのですが、今回はドアの明け閉めで検知可能な「誰かがドアを開けた」というイベントの監視で実現したいと思います。
理由は次のようになります。
- 工作初心者なので複雑な部品を組むには経験値が不足してた
- 設置する場所にコンセントがなく電池で動かす必要があるので、長期間動作させるために部品数を減らしたかった
やりたいことが大体見えてきたところで、次に関連するサイトの調査となり、次にまとめます。
将来腕が上がったら、作り直すというのもいいし、とりあえずはどんどん前に突き進んでいこうと思います。
参考サイト
海外のサイトが賑わっているのですが、自分だけのWiFi機器の自作がはやっているようです。
検索した中で、ドア開閉をお知らせするセンサーに役立つサイトをブックマーク。
- ESP8266を使って玄関ドアを開けたらSlackに通知するマシンを作って、実用できるか試す (kiyopikkoさん)
全く同じドア開閉のお知らせ機能をすでに実現されている方のサイトがありました! すごくためになりました。
私も同じことをやろうと思いますが、永久スリープ方式にするのはもちろんですが、フォトリフレクタではないもう少しシンプルな回路で省電力な方法が無いか考えてみました。 - ESP-WROOM-02とBME280 電池駆動で温度/湿度/気圧測定 (その1) (東京お気楽カメラさん)
乾電池の出力から3.3Vを作るための3端子レギュレータの選定がわかりやすくまとめられていました。
私の使い方も同じようにほぼスタンバイ状態が続くんだと思いますので、提案されている通りNJU7223F33とエネループ4本で作ることに決めました。 - ESP-WROOM-02 の配線 (hotchpotchさん)
ファームウェア書き込み時の配線方法を解説されてます。日本語で読める中ではまとまっていると思いました。
ただし書き込みモードの有効化とリセットの操作を別々にしてもよい場合は回路をシンプルに出来るとわかりましたので、最終的には↓次のサイトの配線を参考にしました。 - Upload sketch to the ESP8266 (ESP-07/ESP-12) using Arduino IDE
ESP-07という互換モジュールを使った回路の作り方についての説明ですが、搭載しているチップは同じESP8266なので手順もESP-WROOM-02と同じになっている模様です。
ポイントはいくつかのピンに抵抗を加えて電源またはGNDへ接続するという内容です。
ESP8266のオフィシャルサイトにあるPDFだと、このうち何箇所かは抵抗無く直結でよいとかプルダウン抵抗が要らないというような記載の差異が見られましたが、上記サイトに掲載されている通り抵抗を追加する方法で確認をとったので、このままこちらの回路を参考に進めたいと思います。 - HTTPS通信のサンプルコード
オフィシャルリポジトリに同梱されているHTTPS通信のためのサンプルコードです。
サンプルコードは検索すると大量にヒットするし、どのやり方でも間違いなく達成できるのですが、省電力を意識したコードは残念ながら引き当てられませんでした。
どこかに電力消費につながる実装箇所があって改善の余地がありそうでした。
そんな中、上記サイトのサンプルコードが一番きれいにまとまっていたので、こちらのコードを参考にしてより省電力になる(と思われる)コードを自作してみました。
ドア開閉をお知らせするセンサー装置の概要
ESP8266を活用した装置として、以下のような仕組みで実現させます。
- ドアが開いたらESP8266が起動してWiFi経由で通知を出す先として、今回はSlackへ通知を出す
- ESP8266が通信するWiFiは自宅ネットワークにある無線ルータであって、以降インターネットへつながるようになってる前提
- Slackへの通知にはSlackのREST APIであるIncoming Webhooksを使う
- Slackへの通知が完了したら、ESP8266は一番電力消費が低いスリープモードに入る(Deep Sleep Mode)
- タイマーで起動する必要は無く、次にドアが開くまでずっとスリープモードのまま
部品調達
Raspberry Piと違いマイコンは基本的には基板へ部品をはんだ付けするのが必須の作業です。
そのため、何はともあれやりたいことを実現するために必要となる部品を集めなければなりません。
今回の工作で必要となり購入した部品をリストアップしておきます。
ESP8266とシリアルコンバーター
まず入手しないといけないのがESP8266です。
このチップがWiFi通信ができるArduinoマイコンとして動作できる大事な部品です。
基本的には小さな基板にESP8266EXチップのほかにもいくつかの部品を搭載して、そのまま使うことが出来る状態になったモジュールで販売されてます。
単品で購入すると送料の方が馬鹿にならないので、まとめて買うか何か別の買い物のついでに送料無料にするための不足分として一緒に買っておくのがよいと思います。
ESP8266用のプログラムをパソコンで開発した後に、コンパイルしたファームウェアデータをESP8266へアップロードするために、USB経由で接続するシリアルコンバーターアダプターが必要になります。
このとき気をつけなければならないのは、ESP8266は3.3Vで接続してあげなければ壊れてしまうとのことで5V (なんか↓商品は表記が5.5VですがUSB接続なので5Vの間違いですね・・・)だけでなく、3.3Vにも対応した製品が必要になります。
↓こちらは中国発送で2週間ぐらいかかりますが送料無料です。
レギュレーターとコンデンサ
今回は電池稼働を目指すのですが、丁度よい3.3Vを提供できる電池はないのでレギュレーターで3.3Vを作ります。
レギュレーターは待機中にも電力を消費するので、Eneloopを最後まで使うためにレギュレーター消費分も加味し最小3.8Vを入力電圧にします。
単3乾電池を4本直列で接続した場合に最大6Vと大きすぎますが、最後まで使いきることができるので、私もこの構成で組んでみます。
またドアの開閉は1日に1人あたり数回なので、ほぼスタンバイ状態となるはずです。
参考サイトまんまですが、待機消費電力に着目して部品を選ぶ必要があり、↓にて期待する3.3Vを作れるようにします。
- 低損失CMOS三端子レギュレータ 3.3V500mA NJU7223F33
- 電解コンデンサー47μF35V85℃(ルビコンPK)
- 絶縁型ラジアルリード型積層セラミックコンデンサー0.1μF50V2.54mm 10個入
磁気接触スイッチ
参考サイトでは赤外線を使ってドアの開閉状態をチェックしてたのですが消費電力が高いようなので、省電力を達成できるやり方を考えてみたところ、この磁気接触の有無でスイッチできるセンサーに行き着きました。
中身は見えないのですが磁石とバネでスイッチしてるんだと想像してます。
なので自作するよりかは値段を見てこちらを購入することで解決。
この製品はケーブルが3本あって、そのうち2本を使い以下のどちらか真逆の使い方に両方対応しています。
どちらか片方だけできればよい場合は1本は不要なので切断してしまっても支障はないそうです。
- GND線(白)と、オープン時にON、クローズ時にOFFになるPOWER線(灰)の2つの線を使ったスイッチ
- GND線(白)と、オープン時にOFF、クローズ時にONになるPOWER線(茶)の2つの線を使ったスイッチ
どれがどの線になっているかはテスターを使って導通テストをすると挙動がわかって面白いのでお勧めです。
この製品、端子部分が接着剤で密閉されていて防水性が良さそうなので、ドア部分で雨天に負けず使用用途にピッタリな気がします。
抵抗
こちらも参考サイトまんまですが、各箇所に共通で10kΩの抵抗をいれます。
単にプルアップさせたいってことだと思いますのでピッタリ10kΩである必要はなさそうですが、抵抗セットが充実してるのでバンバン10kΩを使っていきます。
圧電スピーカー
WiFi接続して通知を出す装置なので、ネット越しに通知が来るかどうかで動作チェックができるのですが、ネットを介さずにすぐに反応を見れた方が状況が把握しやすいはずです。
特に気になるのは電池稼動ゆえに電池がなくなっていることにすぐ気づけるということなんだと思います。
作ったセンサーは出入りの邪魔にならないように天井付近に設置するので、光を出しても気づかれない可能性が大なので音で知らせた方が都合が良さそうです。
そして省電力って言う意味では、さらに音源用の追加のICは足したくないので圧電スピーカーですね。
圧電スピーカーの場合はGPIO直結でシンプルな命令で音を出すことが出来るため扱いが楽というのも大きいです。
※購入する前に気がついたのですが、もう使わなくなった古いパソコンに搭載されてたので、これを再利用して安く済ますことが出来ました。
電池ケース
単3乾電池4本を直列で接続するケースを準備します。
買っても安いのですが、もう使わなくなった子供のおもちゃを廃棄処分する前に、乾電池ケース部分をゲットしました。
分解するために多少は苦労しますが、そのまま捨て無くてよかった。
このアンパンマンのおもちゃ、ピカピカ光る部分はLEDがぎっしり詰まっているし、乾電池ケースに限らず部品を全部取っていたら1000円分ぐらい回収することが出来ました。
プラスチックと不燃物を仕分けるために必要な作業だし、これからは捨てる前に一仕事がんばったほうがよさそう。
回路図
ドアセンサーのための回路図をざっと描いてみました。
この回路図ではESP8266のRESETピンへ接続したドアセンサーがドアの開閉によってオンオフを切り替えることとなり、これでESP8266をリセットさせています。
なおESP8266では、RESETピンがLOWになるとリセット中というステータスとなり処理が停止、その後RESETピンがHIGHになると起動を開始するという動作です。
そしてプログラム実行中にスリープモードに入ることで処理が停止します。
まとめると、ESP8266には状態が、電源なし、電源オン(実行中)、スリープモード、リセット中、という4つありそうです。
この回路図ではハードウェアをくみ上げたあとでも、ファームウェアの更新が出来るようにGPIO0ピンをGND接続できるようにスイッチを用意してあります。
Arduino IDE開発環境のセットアップ
開発環境のセットアップはあまり悩まなくても出来ました。
ほぼWeb検索で得た解説サイトを見ながら進めればよかったと思いますが、ファームウェアのアップロードをするステップをかいつまんで並べておきます。
- Arduino IDEのWindows版をインストール
- ESP8266のためのArduino用ライブラリをインストール
- ESP8266用のボード設定
[ツール]メニューにある以下の項目を設定
ボード:”Generic ESP8266 Module”
Flash Mode: “DIO”
Flash Frequency: “40 MHz”
CPU Frequency: “80 MHz”
Flash Size: “512K (64K SPIFFS)”
Debug port: “Disabled”
Debug Level: “HTTPClient + SSL”
Reset Method: “ck”
Upload Speed: “115200”
書込装置: “USBasp” - ESP8266の接続はUSBシリアルコンバーターに次のように結線
[USBシリアルコンバーター側] RX — [ESP8266側] TX
[USBシリアルコンバーター側] TX — [ESP8266側] RX
[USBシリアルコンバーター側] GND — [ESP8266側] GND
[USBシリアルコンバーター側] 3V3 — [ESP8266側] 3V3 - GPIO0をGNDに落としながら(図のFirmManageボタンを押しながら)電源ON
- Arduino IDE起動直後に表示されているシンプルなLEDチカチカプログラムをESP8266へアップロード
[スケッチ]メニューの[マイコンボードに書き込む]を選択 - 1分ぐらいコンソール出力を眺める
- 何度かリセットを押してみて(図のDoorSensor)動作確認
Arduinoプログラミング
最後に、今回作ったハードウェアに搭載したファームウェアのソースコードを載せておきます。
ソースコード中のWiFi接続用のアクセス情報やら、SlackのIncoming Webhooksアドレスを取得して設定してください。
もしかすると将来Slackサイトのフィンガープリントが変更になるかもしれませんが、その場合はChromeなら次のように最新版を確認できます。
- Slackサイトを表示させる
- F12キーでDeveloper Toolsを開く
- [Security]タブにある[View certificate]ボタンを押す
- [詳細]タブで、[拇印]というフィールドにある値を書き写す
HTTPClientというクラスを使った方法が、おそらく現在のESP8266ネットワークプログラミングの最新版だと思いますので、これを活用することでシンプルな実装になるようにしてみました。
このプログラムでは、極力動作時間を減らすためにDHCPによるIPアドレス取得時間をなくして、特定のIPアドレスを使ってネットワークに接続するようにしています。
WiFiへの接続に失敗したり、Slackへの通知に失敗したらリトライはせずあきらめるようにしています。
Arduino IDEにて[ツール]メニューにある[Debug port]を”Disabled”から”Serial”に変更してからビルドしてESP8266へアップロードすると、シリアルにデバッグメッセージを出力させることが出来ます。
成功時と失敗時にスピーカーから音を鳴らしてお知らせしてくれるので耳で気づくことが出来ます。
電池切れの場合は音がならないのでそこで気づくか、もしくはSlackへの通知が滞っていることを別途監視です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
#include <ESP8266WiFi.h> #include <ESP8266HTTPClient.h> #ifdef DEBUG_ESP_PORT #define DEBUG_PRINTF(...) Serial.printf( __VA_ARGS__ ) #else #define DEBUG_PRINTF(...) #endif // Speaker PIN # #define SPKPIN 4 // Wifi connection const char* ssid = "<<Your Access Point SSID>>"; const char* password = "<<Your Access Point Password>>"; // Static IPv4 for ESP8266 IPAddress ip (nnn, nnn, nnn, nnn); // IP Address IPAddress subnet (nnn, nnn, nnn, nnn); // Subnet mask IPAddress gateway(nnn, nnn, nnn, nnn); // Gateway IPAddress dns (nnn, nnn, nnn, nnn); // DNS Server // Slack incoming web hook URL const char* slackUrl = "https://hooks.slack.com/services/<<Your Slack Incoming Webhooks URL>>"; const char* slackFingerPrint = "C1 0D 53 49 D2 3E E5 2B A2 61 D5 9E 6F 99 0D 3D FD 8B B2 B3"; const char* slackPayload = "payload={\"text\":\"The door opened.\"}"; const char* slackUserAgent = "IoT_DoorSensor/1.0"; // Success melody const int ok_score[] = {3136, 3136}; const int ok_beat[] = {100, 100}; const int ok_rest[] = {120, 120}; // Failed melody const int ng_score[] = {2349, 1397}; const int ng_beat[] = {100, 100}; const int ng_rest[] = {120, 120}; void setup() { #ifdef DEBUG_ESP_PORT Serial.begin(115200); #endif WiFi.config(ip, gateway, subnet, dns); WiFi.begin(ssid, password); } void loop() { wl_status_t status = WiFi.status(); if(status != WL_CONNECTED) { if(status != WL_NO_SSID_AVAIL && status != WL_CONNECT_FAILED) { delay(500); return; } if(status == WL_NO_SSID_AVAIL) { DEBUG_PRINTF("[WiFi] No connection found.\n"); } else if(status == WL_CONNECT_FAILED) { DEBUG_PRINTF("[WiFi] Connection failed.\n"); } play(sizeof(ng_score)/sizeof(ng_score[0]), ng_score, ng_beat, ng_rest); eternalSleep(); } HTTPClient http; http.begin(slackUrl, slackFingerPrint); http.setUserAgent(slackUserAgent); http.addHeader("Content-Type", "application/x-www-form-urlencoded;"); int httpCode = http.POST(slackPayload); if(httpCode == HTTP_CODE_OK){ DEBUG_PRINTF("[HTTP] POST OK. (%s)\n", http.getString().c_str()); http.end(); play(sizeof(ok_score)/sizeof(ok_score[0]), ok_score, ok_beat, ok_rest); }else{ DEBUG_PRINTF("[HTTP] POST failed. (Error: %s)\n", http.errorToString(httpCode).c_str()); http.end(); play(sizeof(ng_score)/sizeof(ng_score[0]), ng_score, ng_beat, ng_rest); } eternalSleep(); } void play(int score_size, const int *score, const int *beat, const int *rest){ for(int i=0; i<score_size; i++){ tone(SPKPIN, score[i], beat[i]); delay(rest[i]); } } void eternalSleep(){ ESP.deepSleep(0); delay(5000); } |
ESP8266のWiFi.config()について
1点だけ補足します。
ESP8266用のライブラリを使ったArduinoプログラムでは、WiFi.config()関数の使い方がArduino標準ライブラリと挙動が違ってました。
こちらのフォーラムでわかったことなのですが、引数の与え方が違ってます。
4つの引数が同じ型なので全く気づかず、デバッグ出力を眺めて当たりをつけ検索したことで発覚。
深く追っていませんが、DNSの設定は2つまで指定させたかったから都合のよいように最後に移動したんだと思われます。
この関数を使う場合はArduino標準ライブラリのほうのマニュアルを見るとはまってしまいますのでご注意ください。
- Arduino標準ライブラリでのWiFi.config()の場合
WiFi.config(IPAddress local_ip, IPAddress dns, IPAddress gateway, IPAddress subnet); - ESP8266用ライブラリでのWiFi.config()の場合
WiFi.config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1, IPAddress dns2);
3ヶ月経過しました! (2017年6月14日)
3月時点ではまだ動くかどうかわからなかったので、エネループを購入する勇気が無く、イオンで売っていた普通の単3アルカリ乾電池を使って試運転を開始しました。
当時、WEB中を見て回って入手した情報を元に計算したところでは2ヶ月ぐらいは持ちそうだったのですが、実際に動かしてみたところ3ヶ月経過時点ではまだ元気に動いてます。
いつ使い切るのか経過観察中ではありますが、予想を超え継続動作し続けていることに感動してます!
これだけ長持ちなのであれば、もう少し部品を足して入ったのか出て行ったのかは区別してもいいかもしれません。
電池交換をするタイミングでArduinoプログラムのほうももう少し手を入れたいアイデアがあるし、溜まったTODOリストを反映させるメンテナンスを設けてもいいかも。
6ヶ月目にして寿命を全う!(2017年9月15日)
1週間ぐらい前からSlackへの通知が途絶えていることに気が付きました。
ドアの開閉をしてもブザーが鳴らず、電池がなくなったという事で間違いなさそうです。
Slackの過去の履歴をたどるとどうやら9月15日で電池残量がなくなった模様です。
単純計算でだいたい6ヶ月稼動し続けていたことになるので、かなりロングライフだったということですね。
これだけ長期間の稼動が可能なのであれば、わざわざ充電池にしなくてもぜんぜん大丈夫。
引き続き次のサイクルもアルカリ乾電池で継続確定です!
変更歴
- 2017/06/14 : 電池が継続動作していることを実況
- 2017/09/15 : 電池を6か月で使い切ったことを実況
- 2018/02/12 : Slackサイトのフィンガープリント(拇印)が2018/02/08付で更新されていたので、ソースコードを修正
- 2018/10/14:一部パーツのURLを修正
レスポンシブ広告
関連記事
-
SlackのIncoming Webhooksが失敗した時の対処
我が家のIoTとしてSlackのIncoming Webhooksを活用したサー …
-
素早くマイクミュートとPCスリープが出来るDIYボタンを作る
2020年はCOVID-19の影響で長期にわたる外出自粛が続きました。9月時点で …
-
Arduinoでロータリーエンコーダーの動作確認
ロータリーエンコーダーは、よくボリューム調整のつまみに使われているようなモジュー …
-
ArduinoのPinChange割り込みライブラリとタイマーライブラリを使う
前回、素早くマイクミュートやPCスリープが行えるボタンを自作することで、とても晴 …
-
ATmega328へArduinoを書き込む
Arduino UNO等のArduinoボードを購入すると、USB端子に直接接続 …
-
Attiny13Aの工場出荷時の書き込みエラーを対策
Attiny13Aは工場出荷時に低速の動作周波数になってる模様です。 この時Ar …
-
ATmega328の書き込み装置をArduino UNO用シールドとして作成
前回、AVRマイクロコントローラーのATmega328PへのArduinoブート …
-
「子ども見守りサービス」をDIYで自作する
最近「子ども見守りサービス」が注目されているようです。 どうも私は課金の発生する …