
【ESP32プログラム】Bluetoothを使ってみよう!(受信編)
スマートフォンからESP32へ指示を出したり、ESP32同士で通信するのに近距離であればBluetoothがとても便利です。今回はESP32におけるBluetooth通信のうち受信についての紹介をします。
Bluetoothプログラムを他のものに流用しやすくするため、それ以外の部分はできるだけシンプルにしておきます。今回はESP32基盤上の青色LEDを点灯・消灯するようにします。そのためESP32だけで試すことができます。
なお、ESP32基盤上の青色LEDはGPIO2をON/OFFすることで点灯・消灯できます。
プログラム
プログラムのうち重要なところを先に説明します。
それ以外の説明はプログラム内のコメントを参照してください。
SERVICE_UUID と CHARACTERISTIC_UUID
BLE(Bluetooth Low Energy)通信におけるサービスやキャラクタリスティックを識別するためのユニークな識別子です。これらは 任意 に設定できますが、いくつかの注意点があります。
(1)ランダムに生成する
一般的には、16バイト(128ビット)のランダムなUUIDを生成して使用します。UUIDジェネレーター(例: uuidgenerator.net)ようなオンラインツールなどで簡単に生成できます。
(2)規格に従ったUUIDを使用
BLEには、Bluetooth SIG が標準化した 16ビットまたは 32ビットのUUIDもあります(例: 0x180D は心拍数モニタリングサービス)。標準のUUIDを使う場合、特定の用途(心拍、バッテリー状態など)に制限されるので、汎用的な用途には128ビットの独自UUIDを使うのが一般的です。
(3)UUIDの用途
SERVICE_UUID
サービス全体を識別するためのUUID。例えば、モータ制御やセンサデータ転送といった特定の機能を定義する単位です。サービス内には複数のキャラクタリスティックを持つことができます。
CHARACTERISTIC_UUID
サービス内の個々のデータポイントや機能を識別するためのUUID。例えば、1つのサービスでモータAとモータBを制御する場合、それぞれの制御用キャラクタリスティックに別々のUUIDを設定することもできます。
(4)選択基準
ユニーク性が必要
UUIDは、BLE通信で衝突を避けるためにユニークである必要があります。同じアプリケーション内で複数のデバイスを扱う場合でも衝突しないよう、しっかり生成・管理しましょう。
他のデバイスと一致させる
受信側と送信側のUUIDは必ず一致させる必要があります。これが一致しないと接続や通信がうまくいきません。
デバイス名の設定
デバイス名を以下の関数で任意に設定します。BLEDevice::init("ESP32_LED_Control");
他のデバイスから当該のESP32を見つけるのに必要です。
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#define LED_PIN 2 // ESP32の内蔵LEDピン
// サービスとキャラクタリスティックのUUID
#define SERVICE_UUID "4fafc2xx-1fb5-459e-8fcc-c5c9c33191xx"
#define CHARACTERISTIC_UUID "beb548xx-36e1-4688-b7f5-ea07361b26xx"
BLECharacteristic *pCharacteristic;
class MyCallbacks : public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) override {
// 値を取得 (String型を使用)
String value = pCharacteristic->getValue().c_str(); // getValue() は std::string を返すので c_str() で String に変換
// 値に応じて動作
if (value == "ON") {
digitalWrite(LED_PIN, HIGH); // LEDを点灯
Serial.println("LEDを点灯しました");
} else if (value == "OFF") {
digitalWrite(LED_PIN, LOW); // LEDを消灯
Serial.println("LEDを消灯しました");
} else {
Serial.println("不明なコマンドを受信しました: " + value);
}
}
};
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT); // LEDピンを出力モードに設定
digitalWrite(LED_PIN, LOW); // 初期状態でLEDを消灯
// BLEデバイスの初期化
BLEDevice::init("ESP32_LED_Control"); // デバイス名を設定
BLEServer *pServer = BLEDevice::createServer();
// サービスを作成
BLEService *pService = pServer->createService(SERVICE_UUID);
// キャラクタリスティックを作成
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
// キャラクタリスティックに初期値を設定
pCharacteristic->setValue("Waiting for command...");
pCharacteristic->setCallbacks(new MyCallbacks());
// サービスを開始
pService->start();
// BLE広告を開始
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->start();
Serial.println("BLEデバイスが起動しました。iPhoneで接続してください。");
}
void loop() {
// 特に処理は不要。BLEはバックグラウンドで動作します。
}
実行してみよう
私はスマホからBluetoothでESP32に送信するのに「BLE Scanner」というアプリを使いました。
アプリを起動したら、「ESP32_LED_Control」を選択します(図1の「Connect」を押す)。これは今回、私が設定したものですので、皆さんの設定したものを選択してください。

「CUSTOM CHARACTERISTIC」の「W」を押します(図2)。
ESP32に指令(WRITE)するためです。

図3のように出てきたダイアログボックスにONと入力して「OK」を押すとESP32の基盤上のLEDが点灯します。図4のように「OFF」と入力して「OK」を押すと消灯します。


購入部品
最新情報は「電子工作お買い物一覧」の記事を参照ください。
リンク切対応や代替部品の紹介もしています。