スマホキー

某アジトの共有キー需要の為、ESP8266を使用したロックシステムを作成した。

仕組みは単純で、スマホ(wifiアクセス可能な機器であれば何でも良い)がwifiアクセスポイントに繋がったらサーボを動かす。

15秒たったらサーボを元に戻す。

ソースコード

#include <ESP8266WiFi.h>
#include <WiFiClient.h> 
#include <ESP8266WebServer.h>
#include <Servo.h> 

const char *ssid = "********";
const char *password = "********";
const int channel  = 1;
const int ssid_hidden = 1;

ESP8266WebServer server(80);

//led
const int ledPin = 16;

//Servo
Servo myservo1;
const int SERVO1 = 14;
const int DOOR_OPEN = 90;
const int DOOR_CLOSE = 20;

//status
int door_open = 0;
int DOOR_CLOSE_TIME = 15;//指定秒数後に自動的に閉じる

void handleRoot() {
  server.send(200, "text/html", "<h1>Welcom</h1>");
}


void setup() {
  delay(100);
  Serial.begin(115200);

  pinMode(ledPin, OUTPUT);
  
  WiFi.mode(WIFI_AP);
  WiFi.softAP(ssid, password, channel, ssid_hidden);
  
  IPAddress myIP = WiFi.softAPIP();
  Serial.println(myIP);

  server.on("/", handleRoot);
  server.begin();
  open_door();
}

void loop() {
  server.handleClient();
  int n = WiFi.softAPgetStationNum();
  
  //Serial.printf("Stations connected = %d\n", n);
  delay(16);

  if( n > 0){
    if(door_open == 0){
      door_open = 1;
      Serial.printf("Stations connected = %d\n", n);
      open_door();
    }
  }else{
    digitalWrite(ledPin, LOW);    
    if(door_open == 1){
      door_open = 0;
      Serial.printf("Stations connected = %d\n", n);
      move_servo(DOOR_CLOSE);
    }
  }
}

void open_door()
{
  move_servo(DOOR_OPEN);
  for(int i = 0; i < DOOR_CLOSE_TIME; i++){
    digitalWrite(ledPin, HIGH);
    delay(500);
    digitalWrite(ledPin, LOW);
    delay(500);
  }
  move_servo(DOOR_CLOSE);    
}

void move_servo(int deg)
{
  myservo1.attach(SERVO1);
  myservo1.write(deg);
  delay(1000); //動作完了するまで待ってからdetachする
  myservo1.detach();
}

判断条件はアクセスポイントへの接続数とした。

接続、切断の各イベント内で制御を行おうと思ったのだが、STADISCONNECTEDイベントを取得できる場合と出来ない場合があり、

単純に指定秒経過でサーボを元に戻す処理にした。


void setup() {
  WiFi.mode(WIFI_AP);
  WiFi.softAP(ssid, password, channel, ssid_hidden);
  WiFi.onEvent(WiFiEvent);  
}

void WiFiEvent(WiFiEvent_t event) {
  switch (event) {
    case WIFI_EVENT_STAMODE_GOT_IP:
      Serial.println("WiFi connected. IP address: " + String(WiFi.localIP().toString()) + " hostname: " + WiFi.hostname() + "  SSID: " + WiFi.SSID());
      break;
    case WIFI_EVENT_STAMODE_DISCONNECTED:
      Serial.println("WiFi client lost connection");
      break;
    case WIFI_EVENT_STAMODE_CONNECTED:
      Serial.println("WiFi client connected");
      break;
    case WIFI_EVENT_STAMODE_AUTHMODE_CHANGE:
      Serial.println("WiFi client authentication mode changed.");
      break;
    //case WIFI_STAMODE_DHCP_TIMEOUT:                             //THIS IS A NEW CONSTANT ENABLE WITH UPDATED SDK
    //    Serial.println("WiFi client DHCP timeout reached.");
    //    break;
    case WIFI_EVENT_SOFTAPMODE_STACONNECTED:
      Serial.println("WiFi accesspoint: new client connected. Clients: "  + String(WiFi.softAPgetStationNum()));
      break;
    case WIFI_EVENT_SOFTAPMODE_STADISCONNECTED:
      Serial.println("WiFi accesspoint: client disconnected. Clients: " + String(WiFi.softAPgetStationNum()));
      break;
    case WIFI_EVENT_SOFTAPMODE_PROBEREQRECVED:
      Serial.println("WiFi accesspoint: probe request received.");
      break;
  }
}

例の基板をブレイクアウトボードとして利用した。サーボ用の電源を取るために空中配線を行った。

電源はUSBケーブルを分解し、アダプタから常時給電するようにした。

イマイチUSBケーブルのことがよく分かってないので以下は確認した値を記録しておく。

赤をテスターの+端子に繋いだ状態で -端子を

  • 白に繋ぐ → 0V
  • 緑に繋ぐ → 3.3V
  • 黄に繋ぐ → 5V

色に関しては各社USBケーブル毎に違いがあるらしいので注意したい。

ケースを123D Designで設計し、3D出力した。

完成!