M5StickCの姿勢を検知して施解錠履歴を管理する

## 概要
* ドアの施開錠履歴をできるだけ安価な仕組みで取得したい。
* 既存のものではサムターンに被せるタイプのスマートロックがあるが、高価である。
* 例えば高齢者の安否確認にスマートロックは必要ない。施開錠履歴のみあれば十分ではないか。

![IMG_0812.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701445/1ce7dc4f-5fa4-9e81-0d5a-2921e05e0392.jpeg)


![IMG_0814.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701445/0503efaf-6ebd-3024-b55f-e9e4412161a6.jpeg)

![key_thumbturn_h.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701445/21725c71-e687-9e50-7b52-1dba0cfcedd6.jpeg)

![スクリーンショット 2021-03-04 9.15.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701445/2a6cacce-12d8-e11f-4380-a47cb19689ac.png)

![スクリーンショット 2021-03-04 9.15.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701445/f5f90fcd-67ea-4b02-6520-478deefb29a9.png)


## 用意するもの
* M5StickC
* Arduino IDEが動くPC (Mac/Windows)

## 環境構築

(1)Arduino IDEをインストール
https://www.arduino.cc/en/main/software
(2)M5StickC関連のライブラリをインストール
　スケッチ→ライブラリをインクルード→ライブラリを管理
　M5StickCを検索

## プログラミング

* M5StickCの6軸センサーを使い、どの軸が上を向いているかを検出する
* ディスプレイにはOPEN/CLOSEと表示する。
* Wifi経由でAmbientに送信し可視化する(1:OPEN 0:CLOSE)

```C++:lockstate.ino
#include <M5StickC.h>
#include "Ambient.h"

#define POSE_P_X 0
#define POSE_M_X 1
#define POSE_P_Y 2
#define POSE_M_Y 3
#define POSE_P_Z 4
#define POSE_M_Z 5
uint8_t pose = POSE_P_X;
uint8_t prev_pose = POSE_P_X;

WiFiClient client;
Ambient ambient;

const char* ssid = "xxxxxxxxxxxxxx";
const char* password = "xxxxxxxxxxxx";

unsigned int channelId = "xxxxx"; // AmbientのチャネルID
const char* writeKey = "xxxxxxxxxxxxxxxx"; // ライトキー

// 加速度
float accX_g = 0;
float accY_g = 0;
float accZ_g = 0;
float accX_mpss = 0;
float accY_mpss = 0;
float accZ_mpss = 0;

// 角速度
float gyroX_dps = 0;
float gyroY_dps = 0;
float gyroZ_dps = 0;

boolean near_p_g(float value){
  if(8.0 < value && value < 12.0){
    return true;
  }else{
    return false;
  }
}

boolean near_m_g(float value){
  if(-12.0 < value && value < -8.0){
    return true;
  }else{
    return false;
  }
}

boolean near_zero(float value){
  if(-2.0 < value && value < 2.0){
    return true;
  }else{
    return false;
  }
}

void setup() {
  // Initialize the M5StickC object
  M5.begin();
  M5.MPU6886.Init();
  M5.Lcd.setRotation(1);
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setTextSize(1);

      WiFi.begin(ssid, password);  //  Wi-Fi APに接続
    while (WiFi.status() != WL_CONNECTED) {  //  Wi-Fi AP接続待ち
        delay(500);
        Serial.print(".");
    }
    Serial.print("WiFi connected\r\nIP address: ");
    Serial.println(WiFi.localIP());

    ambient.begin(channelId, writeKey, &client); // チャネルIDとライトキーを指定してAmbientの初期化
}

void loop() {

  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setTextSize(3);

  // 加速度取得
  M5.MPU6886.getAccelData(&accX_g,&accY_g,&accZ_g);
  accX_mpss = accX_g * 9.8;
  accY_mpss = accY_g * 9.8;
  accZ_mpss = accZ_g * 9.8;
  // 角速度取得
  M5.MPU6886.getGyroData(&gyroX_dps,&gyroY_dps,&gyroZ_dps);

  if(near_zero(accX_mpss) && near_p_g(accY_mpss) && near_zero(accZ_mpss)){
    pose = POSE_P_Y;
  }else if(near_p_g(accX_mpss) && near_zero(accY_mpss) && near_zero(accZ_mpss)){
    pose = POSE_P_X;
  }else if(near_zero(accX_mpss) && near_zero(accY_mpss) && near_p_g(accZ_mpss)){
    pose = POSE_P_Z;
  }else if(near_zero(accX_mpss) && near_m_g(accY_mpss) && near_zero(accZ_mpss)){
    pose = POSE_M_Y;
  }else if(near_m_g(accX_mpss) && near_zero(accY_mpss) && near_zero(accZ_mpss)){
    pose = POSE_M_X;
  }else if(near_zero(accX_mpss) && near_zero(accY_mpss) && near_m_g(accZ_mpss)){
    pose = POSE_M_Z;
  }

  // 姿勢に変化があった場合にのみ描画する
  if(prev_pose != pose){
    M5.Lcd.fillScreen(BLACK);
    switch(pose){
      case POSE_M_X:
        M5.Lcd.setRotation(3);
        M5.Lcd.setCursor(56, 16);
        M5.Lcd.print("CLOSE");
        // 施錠の情報をAmbientに送信する
        ambient.set(1, 0);
        ambient.send();
        delay(500);
        break;
      case POSE_P_Y:
        M5.Lcd.setRotation(3);
        M5.Lcd.setCursor(56, 16);
        M5.Lcd.print("OPEN");
        // 解錠の情報をAmbientに送信する
        ambient.set(1, 1);
        ambient.send();
        delay(500);
        break;
        default:
        ;
        }
    }
  prev_pose = pose;
  delay(100);
}
```

## 注意点
* サムターンの操作性を損なわないような取り付け方を工夫する必要がある。
* 何らかの電源（モバイルバッテリー等）で給電しておく必要がある。

## その他
* 画面表示の明るさ、表示時間を調整すれば節電できる。
* アプリを構築しAPIに送信するようにすれば複数箇所の対応、アラートメールを送信する等機能を増やせる。
* ドアの施解錠以外の用途にも応用できるかもしれない。