ESP32 Arduino開発 #4 総集編|鍵置き忘れ装置っぽいものを作る

ESP32 Arduino開発 #4 総集編|鍵置き忘れ装置っぽいものを作る

今回はESP32を使って、今までのBLE制御とIO制御とPWM制御を組み合わせたプログラムを作成してみたいと思います。

手順も記載してますので、ぜひ実践してみてください。

概要

やりたいこと

鍵置き忘れ装置っぽいものを作りたいと思います。
ボタンの部分には、最終的には受け皿のような形のものを乗せて、この上に車などのカギ(BLEタグ付き)を想定してます。

カギを置き忘れたまま(ボタンが押されていない場合)、鍵が近くにある場合は、ピピッと鳴らします。
カギを置き忘れたまま(ボタンが押されていない場合)、鍵が外に置きっぱなしの状態は、ピーピーピーと鳴らします。

図面・配線

  • タクトSW・・・P15
  • LED赤・・・P19
  • LED緑・・・P18
  • ブザー・・・P2

復習

今回対応する内容は、ほぼ今まで実装してきた機能を組み合わせたプログラム実装になります。
それぞれ部分的な機能を確認したい場合、ご参考ください。

1.BLEタグを検知する

以前、こちらでBLEタグの検知を紹介いたしました。

2.ボタンの状態でLED点灯消灯を切り替える

以前、こちらでボタンとLEDの点灯・消灯方法を紹介いたしました。

3.一定時間ボタンが押されなかったらブザーを鳴らす

以前、こちらでブザーの鳴らし方を紹介いたしました。

実装内容

  • 今回は、ボタンを押していない間だけ、カウンタを増やしていきます。
  • 途中でボタンを押した場合、カウンタをクリアします。
  • カウンタが一定数を超えたら、ブザーを鳴らすようにします。
  • ブザーを鳴らし終わったら、カウンタをクリアします。(ここはお好みで。クリアせずに鳴らし続けてもOKです。)
  • ボタンが押していない間が1分間経過したら、BLEタグを探します。もし見つかったら、ピピッと鳴らします。
  • さらに、BLEタグが見つからないのが5分間経過したら、ピーピーピーと鳴らします。

以下、サンプルコード

※デファイン「DEF_BLE_ADDR」には、監視したいBLEタグのMACアドレスに書き換えてください。
※カウンタの最大値をそれぞれ変えることで、ブザーを鳴らす時間を調整できます。

#include <BLEDevice.h>

#define DEF_BLE_ADDR "05:B3:EC:xx:xx:xx"
#define PIN_SW          15    // ボタンスイッチのピン番号定義
#define PIN_LED_GREEN   18    // 緑LEDのピン番号定義
#define PIN_LED_RED     19    // 赤LEDのピン番号定義
#define PIN_BUZZER      2     // ブザーのピン番号
#define CHANEL_BUZZER   0     // ブザーのチャネル番号
#define SW_ON     0   // ボタンが押された状態。PULLUP(ON/OFF反転)指定の為、ONは1でなく、0で定義
#define SW_OFF    1   // ボタンが押されていない状態。
#define LED_ON    1   // LED点灯
#define LED_OFF   0   // LED消灯
BLEScan* g_pBLEScan;
long g_lRetry;
long g_lCntChkBLE;  // BLEチェックするためのカウンタ
int g_iSwKey;       // 前回SW状態保持用

void setup() {
  Serial.begin(115200);  // ログ出力準備
  BLEDevice::init("");   // BLEデバイス初期化
  g_pBLEScan = BLEDevice::getScan();  // Scanオブジェクト取得
  g_pBLEScan->setActiveScan(false);   // パッシブスキャンに設定
  // ピン情報設定
  pinMode(PIN_SW,INPUT_PULLUP);  // ボタンスイッチのピン番号と、入力(INPUT)を指定
  pinMode(PIN_LED_GREEN,OUTPUT);  // LEDのピン番号と、出力(OUTPUT)を指定
  pinMode(PIN_LED_RED,OUTPUT);    // LEDのピン番号と、出力(OUTPUT)を指定
  // ブザー初期化
  ledcSetup(CHANEL_BUZZER, 12000, 8);
  ledcAttachPin(PIN_BUZZER, CHANEL_BUZZER);
  g_lRetry = 0;
  g_lCntChkBLE = 0;
  g_iSwKey = -1;
}
void loop() {
  int iSw;
  bool bBle;
  iSw = getSwLed();     // ボタン状態取得&LED点灯
  if( iSw == SW_OFF && g_lCntChkBLE % 10 == 0 ){ // 1秒ごと
    Serial.print(".");
  }
  if( g_lCntChkBLE >= 600-100 ){ // 60秒ごとBLEタグのチェック
    Serial.println("BLE scaning");
    bBle = scanBLE();   // BLEタグ取得
    if(bBle){
      buzzerShort();    // ピピッと鳴らす
      g_lRetry = 0;
    }
    else{
      Serial.println("BLE no data");
      g_lRetry++;
      if( g_lRetry >= 5 ){  // リトライオーバー時
        buzzerLong();   // ピーピーピーと鳴らす
        g_lRetry = 0;
      }
    }
    g_lCntChkBLE = 0;
  }else{
    g_lCntChkBLE++;
  }
  delay(100);  // 0.1秒ごとwait
}
// 戻り値;bool   true=BLE検知。false=BLE未検知
bool scanBLE(){
  bool bRtn;
  char buf[1024];
  bRtn = false;
  sprintf(buf, "");
  BLEScanResults res = g_pBLEScan->start(10); // スキャン時間10秒
  int nCnt = res.getCount();
  if (nCnt > 20) {    // 上限20件まで検出
    nCnt = 20;
  }
  for (int i = 0; i < nCnt; i++) {    // 検出したBLE件数分ループ
    BLEAdvertisedDevice bledev = res.getDevice(i);
    BLEAddress ble_addr = bledev.getAddress();  // BLEのMACアドレス取得
    std::string ble_name = bledev.getName();    // BLEの名称取得
    // MACアドレスが一致している場合
    if( DEF_BLE_ADDR == ble_addr.toString() ){
      bRtn = true;
      // ログ出力
      sprintf(buf, "name=[%s]; addr=[%s]", ble_name.c_str(), ble_addr.toString().c_str());
      Serial.println(buf);
      break;
    }
  }
  return bRtn;
}
int getSwLed(){
  int iSw;
  iSw = digitalRead(PIN_SW);  // SW状態取得
  if(iSw != g_iSwKey){  // 変化あり
    g_iSwKey = iSw;
    if(iSw == SW_ON){   // SWが押されていたら
      digitalWrite(PIN_LED_GREEN, LED_ON);  // 緑点灯
      digitalWrite(PIN_LED_RED, LED_OFF);   // 赤消灯
      Serial.println("LED GREEN ON");
      // ボタンが押されたら、カウンタクリア
      g_lCntChkBLE = 0;
      g_lRetry = 0;
    }
    else{
      digitalWrite(PIN_LED_GREEN, LED_OFF); // 緑消灯
      digitalWrite(PIN_LED_RED, LED_ON);    // 赤点灯
      Serial.println("LED RED ON");
    }
  }
  return iSw;
}
void buzzerShort(){ // ピピッと鳴らす
    Serial.println("Buzzer BLE");
    // ピピッと鳴らす
    ledcWriteTone(CHANEL_BUZZER, 1049);
    delay(50) ;
    ledcWriteTone(CHANEL_BUZZER, 0);  // 消音
    delay(50) ;
    ledcWriteTone(CHANEL_BUZZER, 1049);
    delay(50) ;
    ledcWriteTone(CHANEL_BUZZER, 0);  // 消音
}
void buzzerLong(){ // ピーピーピーと鳴らす
    Serial.println("Buzzer none BLE");
    // ピーピーピーと鳴らす
    ledcWriteTone(CHANEL_BUZZER, 1049);
    delay(500);
    ledcWriteTone(CHANEL_BUZZER, 0);  // 消音
    delay(500);
    ledcWriteTone(CHANEL_BUZZER, 1049);
    delay(500);
    ledcWriteTone(CHANEL_BUZZER, 0);  // 消音
    delay(500);
    ledcWriteTone(CHANEL_BUZZER, 1049);
    delay(500);
    ledcWriteTone(CHANEL_BUZZER, 0);  // 消音
}

ESP32へ書込み

  • 使用したESP32開発ボードは、「Node MCU ESP32」ですので、メニュー「ツール」-「ボード」の項目は、「NodeMCU-32S」を選択しました。(※1)
  • シリアルポートは、ESP32をUSBでPCと接続すると、COM番号が追加されるので、それを選択します。
  • 書込みは、ツールボックスの「⇒」右矢印ボタンで開始します。
  • ESP32開発ボードの、右側のボタン(IO0)長押しすると、書込み開始するので、直後にボタンを離します。(※2)
  • 書込みが開始されます。

(※1)他のESP32っぽい名前の項目がありますが、書込みできない場合があります。製品のマニュアルをご確認ください。

(※2)機種によって書込み操作が違う場合があります。例えば、IO0ボタン押しながらEN(リセット)ボタンを押さないと書込みできない場合もあります。

実行結果

以下、ログの出力結果になります。

ボタンを押さない間は、ログに「...」を出力してます。
1分後、BLEタグを探します。
見つかった場合は、ピピッと鳴らします。(ログ内容は、Buzzer BLE)

BLEタグを検知できないところまで離して(もしくは電池の抜いて)同じように確認してみましょう。
ボタンを押さないで5分待ちます。
すると、ピーピーピーとブザーが鳴ります。(ログ内容は、Buzzer none BLE)
※上で紹介した1分ごとのブザー(ピピッ)は鳴りません。

今度は、ボタンを押し続けた場合、BLEタグが近くにあった状態で1分以上経過してもブザーは鳴りません。
同じく、BLEタグが近くにない状態で5分以上経過してもブザーは鳴りません。

最後に

今回は、ボタンスイッチでブザーを鳴らすかどうかの判定に利用しておりましたが、このボタンの部分を受け皿のようなかたちに変えれば、カギ置き場として使用することも可能です。

本プログラム内のタイマー時間を調整することで、例えばカギ置場から、鍵を持っていってから1日経過しても戻らない場合、ブザーやログ出力するしくみを作る事も可能になります。
あとブザーは、数分ごと鳴らすスヌーズ機能みたいなかたちにするとかも良いですね。

このように、組み合わせて使う事で、いろいろ応用を利かせることが可能になると思いますので、是非お試しください。
ご参考になれば幸いです。

最後までご覧頂きましてありがとうございました。