ハイハイ店番を改造してAppleWatchに来店を通知

店の奥で機械作業をしているとドアチャイムが聞こえず、お客さんを無駄に長く待たせてしまうことがあるのでこれをなんとかします。そこで来店があった際にかAppleWatchから通知が来るようにしました。ナショナル製(現Panasonic)ハイハイ店番改造します。

検知器(人感センサー) -> 本体ドアチャイム(ハイハイ店番) ->センサー出力整形 -> AVRマイコンESP-WROOM-02 -> Wifi -> IFTTT -> AppleWatchの流れ

検知器(人感センサー)

赤丸の部分が30年前から設置されている検知器。店の奥にある事務所エリアにある本体と有線接続されています
検知器
センサーとつながっているドアチャイムユニット「ハイハイ店番」本体。右の小さい基盤は今回製作のもの
本体のカバーを外した様子。端子台から+12V、GND、センサー出力を取り出してマイコンボードに接続します

自動ドアの人感センサーは店の事務所区画に設置されているドアチャイムユニット「ハイハイ店番」にGND、+12V、センサー出力の3本でつながっています。

センサー出力整形

検知器からの出力は無人の状態で0V、赤外線を感知すると+10Vとなっています。マイコンに入力できる信号レベルは最大で5Vなので、検知器からの出力をCMOSシュミットトリガ4584で0-12Vの矩形に整形した後に74HC4049で0-5Vの電圧にレベルシフトさせています。

電源は「ハイハイ店番」からの12Vを利用しています。マイコンとレベルシフタに使う5Vは7805ではなくDC-DCコンバータBP5293-50を使用してみました。三端子レギュレータとくらべて部品点数が減り待機消費電力も控えめということで非常に便利です。

AVRマイコン ESP-WROOM-02

ESP-WROOM-02

電源はUSBからではなく基板の10番ピンに対して外部から5Vを加えることになります。
その際ハマったのは基板上のチップダイオードD1を外して短絡しないとマイコンが動作しないということでした。
秋月電子の商品Q&Aページにも記載があり、「5V0端子を使用しなければいけない場合はD1を取り外し短絡することで外部電源使用時でも正常に起動できるようになります。
外部電源とUSB-UART接続を併用する場合はD1を取り外してください」とのことで、その通りに修正を加えたらUSB電源と外部電源どちらを使用しても動作するようになりました。

Wi-fi

プログラム製作にあたってはこちらを参考ベースにさせていただいて自分なりの変更を加えています。IFTTTサーバの接続[client.connect(IFTTT_HOST_NAME, httpPort)]はメインループを回るたびに行うのではなくセンサー出力が発生した時だけ行うようにしています。

店の営業時間中にはドアセンサーからの電圧を監視し、ドアが開いてセンサー入力ピンが0VになったらIFTTTに接続してトリガURLをリクエストします。一回ドアが開いたらその後20秒間は何も反応をしないようにしました。

コンパイルをする際、連続して2回ビルドしないとエラーが発生しますが特に気にもせずに使っています。

#include <ESP8266WiFi.h>
//日本時間
#define JST     3600*9

// 転送レート
#define SERIAL_SPEED  115200

// Wi-Fi SSID
#define WLAN_SSID         "****************"
// Wi-Fi パスワード
#define WLAN_PASS         "****************"

IPAddress ip(XXXXXXXXXXXXXXXX); //ip
IPAddress gateway(XXXXXXXXXXXXXXXXX);
IPAddress subnet(XXXXXXXXXXXXXXX);
IPAddress DNS(XXXXXXXXXXXXXXXX);

// IFTTTのイベント名
#define IFTTT_EVENT_NAME  "DoorOpen"

// IFTTTのホスト名
#define IFTTT_HOST_NAME   "maker.ifttt.com"

// IFTTTのシークレットキー
#define IFTTT_KEY         "XXXXXXXXXXXXXXXXXX"

// ポート番号
#define PORT_NUMBER       80

// 人感センサー入力
const int sensorPin = 12;

// LED接続
const int ledPin = 16;

// HTTP接続ポート番号
const int httpPort = 80;

char sendData[256] = "";

int ct;

time_t t;
struct tm *tm;
static const char *wd[7] = {"Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat"};
WiFiClient client;

void setup() {

  // 入出力ピン設定
  pinMode(sensorPin, INPUT);
  pinMode(ledPin, OUTPUT);

  Serial.begin(SERIAL_SPEED);

  // Wi-Fi設定
  setupWiFi();

  configTime( JST, 0, "ntp.nict.jp", "ntp.jst.mfeed.ad.jp");
  t = time(NULL);
  tm = localtime(&t);
  Serial.printf(" %04d/%02d/%02d(%s) %02d:%02d:%02d\n",
                tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
                wd[tm->tm_wday],
                tm->tm_hour, tm->tm_min, tm->tm_sec);
}

void setupWiFi() {
  Serial.begin(115200);
  Serial.print("Connecting to ");
  Serial.println(WLAN_SSID);
  WiFi.config(ip, gateway, subnet, DNS); //static_ip
  WiFi.begin(WLAN_SSID, WLAN_PASS);
  while (WiFi.status() != WL_CONNECTED) {
    delay(3000);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  for(int i=0; i <=15; i++){
    digitalWrite(ledPin,HIGH);
    delay(50);
    digitalWrite(ledPin,LOW);
    delay(50);
  }
}

void loop() {

  delay(100);
  t = time(NULL);
  tm = localtime(&t);

  // 営業時間内ならIFTTTへデータを送信
  if (9 <= tm->tm_hour and tm->tm_hour < 19 ) {
    // 人感センサーの状態を取得
    int sensorState = digitalRead(sensorPin)
    if (sensorState == LOW) {    // ドアオープン処理
      
        Serial.println("Door open detected.");
        Serial.print("connecting to ");
        Serial.println(IFTTT_HOST_NAME);
      
        if (!client.connect(IFTTT_HOST_NAME, httpPort)) {//IFTTTへの接続失敗
          Serial.println("connection failed");
          Serial.println("wait 5 sec...");
          for(int i=0; i<50;i++){
          digitalWrite(ledPin,HIGH);
          delay(100);
          digitalWrite(ledPin,LOW);
          }
        }else{ //IFTTTへの接続成功
          Serial.printf(" %04d/%02d/%02d(%s) %02d:%02d:%02d\n",
              tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
              wd[tm->tm_wday],
              tm->tm_hour, tm->tm_min, tm->tm_sec);
          sprintf(sendData, "GET http://maker.ifttt.com/trigger/%s/with/key/%s HTTP/1.1\r\nHost:maker.ifttt.com\r\nConnection: close\r\n\r\n", IFTTT_EVENT_NAME, IFTTT_KEY);
          Serial.println(sendData);
          client.print(sendData);
          digitalWrite(ledPin, HIGH);
          delay(30000); //20秒待つ
          digitalWrite(ledPin, LOW);
          sensorState = digitalRead(sensorPin);
          while(sensorState == LOW) //センサーOFFを待つ
          {
            delay(100);
          }
        }//IFTT接続成功時処理終了
    }//センサー反応時処理終了
  }//営業時間時処理終了
}

IFTTT

今回の設定は

If Maker Event “DoorOpen”, then Send a notification from the IFTTT app

という内容にしています。プログラム上で所定のトリガURLにアクセスするとIFTTTアプリが通知を発行します。

Apple Watch

AppleWatchにIFTTTアプリをインストールしておけばあとは通知が届くようになります。特に設定上で難しい部分はありませんでした。

ドアが開いてからおよそ3秒の何とも微妙なタイムラグを経て腕時計が振動してくれます。