スキップしてメイン コンテンツに移動

HaLaKeのドアの開閉を検知しよう!

  今回はセンサーを使って身の回りの物理現象を読み取って活用できるデータをとれるようにしていきたいと思います。 一つの例として今回はHaLaKeのドアの開閉を読み取って一日初めの開閉時間と開閉回数をSlackに投稿してくれるようにしていきたいと思います。

HaLaKeだけでなくお店や家のどこかしらのドアの開閉のデータをとることで何かに活用できるのではないでしょうか。
多様な条件でもなるべく運用できるように今回は超音波センサを使って距離で開閉を読み取っていきます。 SlackにIFTTTを経由して投稿する記事は以前投稿しているので今回はSlackのAPIを使って投稿する方法を紹介します。

前提条件

  • 書き込み方などがわからない方以前の記事を参照
  • arduinoやESP32の知識がある方は上記を無視してもOK

必要なもの

  1. ESP32-DevKitCなどのESP32開発ボード
  2. 書き込み用ケーブル(開発ボードに合う端子のケーブルを各自用意)
  3. 超音波センサ
  4. ブレッドボード
  5. ジャンパワイヤ
  6. 確認用LED(なくても大丈夫)
  7. 抵抗(LEDなしなら容易不要)330~1kΩぐらい
  8. コンデンサ0.1μF(自動書き込みができない場合)

Slackの設定

Slackの設定を行っていきます。
今回使う機能は最低限に絞っているので使わない機能は説明を省きます。 参考にさせて頂いたサイトはこちら

https://note.com/kawa1228/n/nb0811ed44792note.com

最初は下記のサイトにアクセス

Slack API: Applications | Slack サイトからサインインしたことがない方は以下のような画面が出てくるので赤枠をクリックしてサインインするワークスペースURLとメールアドレス、パスワードを入力しサインインする必要があります。
サインインしたことがある方はこちらの作業をスキップ  

サインインできたらもう一度こちらにアクセス Slack API: Applications | Slack

最初からサインインしてあった方はこちらからの作業になります。 初めにAppを作るの画像に従って操作します。 

  • 注意:Appを作ることによってSlack API利用規約に同意したことになるので利用規約を確認の上、各自の判断で行って下さい。

 ここからトークンの種類を設定していきます。     インストールボタンを押してワークスペースで利用できるようにします。    次にSlack自体の設定を行っていきます。
自動投稿したいチャンネルを作成、選択し次の操作を行ってください。    これでワークスペースに追加できました。  左のチャンネル選択画面から一番下App欄を見ると追加されているのがわかります。
これでSlackの下準備が完了しました。

ハードウェア

 必要なもので記入されているものすべてを使った場合の例です。
私の環境ではデバッグ用にLEDと抵抗,自動書き込みされないのでコンデンサを挟んでいます。必要としない場合は取り除いても構いません。
 私はこのような配線になってしまいわかりにくいので一つ目の画像のようにパーツ同士が配線されていればぐちゃぐちゃでも構わないません。
ところどころ配線が二つの画像で違っているので一つ目の画像を参考に組んでもらえれば楽だと思います。

配線をつなぐ場所が間違っていないかだけ確認してもらえればと思います。
 最低限↑のようにつながっていれば動作します。

ソフトウェア

#include <Arduino.h>
#include <HTTPClient.h>
#include <time.h>

#define TRG 12
#define ECH 13
#define HIGHTIME 10
#define threshold 70    //70m
#define judge_time 1000 //1秒

HTTPClient http;
const char* ssid = "";                                                       //Wi-FiのSSID
const char* password = "";                                              //Wi-Fiのpasword
String url = "https://slack.com/api/chat.postMessage";
String acces_token = "";                                                  //アクセストークン
String channel = "";                                                         //投稿したいチャンネル名
String acces_url;

unsigned int counter = 0;
unsigned long total_counter = 0;
unsigned long diff;
float dis;
bool result = false;
struct tm timeInfo;//時刻を格納するオブジェクト
int before_hour = 0;
int before_day = 0;
int open_per_hour_total = 0;
double hour_average;
int start_hour;

bool response_echo(){
    digitalWrite(TRG, HIGH);
    delayMicroseconds(HIGHTIME);
    digitalWrite(TRG, LOW);
    diff = pulseIn(ECH, HIGH);
    dis = (float)diff * 0.01715;//26度の場合0.017355室度によって音の伝わる速さが違うので変えるとより正確に距離を出すことが出来る
    //Serial.print(dis);//debug
    //Serial.println("cm");//debug
    if(dis < threshold){
      result = true;
    }else{
      result = false;
    }
    return result;
  }

void setup() {
  Serial.begin(115200);
  pinMode(TRG, OUTPUT);
  pinMode(ECH, INPUT);
  ledcAttachPin(A18,1);
  ledcSetup(1,12000,8);

  WiFi.begin(ssid, password);
  Serial.print("connecting to WiFi.");
  int i = 0;
  while(WiFi.status() != WL_CONNECTED){
    delay(100);
    Serial.print(".");
    i++;
    if(i == 100){
        i = 0 ;
        Serial.println("Retry!!! please check your ssid and passpword");
        }
    }
    Serial.println("connected! & timeset!");
    configTime(9 * 3600L, 0, "ntp.nict.jp", "time.google.com", "ntp.jst.mfeed.ad.jp");//NTPの設定
    getLocalTime(&timeInfo);
    before_hour = timeInfo.tm_hour;
    before_day = timeInfo.tm_mday;

    bool first_time = true;
    Serial.println("not_first_time");
    while(first_time){
      if(response_echo()){
        ledcWrite(1,0);
        delay(judge_time);
        if(response_echo()){
          getLocalTime(&timeInfo);
          acces_url = url + "?token=" + acces_token + "&channel="+ channel + "&text=" + "HaLaKe_Door_Open_Notification" + "&attachments=" + "[{\"text\":\"First_Open->" + timeInfo.tm_hour + ":" + timeInfo.tm_min + "\"}]";
          http.begin(acces_url);
          http.GET();
          http.end();
          first_time = false;
          Serial.println(acces_url);
          start_hour = timeInfo.tm_hour;
        }
      }else{
        ledcWrite(1,255);
      }
    delay(100);
  }
}

void loop(){
  getLocalTime(&timeInfo);

  if(timeInfo.tm_mday != before_day){
    Serial.println("reset!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
    Serial.print("before_day:");
    Serial.println(before_day);//debug
    Serial.print("now_day:");
    Serial.println(timeInfo.tm_mday);//debug
    ESP.restart();
  }
  if(timeInfo.tm_hour > 18){
    return;
  }else{
    if((timeInfo.tm_hour - before_hour) == 1){
      open_per_hour_total += counter;
      hour_average = (double)open_per_hour_total / (double)(timeInfo.tm_hour - start_hour);
      acces_url = url + "?token=" + acces_token + "&channel="+ channel + "&text=" + "HaLaKe_Door_Open_Notification" + "&attachments=" + "[{\"text\":\"Open_per_Hour:" + counter + "\\n" +  "Hour_Average:" + hour_average + "\"}]";
      http.begin(acces_url);
      Serial.println("GET!!!!!!!!!!!!!!!!!!!!!!!!");
      http.GET();
      http.end();
      counter = 0;
      before_hour = timeInfo.tm_hour;
    }
    if(response_echo()){
      ledcWrite(1,0);
      delay(judge_time);
      if(response_echo()){
        counter++;
        Serial.println(counter);
      }
    }else{
      ledcWrite(1,255);
    }
    delay(100);
  }
}
  • 注意:上記プログラムの一部を書き換える必要があります。

プログラム上部の
ssidWi-FiSSID(名前)
passwordWi-Fiのパスワード
acces_tokenを前章でメモをお勧めしたアクセストーク
channelをSlackの自動投稿してほしいチャンネル名 にそれぞれ書き換えておきましょう。
一つ例としてSSIDを書き換えてみましょう。SSIDhogehogだとしましょう。

const char* ssid = "hogehoge";

こうなります。これと同様にほかの項目も書き換えておきましょう。

プログラムの流れとしては
1. 起動直後はインターネットに接続しドアの初開閉がされるまで待つ
2. 最初の開閉を検知したら投稿
3. 随時開閉を検知してカウントしておく
4. 一時間おきに一時間の開閉回数と一日のその時点までの開閉回数の時間平均を投稿 5. 18時以降はカウントをストップ
6. 日付が変わると同時に再起動を行い起動直後の動作1.に戻る といった内容になっています。

  • 注意:このプログラムは特に作りこんでいないのである程度の動作はしますが、サンプル程度と認識していただきたい。各環境に合わせてプログラムを変える必要があります。このプログラムをそのまま利用する場合や何か問題が起きた場合、自己責任でよろしくお願いします。随時問題が見つかり改善出来次第追記していきたいと考えています。

動作確認

  HaLakeのドアにはこんな感じにおいてみてました。
起動したときはこんな感じに通知されます。 
初開閉から区切りの良い一時間置き(9時、10時、11時のような時間刻みで18時まで)に通知します。
運用はじめはわざと最初の開閉を誤認識させておく必要があります。
次の日の開店時には自動で一日の初開閉を認識するようになります。

まとめ

今回は多様な条件下でも運用できるようにと超音波センサを使って一つの例を紹介しましたが、それぞれの運用条件に合ったセンサを使うことによってもっと効率と精度を上げることが出来ます。
そのため紹介したプログラムは(経験が未熟なことも含め)無駄が多いような気がしますがご了承ください。
ドアノブが鉄などの導体でできているならタッチセンサ、運用場所の周りに人がいることが少なければ開閉でなく人を検知する人感センサ、ドアが頑丈で風などで動かないものならドアの加速度を測る加速度センサなど、開閉を検知できるセンサはたくさんあります。使うものによっては簡単なプログラムでも動くので私のような初心者でも運用ができると思います。長期運用の場合、消費電力なども考慮してプログラムやパーツ選びも重要になってくるので掘り下げてみるのも面白いかもしれません。

コメント

このブログの人気の投稿

Phaser3 + Typescriptを使ってRPGゲームの基礎を作ろう!その2

前回の記事 に引き続きPhaser3+Typescriptを使って RPG の基礎を作っていきます。 この記事は前回の記事を呼んだ前提で説明していきますので、ぜひそちらを先に読むことをお勧めします。 また、今回の記事は前回よりも難易度と内容量が上がっていますが、記事の最後に作業後の リポジトリ のリンクがありますので、そちらを先にダウンロードしてそちらと比較しながら学習することができます。 前回まで作成した状態のプログラムが以下の リポジトリ からダウンロードできますので前回まででうまくいっていない方は参考にしてみてください。 github.com 最終目標(再掲) ・Phaser3とTypescriptで RPG ゲームの基礎を作る。 ・Phaser3をTypescriptで使う方法を学ぶ ・Phaser3の使い方を学ぶ 今回の目標 ・ゲームの作り方の断片を知る ・キャラの表示できるようにする ・キャラを移動できるようにする ・当たり判定をつける ・ NPC の追加してみる ・話しかけられるようにする 開発前提(再掲) ・Nodejsの環境・知識がある ・ Javascript ・Typescriptがある程度かける ・当ページ紹介の環境を試す場合はgit・ github の知識がある 使用した主要Nodeモジュール(再掲) ・typescript(Typescriptの コンパイル 用) ・phaser(フロントの Javascript 用ゲームライブラリ) ・live-server(ソースを監視してブラウザのページをリロード) ・ts-loader(webpackがTypescriptをバンドルする用)webpack(言わずと知れたモジュール依存をいい感じに解決しバンドルする) ・webpack- cli (webpackを コマンドライン で使用するのに必要) 注:各Nodeモジュールバージョンは後述 当ブログ仕様の画像素材の注意点 当ブログで使用する画像素材は『 ピポヤ倉庫 』より許可なしで無償再配布・改変が認められたものを改変して作成されたものです。 中には許可なく再配布・改変してはいけない素材もインターネット上には多く存在するのでそれらを使用するときは十分に規約を呼んでから使用しましょう。 1. キャラの表示 想定画面 今回は、はじめにキャラつまり操作

M5Stackで、においセンサー(TGS2450)を使ってみる。(LCDに表示編)

今回は、においセンサー(TGS2450)から取得したデータをM5Stackの LCD にグラフ表示をしていきます。 今回主に使用したもの M5Stack 10Ω抵抗 5本 Pch  MOSFET  2SJ334(スイッチとして利用) M5StackSideBB(ブレッドボード) M5Stackのピンはそのままだと配線するとき手間がかかるかと思いますので、今回はM5StackSideBBを利用しました。 ブレッドボードも付いているので、手軽に電子工作できるので個人的にオススメです。 SideBB for M5Stack www.switch-science.com 諸注意 本ブログのプログラムはArduinoIDEまたはPlatformIOでM5Stackの開発ができる状態であること前提のものですので、各自導入をお願いします。 過去に Windows のArduinoIDEで M5Stackの開発環境を構築する記事 があるので、参考にしてください。 においセンサー(TGS2450)について 今回使用したセンサーは 秋月電子通商 で購入できます。 http://akizukidenshi.com/catalog/g/gP-00989/ akizukidenshi.com TGS2450には4つのピンがあり、使用するのはそのうちの3本でヒーターを温めるピン、センサー情報を得るピン、GNDがあります。 ここで注意したいのは、ヒーター電圧は1.6Vと記述されているのでM5Stackで利用するときは分圧して3.3Vを1.6V近くまでに降圧することをお勧めします。 TGS2450のセンサーは可変抵抗になっており、データシートには5.62kΩ〜56.2kΩの間を抵抗が変化し、においが強いとより低くなると記述されていました。 よって、センサーの値をM5Stackで取得するにはセンサー抵抗と外部に接続する任意の値の抵抗による分圧回路によって求めることができます。 TGS2450の動作方法は、250ms周期でセンサーに電圧を5ミリ秒on、245ミリ秒offの状態にしてヒーターは8ミリ秒on、242ミリ秒offにすることで値を取得します。 配線 においセンサーとM5Stackの配線 上の図が配線図です。 30Ωの抵抗は10Ωの抵抗を三つ直列に接続して作成しました。 また、上部の抵抗10Ω二

Phaser3 + Typescriptを使ってRPGゲームの基礎を作ろう!その1

今回はPhaser3とTypescriptを使って簡単な RPG ゲームを作る方法を紹介していきます。 内容はPhaser3およびゲーム作りについての記事なので、Nodejsの周辺モジュールなどの説明は一部省いての説明になりますのでご了承ください。 またこの記事では Phaser2 ではなく Phaser3 を使用するので注意してください。 この記事は二部構成になりますので、この記事を読んだ際はぜひ次の記事も読むことをお勧めします。 最終目標 ・Phaser3とTypescriptで RPG ゲームの基礎を作る。 ・Phaser3をTypescriptで使う方法を学ぶ ・Phaser3の使い方を学ぶ 今回の目標 ・開発環境を整える ・Phaser3の開発構成を知る ・スタート画面を作る ・マップ表示をさせる 開発前提 ・Nodejsの環境・知識がある ・ Javascript ・Typescriptがある程度かける ・当ページ紹介の環境を試す場合はgit・ github の知識がある 使用した主要Nodeモジュール ・typescript(Typescriptの コンパイル 用) ・phaser(フロントの Javascript 用ゲームライブラリ) ・live-server(ソースを監視してブラウザのページをリロード) ・ts-loader(webpackがTypescriptをバンドルする用)webpack(言わずと知れたモジュール依存をいい感じに解決しバンドルする) ・webpack- cli (webpackを コマンドライン で使用するのに必要) 注:各Nodeモジュールバージョンは後述 1. 最低限の開発環境の準備 今回最低限の環境を整えるために、『Typescript + Phaser3』の開発テンプレートを github リポジトリ で公開しました。 以下からZIPをダウンロードするか、 git clone コマンドで各自環境に展開してみてください。 ここから先は リポジトリ のプログラムを元に説明していきます。 github.com 展開するとファイル構造は以下のようになっているかと思われます。 注: 他にもファイルやフォルダがあるかと思われますが、表記されているのは今回使うものになっています。 - src/ (これから書くプログラムの保存領域)