はじめての電子工作超入門

第71回 ESP-WROOM-32をArduinoで触ってみよう(Bluetooth-BLE送信編)

IMG_20171215_170202

前回、無事ESP-WROOM-32でBluetooth機能を有効にして、スマホ側でデバイスを認識することができました。今回は実際にスマホとESP-WROOM-32をつなげて、デバイス側からスマホ側にデータを送信してみたいと思います。

今回の電子工作レシピ

完成までの時間目安:60分
必要なパーツ

目次

  1. ESP-WROOM-32からスマホに送信したデータを確認する
  2. ESP-WROOM-32のタッチセンサについて
  3. タッチセンサを利用してスイッチのON/OFFをBluetoothで通知
  4. まとめ

 

1.ESP-WROOM-32からスマホに送信したデータを確認する

ESP-WROOM-32からBluetoothを通じてデータを送信するプログラムは、スケッチのサンプルとして用意されています。
まずはそれを使ってスマホ側にデータを送信して、スマホ側でそのデータがきちんと受信できているか確認してみましょう。
Bluetoothのデータをそのまま確認することができるアプリは複数あります。今回は「BLE Scanner」というアプリで確認してみます。

blescanner

BLE Scanner(Android/iOS)

BLE Scannerをインストールして開くと、近くにあるBluetooth端末が表示されて、「CONNECT」ボタンで接続できるようになっています。ESP-WROOM-32にデータ送信サンプルのプログラムを書き込んだ状態でBLE Scannerを起動するとデバイスとして確認できますので、実際にCONNECTで接続してみます。

vol-5

書き込むサンプルプログラムはArduinoIDEの「ファイル」-「スケッチ例」-「ESP32 BLE Arduino」-「BLE_notify」です。

BLE送信用のサンプルプログラム

/*
    Video: https://www.youtube.com/watch?v=oCMOYS71NIU
    Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleNotify.cpp
    Ported to Arduino ESP32 by Evandro Copercini

   Create a BLE server that, once we receive a connection, will send periodic notifications.
   The service advertises itself as: 4fafc201-1fb5-459e-8fcc-c5c9c331914b
   And has a characteristic of: beb5483e-36e1-4688-b7f5-ea07361b26a8

   The design of creating the BLE server is:
   1. Create a BLE Server
   2. Create a BLE Service
   3. Create a BLE Characteristic on the Service
   4. Create a BLE Descriptor on the characteristic
   5. Start the service.
   6. Start advertising.

   A connect hander associated with the server starts a background task that performs notification
   every couple of seconds.
*/
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

BLECharacteristic *pCharacteristic;
bool deviceConnected = false;
uint8_t value = 0;

// See the following for generating UUIDs:
// https://www.uuidgenerator.net/

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"


class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;
    };

    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;
    }
};



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

  // Create the BLE Device
  BLEDevice::init("MyESP32");

  // Create the BLE Server
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  // Create the BLE Service
  BLEService *pService = pServer->createService(SERVICE_UUID);

  // Create a BLE Characteristic
  pCharacteristic = pService->createCharacteristic(
                      CHARACTERISTIC_UUID,
                      BLECharacteristic::PROPERTY_READ   |
                      BLECharacteristic::PROPERTY_WRITE  |
                      BLECharacteristic::PROPERTY_NOTIFY |
                      BLECharacteristic::PROPERTY_INDICATE
                    );

  // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
  // Create a BLE Descriptor
  pCharacteristic->addDescriptor(new BLE2902());

  // Start the service
  pService->start();

  // Start advertising
  pServer->getAdvertising()->start();
  Serial.println("Waiting a client connection to notify...");
}

void loop() {

  if (deviceConnected) {
    Serial.printf("*** NOTIFY: %d ***\n", value);
    pCharacteristic->setValue(&value, 1);
    pCharacteristic->notify();
    //pCharacteristic->indicate();
    value++;
  }
  delay(2000);
}

プログラムのアップロードをして、実行した状態でBLE Scannerを起動してみてください。「MyESP32」という名称でデバイスが認識できると思います。

vol71-4

何やらいろいろ英語の文字が出てくるかと思いますが、その中で「CUSTOM SERVICE」という項目をタップしてください。
詳細情報が表示されて、R、W、N、Iといった文字が出てくると思いますが、そのR(Read)をクリックするとESP-WROOM-32から送られてきたデータを見ることができます。サンプルプログラムでは2秒ごとに1ずつカウントした値を送信するようなプログラムになっているので、Rを再度押すとValueの値が増えていることが確認できると思います。

db6c99d182d45c2e6d25f6169e355608

このように、ESP-WROOM-32からBluetooth端末側にデータを手軽に送ることができます。

 

2.ESP-WROOM-32のタッチセンサについて

実はESP-WROOM-32にはBluetoothやWi-Fiの他、デフォルトで内蔵されている様々なセンサ機能を利用することができます。
主な利用できるセンサは下記のとおりです。

・ホールセンサ
・温度センサ
・タッチセンサ

今回はタッチセンサを使って、Bluetoothと組み合わせてみたいと思います。
タッチセンサは、今では当たり前となったスマホの画面などに使われています。この主な仕組みとしては静電容量方式という方式で、人体とデバイスの電極の間に発生する静電容量の変化を読み取り、入力のオンオフを検知する方法です。
ESP-WROOM-32ではタッチセンサとして利用できるピンが複数あるので、それをうまく使うことで静電入力式のパネルなども作成することができます。

データシート参照(2.Pin DefinitionsにTouchとして利用できるピンが記載)

 

2-1.タッチセンサを使ってみる

ArduinoIDEの「ファイル」-「スケッチ例」-「ESP 32」-「Touch」-「TouchRead」のサンプルを呼び出してください。
このプログラムでは、T0(4番ピン)の入力値をシリアルモニタに表示する内容になっています。このプログラムをESP-WROOM-32に書き込んで実行すると、T0(4番ピン)に触れたときに、シリアルモニターの値が変化することが確認できます。
T0(4番ピン)に入力された数値の変化をON/OFFに利用したりすることでタッチセンサとして機能させることができます。

タッチセンサのサンプルプログラム

// ESP32 Touch Test
// Just test touch pin - Touch0 is T0 which is on GPIO 4.

void setup()
{
  Serial.begin(115200);
  delay(1000); // give me time to bring up serial monitor
  Serial.println("ESP32 Touch Test");
}

void loop()
{
  Serial.println(touchRead(T0));  // get value using T0
  delay(1000);
}

vol71-6

 

3.タッチセンサを利用してスイッチのON/OFFをBluetoothで通知

タッチセンサの入力が確認できたので、この処理をBluetooth通信側のプログラムに組み込みます。
Bluetoothにつながった状態のときに、T0(4番ピン)を触れるとスイッチがON、スイッチが入っている時にT3(14番ピン)を触れるとスイッチがOFFになるような処理にしてみます。

スイッチのON/OFFが分かりやすいようにLEDをつけておきます。Bluetooth接続の際には、12,13番ピンはBluetooth側で利用されているため、LED出力用には14番ピンを指定しています。(12,13番ピンなどを指定するとコンパイルや書き込みは成功しますが、エラーになってしまいます)

vol71-3

スイッチON/OFFのBluetooth送信プログラム

/*
    Video: https://www.youtube.com/watch?v=oCMOYS71NIU
    Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleNotify.cpp
    Ported to Arduino ESP32 by Evandro Copercini

   Create a BLE server that, once we receive a connection, will send periodic notifications.
   The service advertises itself as: 4fafc201-1fb5-459e-8fcc-c5c9c331914b
   And has a characteristic of: beb5483e-36e1-4688-b7f5-ea07361b26a8

   The design of creating the BLE server is:
   1. Create a BLE Server
   2. Create a BLE Service
   3. Create a BLE Characteristic on the Service
   4. Create a BLE Descriptor on the characteristic
   5. Start the service.
   6. Start advertising.

   A connect hander associated with the server starts a background task that performs notification
   every couple of seconds.
*/
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

BLECharacteristic *pCharacteristic;
bool deviceConnected = false;
uint8_t value = 0;

bool ledFlg = false;

// See the following for generating UUIDs:
// https://www.uuidgenerator.net/

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"


class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;
    };

    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;
    }
};



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

  pinMode(14, OUTPUT);  

  // Create the BLE Device
  BLEDevice::init("MyESP32");

  // Create the BLE Server
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  // Create the BLE Service
  BLEService *pService = pServer->createService(SERVICE_UUID);

  // Create a BLE Characteristic
  pCharacteristic = pService->createCharacteristic(
                      CHARACTERISTIC_UUID,
                      BLECharacteristic::PROPERTY_READ   |
                      BLECharacteristic::PROPERTY_WRITE  |
                      BLECharacteristic::PROPERTY_NOTIFY |
                      BLECharacteristic::PROPERTY_INDICATE
                    );

  // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
  // Create a BLE Descriptor
  pCharacteristic->addDescriptor(new BLE2902());

  // Start the service
  pService->start();

  // Start advertising
  pServer->getAdvertising()->start();
  Serial.println("Waiting a client connection to notify...");

}

void loop() {

  if (deviceConnected) {
    int t0val  = touchRead(T0);  // get value using T0 - IO04
    int t3val  = touchRead(T3);  // get value using T3 - IO15
    bool flg = false;

    if(t0val < 70 && !ledFlg){
      //switch on
      digitalWrite(14,HIGH);
      flg = true;
      ledFlg = true;
      value = 1;
      Serial.println("*** SWITCH ON ***");
    }
    if(t3val < 70 && ledFlg){
      //switch off
      digitalWrite(14,LOW);
      flg = true;
      ledFlg = false;
      value = 0;
      Serial.println("*** SWITCH OFF ***");
    }

    if(flg){
      pCharacteristic->setValue(&value, 1);
      pCharacteristic->notify();
      //pCharacteristic->indicate();
      //value++;
    }

  }
  delay(2000);
}

実際に動作させてみた動画です。タッチセンサとして利用するピンにさしたジャンパケーブルを触れると静電容量が変わって入力の切り替えができていることがわかると思います。(動画の字幕をONにすると説明がでます)

スマホ側の数値も変更されていることが確認できますね。このタッチセンサがいいところは、ワイヤーの通電している金属部分を直接触らせなくても入力ができるので、防水加工をして手軽なスイッチに利用、などなどさまざまな可能性を感じることができますね。

 

 

まとめ

ESP-WROOM-32からスマホにデータを送ることができました。実際には、この応用として、AndroidやiOSでアプリを作成して、Bluetoothからの値をサーバーに送信してほかのサービスに連携させたり(以前紹介したIFTTTなど)すると、ESP-WROOM-32を手軽にIoTリモコンとして使うことができちゃいますね。

スマホでコントロールできるロボットを作ろう
赤川シホロ

電子工作や新しいデバイスをこよなく愛するエンジニア。日常生活のちょっとしたことを電子工作で作って試して、おもしろく過ごしたいと日々考えています。