12
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

M5Stackでスマートロックを作った

Last updated at Posted at 2019-12-05

#今回作るモノ

はじめに

大まかな仕組み
名称未設定ファイル (1).png
API Gateway -> Lambda -> AWS IoT
といった形で繋げています。

Q. 前にも作ってなかった?
A. 作ってます。-> コレ

前に作ったものは

  • 基板丸出し
  • 配線丸見え
  • サーボの固定がお粗末
  • ラズパイが扉についてるのはカッコ悪い

ということで作り直します。

使用したもの

※ESP32をArduinoIDEで開発します。公式のGitHubにセットアップ方法が載ってますので先にそちらを済ませてから

1.M5Stackでサーボを動かす

今回はESP32Servoを使って制御します。
:pushpin:こちらの記事が参考になります。

回路を作る

サーボモータのSG92Rは小型のサーボなのでこのような回路にします。
Untitled Sketch_ブレッドボード.png

ESP32は起動時に1Aもの電流が流れ、サーボモーターと同時に使用するとマイコンの動作が不安定になる場合があるため申し訳程度にコンデンサを挟んでいます。

サーボを動かす

次にプログラムの書き込みです。
以下にサンプルコードを載せます。

Servo_test.ino
#include <M5Stack.h>
#include <ESP32Servo.h>

Servo servo1; // create four servo objects
int servo1Pin = 26;

// Published values for SG90 servos; adjust if needed
int minUs = 500;
int maxUs = 2400;

int pos = 0;      // position in degrees
bool lock_flag = true;

void door_open() {
  M5.Lcd.setTextFont(4);
  M5.Lcd.setTextSize(8);
  M5.Lcd.setCursor(80, 100, 1);
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setTextColor(GREEN, BLACK);
  M5.Lcd.println("open");
  servo1.attach(servo1Pin, minUs, maxUs);
  for (pos = 90; pos <= 180; pos += 1) {
    servo1.write(pos);
    delay(2);
  }
  delay(500);
  for (pos = 180; pos >= 90; pos -= 1) {
    servo1.write(pos);
    delay(2);
  }
  lock_flag = false;
  servo1.detach();
}

void door_close() {
  M5.Lcd.setTextFont(4);
  M5.Lcd.setTextSize(10);
  M5.Lcd.setCursor(60, 100, 1);
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setTextColor(RED, BLACK);
  M5.Lcd.println("close");
  servo1.attach(servo1Pin, minUs, maxUs);
  for (pos = 90; pos >= 0; pos -= 1) {
    servo1.write(pos);
    delay(2);
  }
  delay(500);
  for (pos = 0; pos <= 90; pos += 1) {
    servo1.write(pos);
    delay(2);
  }
  lock_flag = true;
  servo1.detach();
}

void setup() {
  Serial.begin(115200);
  M5.begin(true, false, true);
  M5.Lcd.clear(BLACK);
  servo1.setPeriodHertz(50);      // Standard 50hz servo
  door_close();
}

void loop() {
  M5.update();
  if (M5.BtnA.wasReleased() || M5.BtnB.wasReleased() || M5.BtnC.wasReleased()) {
    if (lock_flag) {
      door_open();
    }
    else {
      door_close();
    }
  }
}

M5Stackのボタンを押してみて右に90°左に90°と動けば成功です。
うまく動いたらM5Stack用の基板に回路を作ってしまいましょう。
また、door_open()とdoor_close()はお宅によって逆の可能性があるので適宜修正してください。

2.外装設計

とりあえず動くものができたのでモチベーションを上げる意味を込めて3D CADで設計をします。
私はFusion360を使って設計しました。
とはいえ、ここで説明できないのでリンクを置いときます。

M5Lock_img.png

※位置調整パーツはなくても構いませんがあった方が設置するときに楽です。

ご家庭の3Dプリンターもしくは、どこかに頼んで出力しましょう。
私が使ったものは2万円の中華製のものです。

パーツができたら組み立てます。

せっかく3Dプリンターで出力しているので、お宅に合わせて修正や改善をしてください。

3.AWS IoTにつなげる

外装ができてモチベーションを上がったはずなので、次はAWS IoTにM5Stackを接続したいと思います。

ESP32(M5Stack)をAWS IoTに接続している記事はたくさんあるので:pushpin:こちらの記事を参考にしながらPubSubClientなどの設定をしてください。

また、ArduinoJsonも使用するのでIDEからダウンロードをします。

今回使用するコードはGitHubにあげてあります。

send_status()で/shadow/updateに鍵の開閉を送信していて、開け閉めと60秒に1回送信しています。
また、/shadow/update/deltaの変更を受け取って関数を発火しています。

なのでshadowをupdateしてあげれば鍵の開け閉めができるということになります。

実際にAWS IoTのshadowをいじってみましょう。
AWS IoT -> 管理 -> モノ -> 作成したもの -> シャドウ
です。

ここでシャドウドキュメントを編集してみてM5Stackの画面が変わったらうまく接続できています。

何かエラーが発生して動かない場合はトラブルシューティングを参照してください。

4.LambdaとAWS IoTをつなげる

次にLambdaとAWS IoTを接続します。

ロール作成

まず最初にロール作成をします。

AWS IAMにおいて、ロールを設定して、Lambdaのインスタンスに割り当てます。
そこでポリシーを 

  • AWSIoTDataAccess

を追加して保存します。
今回はUpdateしかしないのでここまでの権限は必要ないですが大は小を兼ねるの精神で見逃してください。

インスタンス作成

Lambdaでインスタンスを作成します。
「名前」をよしなに設定して
「ランタイム」はPython 3.6を、
「ロール」は先ほど作ったものにします。

Lambdaの設定

今回はコードをインラインで編集します。

lambda_function
# coding: utf-8
 
import json
import boto3
 
# Functionのロードをログに出力
print('Loading function')  
 
#AWS IoT Data Planeオブジェクトを取得
iot = boto3.client('iot-data')
 
def lambda_handler(event, context):
    
    lock_state = event['lock_state']
    
    payload = {
        "state":{
            "desired": {
                "lock_state": lock_state
            }
        }
    }
    
    try:
        # メッセージをPublish
        response = iot.update_thing_shadow(thingName = '<YOUR THING>', payload = json.dumps(payload, ensure_ascii=False))
        
        print(response)
    
        return {
            'isBase64Encoded': False,
            'statusCode': 200,
            'headers': {},
            'body': {"lock_state": lock_state}
        }
        
    except Exception as e:
        print(e)
        return {
            'isBase64Encoded': False,
            'statusCode': 200,
            'headers': {},
            'body': {"message": "failed"}
        }

こんな感じで編集します。

関数が発火するとeventに辞書型でjsonが渡されるので中身に応じてboto3のupdate_thing_shadow関数で状態を更新します。

テスト

右上のテストのボタンから
test_event.png
こんなものを作ってテストしてみましょう。
AWS IoTのシャドウが更新されているはずです。


Slackなどに通知するコードなどを書いてもいいかもしれません。

5.API GatewayとLambdaをつなげる

次はAPI GatewayとLambdaをつなげます。

API Gateway作成

AWSマネジメントコンソールよりAPI Gatewayを選択し、APIの作成行います。
APIの名前は好きなもので構いません。

メソッドの作成

API Gatewayがリクエストを受け付けるhメソッドを定義します。今回はPOSTリクエストを受けた時にLambdaを起動するようにします。

アクション -> メソッドの作成 -> 「POST」を選択

統合タイプは「Lambda関数」を選択して
先ほど作った関数を指定します。

また、API GatewayからのLambda関数呼び出しを許可します。

テスト

「テスト」ボタンからテストをします。

「リクエスト本文」に
{"lock_state": 1}
を入れて「:zap:テスト」を押します。

右側にログが出たら、LambdaとAWS IoTを確認してlock_stateが変更されているか確認してください。

APIのデプロイ

テストを実行して変更が確認出来たらAPIをデプロイします。
「アクション」-> 「APIのデプロイ」
ステージ名を適当に設定し「デプロイ」ボタンを押します。

URLが表示されたら成功です。

後は好きな端末でPOSTしてあげれば鍵を操作できます。

おまけ

私はiPhone (iOS12以降)を使っているのでこのように「ショートカット」を使って鍵を操作しています。
iOS の画像.jpg

「URL」に先ほどのURLをいれて「URLの内容を取得」でPOSTを選択しフィールドを真偽値にしてあげればiPhoneから操作ができます。

12
10
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
12
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?