Bluetooth接続をしてみる | arduino ESP32ロボットプログラミング

2023年12月15日

クムクムロボット Qumcum PRO、SEにはメインプロセッサーにESP32が使われています。このプロセッサーは最大内部240MHzのクロックで動作していて、WiFi通信やBluetoothでの通信ができる機能が内蔵されています。Bluetoothでは最新のBLEも使えます。ここではこのBLEの機能を使って、クムクムロボットとスマートフォンの間で通信の実験をしてみます。それを拡張すればスマートフォンからクムクムを動作させることも可能です。

Bluetooth と BLE概要

クムクムロボットのCPU、ESP32にはBluetoothの機能が内蔵されていますが、このBluetoothと一般に呼ばれているものは、従来のBluetoothとBLE(Bluetooth Low Energy)と呼ばれるIoT機器向けの通信の2種類があります。

※写真のCPUがESP32で、小さなアンテナが見えています。ここから電波を送受信します。

 

BluetoothとBLE

従来からのBluetoothは、主にワイヤレススピーカーやイヤフォン、スマートフォンとカーナビ接続などで、音声や音楽のデータをやり取りする目的で使われていました。

このマークがついているのがBluetoothです。正確にはバージョンが複数ありますが、通常販売されている機器では、バージョン5.x になっていると思われますし、バージョン4.xとの互換性もありますのであまり気にする必要はありません。というのも昨今においてはBluetoothと言うのはほぼBluetooth Low Energy つまり BLE のことを指しています。Bluetooth と BLE は直接的には互換性はありません。最大の特徴は Low Energy なことなので、電池駆動するようなデバイスはほとんどの場合 BLE を使っています。このBLEはBluetooth バージョン4から搭載されています。

ESP32も最新のチップではBluetoothバージョン5をサポートしています。ソフトウエアから見ればEspressif社が用意しているSDKで細かな違いは吸収されていますので、使えるAPIとしては同じです。

 

クムクム基板でBLE

では実際にクムクムを使ったBLEの通信をしてます。とは言っても通信である以上通信する相手が必要です。いろんな通信相手を考えるのは応用の段階なのでここでは、既存のBLEアプリを使ってみます。

 

スマートフォンの準備

スマートフォンのアプリでBLEを直接扱えるアプリが複数ありますが、広告などの煩わしいものを除いておすすめは、「BLE Scanner」と「nRF Connect for Mobile」です。前者はBluepixcel Technologies、後者はNordic Semiconduntor社なのでどちらも安心して使えそうです。

ここでは直感的に使いやすそうな 「BLE Scanner」を例にします。

 

インストール

スマートフォンのアプリで「BLE Scanner」を検索してインストールしてください。スマートフォンの操作はここでは省略します。起動すると以下の画面がでます。

Bluetooth機器を触ったことがある方なら直感的に理解できると思いますが、この画面は周辺のBluetooth機器のScan結果の画面です。緑の[CONNECT]をクリックすれば相手と接続することができます。

 

一番簡単なサンプル

何が一番簡単かと探してみましたが、やはりスケッチ例で実験してみることかと思いますので、それをそのまま使ってみます。

[ファイル]-[スケッチ例]-[ESP32 BLE Arduino]-[BLE_write]を選択します。

 

Arduino IDEのデバイスは、[ボード: ESP32-DevModule] を確認してください。

このサンプルをそのままコンパイル、書き込みします。

サンプルからさらに不必要な部分を削除すると以下の分量のコードだけです。

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"


class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string value = pCharacteristic->getValue();
      if (value.length() > 0) {
        Serial.print("New value: ");
        for (int i = 0; i < value.length(); i++)
          Serial.print(value[i]);
        Serial.println();
      }
    }
};


void setup() {
  Serial.begin(115200);
  BLEDevice::init("MyESP32");
  BLEServer *pServer = BLEDevice::createServer();
  BLEService *pService = pServer->createService(SERVICE_UUID);
  BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID,
                                         BLECharacteristic::PROPERTY_READ |
                                         BLECharacteristic::PROPERTY_WRITE
                                       );
  pCharacteristic->setCallbacks(new MyCallbacks());
  pCharacteristic->setValue("Hello World");
  pService->start();
  BLEAdvertising *pAdvertising = pServer->getAdvertising();
  pAdvertising->start();
}


void loop() {
  delay(2000);
}

Arduino IDEで書き込み後、ESP32がリセットしたあと、スマートフォンの「BLE Scanner」を見てみると、[MyESP32] というデバイスがスキャンされて上図のように見えていると思いますので、[CONNECT]をクリックしてください。すると画面が切り替わり以下のような表示になります。この画面は、[CUSTOM SERVICE]をクリックした後の画面です。

 

 の (R)READ をクリックします。

コードにある pCharacteristic->setValue("Hello World");

で送信された Hello World が見えていればサンプルは正常に動作しています。

では次に、Arduino IDEの[シリアルモニタ] を開きます。

そして「BLE Scanner」の(W)をクリックすると以下の画面で送信するTEXTを入力する画面がになりますので、適当な文字列、ここでは [abc] と書き込んで [OK] をクリックします。

すると、PCのシリアルモニタに [abc] と表示され、ESP32がスマートフォンからのデータを受信したことがわかります。

これで、クムクムのESP32 からスマートフォンへデータ送信、スマートフォンからクムクムへデータを送信、両方向から送信そして受信できたことになります。

 

クムクムをBLEで制御

ここまでできれば後はスケッチを拡張してクムクムロボットをスマートフォンから制御してみます。

※ここでのプログラムは何かのエラーなどには一切対応していませんので、動作がおかしくなった場合はクムクムの電源をとUSBケーブルを抜いてリセットしてください。

 

クムクムのLEDを制御

クムクムにはRGB3色のLEDが搭載されていますので、それぞれを点灯、消灯するコマンドを考えてみます。

仕様は以下の通りとします。

文字 ’c’ で全LED消灯

’r’ で赤、’g’ で緑、’b’ で青LEDを点灯

では、コードを拡張してみます。

std::string value;
bool bReceived=false;

受信文字列格納用 string value と受信完了フラグ bool bReceived  変数を2つ用意します。

void onWrite(BLECharacteristic *pCharacteristic) {
  value = pCharacteristic->getValue();
  if (value.length() > 0) {
    Serial.println(value.c_str());
    bReceived=true;
  }
}

受信時callback関数で受信完了フラグと受信文字列をシリアルモニタにも表示します。

pinMode(LED_RED, OUTPUT);
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_BLUE, OUTPUT);

setup()内の馴染みのLEDの初期設定です。

if(bReceived){
  if(value.find("r")!=-1)
    digitalWrite(LED_RED,HIGH);
  if(value.find("g")!=-1)
    digitalWrite(LED_GREEN,HIGH);
  if(value.find("b")!=-1)
    digitalWrite(LED_BLUE,HIGH);
  if(value.find("c")!=-1){
    digitalWrite(LED_RED,LOW);
    digitalWrite(LED_GREEN,LOW);
    digitalWrite(LED_BLUE,LOW);
  }
bReceived=false;
}

loop()内で、受信文字列の中にキーとなる文字 ‘r’ ‘g’ ‘b’ ‘c’ のどれかが含まれるか検索してそれぞれの場合のLEDを点灯、消灯させています。

全体は以下の通りです。

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
#define LED_RED 32
#define LED_GREEN 27
#define LED_BLUE 33

std::string value;
bool bReceived=false;

class MyCallbacks: public BLECharacteristicCallbacks {
  void onWrite(BLECharacteristic *pCharacteristic) {
    value = pCharacteristic->getValue();
    if (value.length() > 0) {
      Serial.println(value.c_str());
      bReceived=true;
    }
  }
};

BLECharacteristic *pCharacteristic;
void setup() {
  Serial.begin(115200);
  BLEDevice::init("MyESP32");
  BLEServer *pServer = BLEDevice::createServer();
  BLEService *pService = pServer->createService(SERVICE_UUID);
  pCharacteristic = pService->createCharacteristic(
  CHARACTERISTIC_UUID,
  BLECharacteristic::PROPERTY_READ |
  BLECharacteristic::PROPERTY_WRITE
  );
  pCharacteristic->setCallbacks(new MyCallbacks());
  pService->start();
  BLEAdvertising *pAdvertising = pServer->getAdvertising();
  pAdvertising->start();

  pinMode(LED_RED, OUTPUT);
  pinMode(LED_GREEN, OUTPUT);
  pinMode(LED_BLUE, OUTPUT);
}

void loop() {
  if(bReceived){
    if(value.find("r")!=-1)
      digitalWrite(LED_RED,HIGH);
    if(value.find("g")!=-1)
      digitalWrite(LED_GREEN,HIGH);
    if(value.find("b")!=-1)
      digitalWrite(LED_BLUE,HIGH);
    if(value.find("c")!=-1){
      digitalWrite(LED_RED,LOW);
      digitalWrite(LED_GREEN,LOW);
      digitalWrite(LED_BLUE,LOW);
    }
    bReceived=false;
  }
}

 

スマートフォン側の操作

「BLE Scanner」を起動すると [MyESP32] がスキャンされますので [CONNECT] をクリックし、

(W)をクリックします。

このText入力文字列に、 ‘r’ ‘g’ ‘b’ ‘c’  を含んだ文字列を入力して [OK] すれば、送信した文字列に応じてクムクムのLEDが動作します。

この拡張サンプルからさらに拡張すればモーター制御なども同じようにできると思います。スマホ側のアプリはやはり専用アプリが無いと使い難いですが、実験としてクムクムを動作させるためであればこのBLE Scannerなどのアプリでもまずまず使えるではないでしょうか。