CodedPhyとは?
低スピードで長距離を飛ばす設定であり、50m~100m程度飛ばせる機能です。CodedPhyの機能がESP32S3で試せることがわかっていたのですが、成功している人がほとんどいなかったので、調べながら実行しました。
ESP32S3で実行した結果
適当に試しただけですが、50m~70mくらいは飛ばせました。通常Bluetoothはせいぜい20mくらい繋がっていればいいくらいのイメージでしたので、かなり長距離飛ばせるのだなあというのが素直な感想です。
コードについて
少しハマりどころもありましたので、platformIOで実行したコードはこちらに上げておきます。Espressif-idfのv5.4では修正されていますので、2025年1月リリースではうまく動くであろうと考えられますので、その時期になったら、再度試してみたいと思います。
Client
#include <Arduino.h>
#include "BLEDevice.h"
#include <esp_gap_ble_api.h>
#define SERVER_BLE_NAME "ESP32_BLE_Server" // 接続するサーバー名
#define SERVICE_UUID "12345678-1234-5678-1234-56789abcdef0"
#define CHARACTERISTIC_UUID "87654321-4321-6789-4321-abcdef012345"
BLEClient* pClient = NULL;
BLERemoteCharacteristic* pRemoteCharacteristic = NULL;
BLEAddress serverAddress = BLEAddress("24:0A:C4:00:00:00");
static void gapEventHandler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param) {
if (event == ESP_GAP_BLE_READ_PHY_COMPLETE_EVT) {
if (param->phy_update.status == ESP_BT_STATUS_SUCCESS) {
Serial.println("PHY情報取得完了:");
Serial.print("Tx PHY: ");
Serial.println(param->phy_update.tx_phy);
Serial.print("Rx PHY: ");
Serial.println(param->phy_update.rx_phy);
} else {
Serial.print("PHY情報の取得に失敗しました: ");
Serial.println(param->phy_update.status);
}
}
}
// データ受信コールバック
static void notifyCallback(BLERemoteCharacteristic* pBLERemoteCharacteristic,
uint8_t* pData, size_t length, bool isNotify) {
String receivedData = String((char*)pData).substring(0, length);
Serial.print("受信データ: ");
Serial.println(receivedData);
// remote address
// typedef uint8_t esp_bd_addr_t[ESP_BD_ADDR_LEN];
Serial.print(serverAddress.toString().c_str());
esp_bd_addr_t bd_addr = {0x24, 0x0A, 0xC4, 0x00, 0x00, 0x00}; // ここはサーバーのアドレスを指定
esp_err_t res = esp_ble_gap_read_phy(bd_addr);
Serial.println(res);
}
void setup() {
Serial.begin(115200);
Serial.println("ESP32 BLE クライアント - データ受信開始");
// BLEデバイス初期化
BLEDevice::init("");
// BLEスキャン設定
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan->setActiveScan(true);
BLEScanResults foundDevices = pBLEScan->start(5);
// サーバー検索
for (int i = 0; i < foundDevices.getCount(); i++) {
BLEAdvertisedDevice device = foundDevices.getDevice(i);
if (device.getName() == SERVER_BLE_NAME) {
Serial.println("サーバーを発見しました。接続中...");
pClient = BLEDevice::createClient();
serverAddress = device.getAddress();
if (pClient->connect(&device)) {
Serial.println("サーバーに接続しました!");
// サービスとキャラクタリスティックを取得
BLERemoteService* pRemoteService = pClient->getService(SERVICE_UUID);
if (pRemoteService) {
pRemoteCharacteristic = pRemoteService->getCharacteristic(CHARACTERISTIC_UUID);
if (pRemoteCharacteristic) {
Serial.println("キャラクタリスティックを取得しました。");
pRemoteCharacteristic->registerForNotify(notifyCallback);
}
}
}
break;
}
}
esp_err_t res = esp_ble_gap_register_callback(gapEventHandler);
Serial.println(res);
}
void loop() {
if (pClient && pClient->isConnected()) {
delay(1000); // 接続維持
} else {
Serial.println("サーバー接続が切れました。再試行します...");
setup();
}
}
Server
#include <Arduino.h>
#include "BLEDevice.h"
#include <esp_gap_ble_api.h>
#define DEVICE_NAME "ESP32_BLE_Server" // サーバーデバイス名
#define SERVICE_UUID "12345678-1234-5678-1234-56789abcdef0"
#define CHARACTERISTIC_UUID "87654321-4321-6789-4321-abcdef012345"
BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;
bool deviceConnected = false;
// 接続状態を検知するコールバック
class MyServerCallbacks : public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
Serial.println("クライアントが接続しました!");
deviceConnected = true;
}
void onDisconnect(BLEServer* pServer) {
Serial.println("クライアントが切断しました。");
deviceConnected = false;
BLEDevice::startAdvertising(); // 広告を再開
}
};
void setup() {
Serial.begin(115200);
Serial.println("ESP32 BLE サーバー - データ送信開始");
// BLEデバイス初期化
BLEDevice::init(DEVICE_NAME);
// サーバーとサービスの作成
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
BLEService* pService = pServer->createService(SERVICE_UUID);
// キャラクタリスティック作成(Notifyのみ)
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_NOTIFY
);
esp_err_t res = esp_ble_gap_set_prefered_default_phy(ESP_BLE_GAP_PHY_CODED_PREF_MASK, ESP_BLE_GAP_PHY_CODED_PREF_MASK);
if (res == ESP_OK) {
Serial.println("PHY設定成功");
} else {
Serial.println("PHY設定失敗");
}
// サービス開始
pService->start();
// 広告の開始
BLEAdvertising* pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
BLEDevice::startAdvertising();
Serial.println("BLE広告を開始しました。");
}
void loop() {
static int count = 0; // 送信カウンタ
if (deviceConnected) {
String message = "Count: " + String(count++); // 送信するデータ
pCharacteristic->setValue(message.c_str());
pCharacteristic->notify(); // データを送信
Serial.println("送信データ: " + message);
}
delay(1000); // 1秒ごとにデータ送信
}
ハマりどころとしては、esp_ble_gap_set_prefered_phyの関数は動きませんでした。
変わりに、esp_ble_gap_set_prefered_default_phyを設定することで、設定できました。
コメント