LoginSignup
7
7

More than 3 years have passed since last update.

M5StickC をドアセンサー(&開閉通知)にする

Posted at

日曜DIY。家人の外出や帰宅が何となく分かるように、M5StickC + ENV Hatで家のドアセンサーを作った(3000円前後)。
m5stickc.jpg

ハードウェアの調達

開発

開発環境

プログラム

#include <M5StickC.h>
#include <Wire.h>
#include "bmm150.h"
#include "bmm150_defs.h"
#include <WiFi.h>
#include <WiFiClientSecure.h>

const char* wifi_ap_ssid = "XXXXXXXX";
const char* wifi_ap_pass = "XXXXXXXX";

String   door_state     = "close";
uint16_t door_thr_close =  1600;
uint16_t door_thr_open  =   800;
uint16_t door_ignore    = 60000;
uint32_t door_lastpost  = -door_ignore;

BMM150 bmm = BMM150();

void setup() {
  Serial.begin(115200);
  Serial.println("start debugging");
  Wire.begin(0,26);
  M5.begin();
  M5.Lcd.setRotation(3);
  M5.Lcd.fillScreen(BLACK);
  pinMode(M5_BUTTON_HOME, INPUT);
  initdev();
  M5.Lcd.fillScreen(BLACK);
}

void initdev(){
  M5.Lcd.setCursor(0, 0, 2);
  if(bmm.initialize() == BMM150_E_ID_NOT_CONFORM){ while(1); }
  M5.Lcd.printf("Mag sensor OK.\n");

  WiFi.begin(wifi_ap_ssid, wifi_ap_pass);
  while (WiFi.status() != WL_CONNECTED){ delay(500); }
  IPAddress ip = WiFi.localIP();
  M5.Lcd.printf("Wifi: %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
  delay(2000);
}

uint8_t setup_flag = 1;
void loop() {
  bmm.read_mag_data();
  int magval = (int)(sqrt(pow(bmm.raw_mag_data.raw_datax, 2) + pow(bmm.raw_mag_data.raw_datay, 2) + pow(bmm.raw_mag_data.raw_dataz, 2)));
  String state = "-----";
  if (door_thr_close < magval){ state = "close"; }
  if (magval < door_thr_open ){ state = "open"; }

  M5.Lcd.setCursor(0, 0, 2);
  M5.Lcd.printf("%06d [%s]  \n", magval, state);
  if ((state != "-----") && ((millis()-door_lastpost) > door_ignore) && (door_state != state)){
    door_state = state;
    door_lastpost = millis();
    String r = https_Web_Get("example.com", "/update?1=door&2=" + state + "&3=" + String(magval));
    M5.Lcd.printf("send: %s \n", state);
    M5.Lcd.println(r);
  }
  delay(200);

  if(!setup_flag){
    setup_flag = 1;
    initdev();
  }
  if(digitalRead(M5_BUTTON_HOME) == LOW){
    setup_flag = 0;
    while(digitalRead(M5_BUTTON_HOME) == LOW);
  }
  return;
}

String https_Web_Get(const char* host, String target_page){
  String res;
  WiFiClientSecure https_client;
  if (https_client.connect(host, 443)){
    String s = "GET https://" + String(host) + target_page + " HTTP/1.1\r\nHost: " + String(host) + "\r\n";
    s += "User-Agent: ESP32\r\nConnection: close\r\n\r\n\0";
    https_client.print(s);
    https_client.flush();
  }
  if(https_client){
    while(https_client.connected()){
      String r = https_client.readStringUntil('\n');
      if(0 <= r.indexOf("HTTP")){res = r;}
      Serial.println(r);
      if (r == "\r") break;
    }
    while (https_client.available()){ https_client.read(); }
    https_client.stop();
  }
  return res;
}
  • 上記では磁力の閾値は800以下でclose、1600以上でopenとしてある。
  • チャタリング防止のため、状態変化通知後60秒間は次の通知を行わないようにしている。
  • 通知先のAPIは当初IFTTTからのEmailとしていたが、通知が遅いことがあったため、自作+Slackにした。
  • 通信はhttpsだが、ライブラリではサーバ証明書の検証まではしていないようなので、その点留意。
  • 機能加除、各種デバッグ行いたい場合は、SerialかDisplayにて適宜printfデバッグ。
  • ENV HATは気温/湿度/気圧のデータも取れるほか、StickC本体にはマイクもあるため、ドアが開いたら録音、など様々な拡張の妄想が広がります。StickVだとさらに。

設置と調整

  • ドア側にマグネットを付ける
  • 閾値を環境に合わせて調整
  • 当初USB電源に安価なものを使ったら、過電流で熱くなり液晶がダメになって1台つぶしてしまった。USB電源接続後は3分ほど本体温度や見た目に異状ないか要確認。
7
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7