Wi-FiマイコンXIAO ESP32S3とAndroidとのBLE Uart通信
(1) ESP32S3単体とAndroidデバイスの通信
(2) ESP32S3+温度センサBMP280とAndroidデバイスの通信

2023.9.28 Coskx Lab  

1 はじめに

温度センサBMP280を載せたWi-FiマイコンXIAO ESP32S3からAndroidスマホに向けてBLE(Bluetooth Low Energy)を使って温度情報を送ります。
Wi-FiマイコンとAndroidスマホ間の通信は無線LAN環境の下ではHTTPでの通信ができますが,無線LAN環境がない場合では,Bluetooth通信が便利です。
XIAO ESP32S3はBLE UART Profileを使って通信します。(Bluetooth Classicではありません。)


BLEコネクション通信では,Central(or Master or Observer)とPeripheral(or Slave or Broadcaster)の間で通信が行われます。
ここでは,AndroidをCentral,XIAO-ESP32S3をPeripheralとして使うことにします。
(PeripheralはServer,CentralはClientと説明されることもあります。)

ESP32 Bluetooth4.2でのBLE通信のペアリングでは,セキュリティに関する記述をしなくてもよかったのですが,ESP32S3 Bluetooth5.0ではセキュリティに関する記述が必要になったようです。記述していないとペアリング出来ず,エラーを通知してきます。
セキュリティの関する記述には次の2つの方法があります。

(1)PIN(暗証番号)を設定する
6桁のPINをESP32S3のプログラム(setup中)に設定しておき,Androidデバイスとペアリングする際におなじPINを入力することでPairingが完了します。(ここではPINは123456の6桁です。PINは6桁にする必要があります。)
(2)PINは設定しないが認証モードを簡易なものに設定する

なお,ここで使用するAndroidの2つのアプリSerial Bluetooth Terminal","Bluefruit Connect"はアプリ起動の度に,通信相手を探して接続するようになっているため,ペアリングを必要としていません。

2 使用環境

3 準備

3.1 ArduinoIDE

(1)Arduino IDEのメニューバーから[ファイルFile] -> [環境設定(Preferences)]
Additional board manager URLsに
https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json
および
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
を設定してOK
(2)ツール[Tools] > ボード[Board] > Boards Manager
検索boxに「ESP」を入力すると複数のボード候補が出てくるので
esp32 by Espressif Systems
をinstall
(3)ツール[Tools] > ボード[Board]でESP32を探すとXIAO ESP32S3が見つかるので,これを選ぶ。

3.2 XIAO ESP32S3

XIAO ESP32S3の説明書を読んでプログラムの転送方法を確認します。
(USBケーブルでつないで書き込むだけでした。)

4 XIAO ESP32S3と温度センサBMP280の配線

(BLE Uart通信のテストだけならBMP280は使用しないので,ここは読み飛ばしてください)

温度センサBMP280は温度をデジタル値に変換しているので,そのデータをXIAO ESP32S3が読み出します。
XIAO ESP32S3と温度センサBMP280はI2C接続ですので,電源線,GND線の他はSCLとSDAの2本のみで通信できます。

CSBをVCCにつなぐとBMP280はI2C接続になります。(データシートによれば確実にVCCにつなぐべきとなっています)
SDO(シルク印刷は間違えていてSDDとなっている)をVCCにつなぐとBMP280のI2Cアドレスは77になります。GNDにつなぐとBMP280のI2Cアドレスは76になります。Groveライブラリのデフォルトは77なのでVCCにつないでいます。

なおBMP280ではSDA,SCLをpullupせずに動作しています。

   XIAO ESP32S3と温度センサBMP280の配線

ブレッドボードには載せないので,XIAO ESP32S3のピンを上向きに付けています。
   XIAO ESP32S3と温度センサBMP280

5 XIAO ESP32S3のスケッチコード(サーバプログラム)

ここでは,
(1)BMP280を使用せず,BLE Uart通信のテストだけのプログラム
(2)BMP280を使用して,BLE Uart通信で温度などの情報を送信するプログラム
の2つを紹介します。

XIAO ESP32S3のスケッチコードは,クライアントがiOSデバイスであってもWindowsPCであっても同じものを使っています。
  iOSデバイス版の解説
  WindowsPC版の解説

5.1 BMP280を使用せず,BLE Uart通信のテスト

プログラムの概要
クライアント(Androidスマホなど)からのリクエストで,サーバであるXIAO ESP32S3は,文字列"Hello"と経過時間を,クライアントに返します。
具体的には,XIAO ESP32S3は文字列"start"を受け取ったら1秒間隔で文字列"Hello"と経過時間を送信し,文字列"stop"を受け取ったら送信をやめるようにします。

説明
UART通信ですので,プログラム中の受信のパートと送信のパートが分かれば,そこにやりたいことを書けばよいことになります。
受信時はclass MyCallbacks: public BLECharacteristicCallbacksのonWrite()が呼び出され,String rxValueに受信文字列が保存されます。
ここが受信のパートになります。
受信パートでは受信文字列が"start","stop"であった時には,作業フラグisrequestedをそれぞれtrue,falseに設定します。

loop()内でdeviceConnected およびisrequestedがtrueで,一定時間が経過したら,送信すべきデータ文字列(文字列"Hello"と経過時間)を作って,送信します。
ここが送信パートになります。

もう少し要点を絞ってみます。
◎受信時は,
 void onWrite(BLECharacteristic *pCharacteristic)
が呼び出されて,
 String rxValue = pCharacteristic->getValue();
で,String型の文字列rxValueに受信文字列が得られます。
◎送信時は,送信したいString型の文字列を
 pTxCharacteristic->setValue();
で送って
 pTxCharacteristic->notify();
で送信相手に送ったよと知らせて完了です。

なお,
 #define DEVICENAME "UART ESP32S3"
は自分の名前です。通信相手のAndroidスマホなどから見つけてもらう名前です。
 #define INTERVAL 1000 //millisec
を変更するとデータ送信間隔が変わります。

 BLESecurity *pSecurity = new BLESecurity();
 pSecurity->setStaticPIN(123456);
上記2行がペアリング時に使われるPINの設定です。PINを設定しない場合は,次の2行に置き換えてください。
 BLESecurity *pSecurity = new BLESecurity();
 pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_ONLY);

次のコードは,Arduino IDEの既存スケッチ例"BLE_uart.ino"を元に作ったものです。
Arduino IDEでコンパイルするときは,ライブラリ"Grove_-_Barometer_Sensor_BMP280"を予めIDEに追加しておいてください。

#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include <Wire.h>

#define DEVICENAME "UART test"
#define INTERVAL 1000 //millisec

// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

BLEServer *pServer = NULL;
BLECharacteristic * pTxCharacteristic;
bool deviceConnected = false;
bool oldDeviceConnected = false;
boolean isrequested = false;
int interval = INTERVAL; //millisec
int currenttime = 0; //millisec
int previoustime = 0; //millisec

class MyServerCallbacks: public BLEServerCallbacks {
  void onConnect(BLEServer* pServer) {
    deviceConnected = true;
    Serial.println("** device connected");
  };

  void onDisconnect(BLEServer* pServer) {
    deviceConnected = false;
    Serial.println("** device disconnected");
  }
};

class MyCallbacks: public BLECharacteristicCallbacks {
  void onWrite(BLECharacteristic *pCharacteristic) {
    String rxValue = pCharacteristic->getValue();

    if (rxValue.length() > 0) {
      //Display on serial monitor for debug
      Serial.println("*********");
      Serial.print("Received Value: ");
      rxValue.trim();
      Serial.println(rxValue);
      Serial.println("*********");
      //Reply as is
      pTxCharacteristic->setValue(rxValue);
      pTxCharacteristic->notify();
      delay(10);

      if (rxValue.indexOf("start") == 0) { //"start" has found
        isrequested = true;
        previoustime = millis(); //elapsed time(ms)
        previoustime -= interval;
      } else if (rxValue.indexOf("stop") == 0) { //"stop" has found
        isrequested = false;
      }
    }
  }
};

void setup() {
  Serial.begin(115200);
  // Create the BLE Device
  BLEDevice::init(DEVICENAME); //BLE Device Name scaned and found by clients

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

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

  // Create a BLE Characteristic
  pTxCharacteristic = pService->createCharacteristic(
                    CHARACTERISTIC_UUID_TX,
                    BLECharacteristic::PROPERTY_NOTIFY
                  );
                      
  pTxCharacteristic->addDescriptor(new BLE2902());

  BLECharacteristic * pRxCharacteristic = pService->createCharacteristic(
                    CHARACTERISTIC_UUID_RX,
                    BLECharacteristic::PROPERTY_WRITE
                  );

  pRxCharacteristic->setCallbacks(new MyCallbacks());

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

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

  //The ESP32S3 bluetoth 5.0 requires security settings.
  //Without it, an error will occur when trying to pair with other devices.
  //Using a 6-digit PIN as the authentication method seems to work.
  //This PIN allows the device to be paired with an Client device.
  //Client device users will be prompted to key in a 6-digit PIN, '123456'.
  BLESecurity *pSecurity = new BLESecurity();
  pSecurity->setStaticPIN(123456);
  //Setting ESP_LE_AUTH_REQ_SC_ONLY instead of the PIN setting eliminates the need for PIN input during pairing.
  //pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_ONLY);

}

void loop() {
  if (deviceConnected) {
    if (isrequested) {
      currenttime = millis(); //elapsed time(ms)
      if (interval <= currenttime - previoustime) {
        previoustime += interval;
        char string0[256];
        sprintf(string0, "Hello %.3f\r\n", currenttime/1000.f);
        pTxCharacteristic->setValue((String)string0);
        pTxCharacteristic->notify();
        delay(10);
      }
    }
  } else {
    isrequested = false;
  }
  
  // disconnecting
  if (!deviceConnected && oldDeviceConnected) {
    delay(500); // give the bluetooth stack the chance to get things ready
    pServer->startAdvertising(); // restart advertising
    Serial.println("start advertising");
    oldDeviceConnected = deviceConnected;
  }

  // connecting
  if (deviceConnected && !oldDeviceConnected) {
    // do stuff here on connecting
    oldDeviceConnected = deviceConnected;
  }
  delay(2);//allow the cpu to switch to other tasks
}

5.2 BMP280を使用して,BLE Uart通信で温度などの情報を送信

プログラムの概要
クライアント(Androidスマホなど)からのリクエストで,サーバであるXIAO ESP32S3は,温度センサBMP280の値を取得し,クライアントに返します。
具体的には,XIAO ESP32S3は文字列"start"を受け取ったら1秒間隔で温度などのデータを送信し,文字列"stop"を受け取ったら送信をやめるようにします。

説明
UART通信ですので,プログラム中の受信のパートと送信のパートが分かれば,そこにやりたいことを書けばよいことになります。
受信時はclass MyCallbacks: public BLECharacteristicCallbacksのonWrite()が呼び出され,String rxValueに受信文字列が保存されます。
ここが受信のパートになります。
受信パートでは受信文字列が"start","stop"であった時には,作業フラグisrequestedをそれぞれtrue,falseに設定します。

loop()内でdeviceConnected およびisrequestedがtrueで,一定時間が経過したら,温度などを測定して,送信すべきデータ文字列("温度","気圧","標高")を作って,送信します。
ここが送信パートになります。

もう少し要点を絞ってみます。
◎受信時は,
 void onWrite(BLECharacteristic *pCharacteristic)
が呼び出されて,
 String rxValue = pCharacteristic->getValue();
で,String型の文字列rxValueに受信文字列が得られます。
◎送信時は,送信したいString型の文字列を
 pTxCharacteristic->setValue();
で送って
 pTxCharacteristic->notify();
で送信相手に送ったよと知らせて完了です。

なお,
 #define DEVICENAME "UART ESP32S3"
は自分の名前です。通信相手のAndroidスマホなどから見つけてもらう名前です。
 #define INTERVAL 1000 //millisec
を変更するとデータ送信間隔が変わります。

 BLESecurity *pSecurity = new BLESecurity();
 pSecurity->setStaticPIN(123456);
上記2行がペアリング時に使われるPINの設定です。PINを設定しない場合は,次の2行に置き換えてください。
 BLESecurity *pSecurity = new BLESecurity();
 pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_ONLY);

次のコードは,Arduino IDEの既存スケッチ例"BLE_uart.ino"を元に作ったものです。
Arduino IDEでコンパイルするときは,ライブラリ"Grove_-_Barometer_Sensor_BMP280"を予めIDEに追加しておいてください。

#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include <Wire.h>
#include "Seeed_BMP280.h"

#define DEVICENAME "UART ESP32S3"
#define INTERVAL 1000 //millisec

// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

BLEServer *pServer = NULL;
BLECharacteristic * pTxCharacteristic;
bool deviceConnected = false;
bool oldDeviceConnected = false;
boolean isrequested = false;
BMP280 bmp280;
int interval = INTERVAL; //millisec
int currenttime = 0; //millisec
int previoustime = 0; //millisec

class MyServerCallbacks: public BLEServerCallbacks {
  void onConnect(BLEServer* pServer) {
    deviceConnected = true;
    Serial.println("** device connected");
  };

  void onDisconnect(BLEServer* pServer) {
    deviceConnected = false;
    Serial.println("** device disconnected");
  }
};

class MyCallbacks: public BLECharacteristicCallbacks {
  void onWrite(BLECharacteristic *pCharacteristic) {
    String rxValue = pCharacteristic->getValue();

    if (rxValue.length() > 0) {
      Serial.println("*********");
      Serial.print("Received Value: ");
      rxValue.trim();
      Serial.println(rxValue);
      Serial.println("*********");
      //Reply as is
      pTxCharacteristic->setValue(rxValue);
      pTxCharacteristic->notify();
      delay(10);

      if (rxValue.indexOf("start") == 0) { //"start" has found
        pTxCharacteristic->setValue("tempreture[degC], pressure[hPa], altitude[m]\r\n");
        pTxCharacteristic->notify();
        delay(10);
        isrequested = true;
        previoustime = millis(); //elapsed time(ms)
        previoustime -= interval;
      } else if (rxValue.indexOf("stop") == 0) { //"stop" has found
        isrequested = false;
      }
    }
  }
};

void setup() {
  Serial.begin(115200);
  // Create the BLE Device
  BLEDevice::init(DEVICENAME); //BLE Device Name scaned and found by clients

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

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

  // Create a BLE Characteristic
  pTxCharacteristic = pService->createCharacteristic(
                    CHARACTERISTIC_UUID_TX,
                    BLECharacteristic::PROPERTY_NOTIFY
                  );
                      
  pTxCharacteristic->addDescriptor(new BLE2902());

  BLECharacteristic * pRxCharacteristic = pService->createCharacteristic(
                    CHARACTERISTIC_UUID_RX,
                    BLECharacteristic::PROPERTY_WRITE
                  );

  pRxCharacteristic->setCallbacks(new MyCallbacks());

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

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

  //The ESP32S3 bluetoth 5.0 requires security settings.
  //Without it, an error will occur when trying to pair with other devices.
  //Using a 6-digit PIN as the authentication method seems to work.
  //This PIN allows the device to be paired with an Client device.
  //Client device users will be prompted to key in a 6-digit PIN, '123456'.
  BLESecurity *pSecurity = new BLESecurity();
  pSecurity->setStaticPIN(123456);
  //Setting ESP_LE_AUTH_REQ_SC_ONLY instead of the PIN setting eliminates the need for PIN input during pairing.
  //pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_ONLY);

  //start BMP280
  if(!bmp280.init()){
    Serial.println("Device error!");
  }
}

void loop() {
  if (deviceConnected) {
    if (isrequested) {
      currenttime = millis(); //elapsed time(ms)
      if (interval <= currenttime - previoustime) {
        previoustime += interval;
        float tempreture = bmp280.getTemperature();
        float pressure = bmp280.getPressure();
        float altitude = bmp280.calcAltitude(pressure);
        char string0[256];
        sprintf(string0, "%.1f, %.0f, %.2f\r\n", tempreture, pressure/100.f, altitude);
        pTxCharacteristic->setValue((String)string0);
        pTxCharacteristic->notify();
        delay(10);
      }
    }
  } else {
    isrequested = false;
  }
  
  // disconnecting
  if (!deviceConnected && oldDeviceConnected) {
    delay(500); // give the bluetooth stack the chance to get things ready
    pServer->startAdvertising(); // restart advertising
    Serial.println("start advertising");
    oldDeviceConnected = deviceConnected;
  }

  // connecting
  if (deviceConnected && !oldDeviceConnected) {
    // do stuff here on connecting
    oldDeviceConnected = deviceConnected;
  }
  delay(2);//allow the cpu to switch to other tasks
}

6 AndroidスマホアプリとXIAO ESP32S3のペアリング

◎このペアリング作業は不要です。
XIAO ESP32S3を起動後,Androidスマホの設定からBluetoothの設定に移ります。
新しいデバイスとペア設定に進むと,XIAO ESP32S3のデバイス名として設定した"UART ESP32S3"が見つかると思います。
そこでPINを要求されるので,XIAO ESP32S3のプログラム中で設定したPIN "123456"を入力するとpairingが完了します。

7 Androidスマホアプリ"Serial Bluetooth Terminal"の準備

Android playから,"Serial Bluetooth Terminal"をダウンロードしてインストールします。

  "Serial Bluetooth Terminal"のアイコン

最初の起動で,メニュー等の探検をします。
〇左上三本線メニューでは
settings→terminal→Show timestampをONにしておくとよいでしょう。
settings→terminal→Buffer sizeは表示内容を保存する作業メモリのサイズです。できるだけ大きくとるのが良いと思います。(200kBでは100文字のデータ約2000行分です。場合によっては無制限もあり)
settings→ReceiveはCR+NLが標準ですが,後で受信行での改行が変だったら,適当に変えてください。
settings→Send→Local echoはONが標準です。自分が送信した文字列も表示されます。
settings→Misc.→Save....は表示内容(LOG)保存先フォルダの設定です。
〇右上3点メニューには
Data→Saveがあって,表示内容を保存の時使います。

8 XiaoESP32S3と"Serial Bluetooth Terminal"の通信

先にXiaoESP32S3に電源を与え,立ち上げておきます。

  "BMP280が接続されたXIAO ESP32S3(紙のアンテナがついています。)

その後,"Serial Bluetooth Terminal"で 左上三本線メニューでDevices→BluetoothLE→SCAN で付近のBLEデバイスを見つけて表示してくれます。
ここでは,XiaoESP32S3のプログラムの
   #define DEVICENAME "UART ESP32S3"
でつけた名前"UART ESP32S3"が見つかるのでこれをタップします。

  Serial Bluetooth Terminalデバイス選択画面

"Serial Bluetooth Terminal"から"start"を送信すると,1秒ごとにデータが送信されてきます。
受信した3つの数値は温度[℃],気圧[hPa],標高[m]を表しています。
"Serial Bluetooth Terminal"から"stop"を送信すると,データ送信が止まります。
画面上の受信データは,右上3点メニューからData→Saveでファイル保存することができます。

"Serial Bluetooth Terminal"から"start"や"stop"を送信するときは,画面下部のテキストボックスに入力して送信ボタンをタップするか,予めマクロボタンに"start"や"stop"の文字列を登録(マクロボタンのタップ&ホールドで登録出来る)しておいて,それらのボタンをタップます。
次の通信画面では,予めマクロボタンに"start"や"stop"の文字列が登録されています。


    Serial Bluetooth Terminal通信画面

9 通信距離

AndroidスマホをCentralとして,XIAO ESP32S3に付属の紙のようなアンテナをつけた状態で通信距離を測定しました。
見通しの良い直線で130mまでの通信が確認できました。
測定場所の都合でそれ以上距離を伸ばせなかったですが,通信限界はもう少し先になると思います。
Bluetooth4.0(LE)は通信範囲100mと言われています。(手元で試したら直線の見通せる場所で50mでした。)
Bluetooth5.0(LE)は通信範囲400mと言われています。

10 発熱に関して

通信時には指先で触っていられないほどESP32S3が高温になっていたので気になったので長時間通信を行いました。
AndroidスマホをCentralとして,XIAO ESP32S3に付属の紙のようなアンテナをつけた状態で通信を行いました。
通信は1秒ごとに行われ,XIAO ESP32S3からAndroidスマホに温度[℃],気圧[hPa],標高[m]を送信していました。

30℃を超える気温の中で,連続送信していたところ,1時間程度で通信が途絶えてしまいました。
再度送信を開始したところ,今度は3時間ほどで通信が途絶えてしまいました。
気温が30℃を下回ったところで,再再度送信を開始したところ,8時間の送信で異常は起きませんでした。
周囲温度が高いときは,異常終了する可能性があることがわかりました。

一般に通信距離が2倍になると4倍の電力を消費するため,この発熱はBluetooth5.0(LE)になったことに起因していると考えられます。

11 まとめ

(1)Wi-FiマイコンXIAO ESP32S3とAndroidスマホでBLEuart通信し,Androidスマホからの指令によって文字列をXIAO ESP32S3が送るプログラムを示しました。
(2)Wi-FiマイコンXIAO ESP32S3とAndroidスマホでBLEuart通信し,Androidスマホからの指令によって温度などのデータをXIAO ESP32S3が送るプログラムを示しました。

XIAO ESP32S3側のプログラムで,受信文字列を取り出す部分と,送信したい文字列を送信する部分を示しました。

XIAO ESP32S3がBLE通信するときは,発熱が大きく問題が生ずるの可能性があるため,放熱対策をしたほうが安全と思われます。

この記事ではAndroidスマホのアプリ"Serial Bluetooth Terminal"を使いました。
他にも"Bluefruit Connect"というがあり,同じような使い方が出来ます。 → 付録
iPhoneにもアプリ"Bluefruit Connect"がありAndroid版"Bluefruit Connect"と同じ使い方ができます。
WindowsPCにも同様なアプリ"BLE_serial_terminal"があり,同様の使い方ができます。
  iOSデバイス版の解説
  WindowsPC版の解説


付録 "Bluefruit Connect"

アプリ"Bluefruit Connect"にはAndroid版とiOS版があり,同じ操作で使うことができて便利です。

A1 Androidデバイスアプリ"Bluefruit Connect"の準備

Android playから,"Bluefruit Connect"をダウンロードしてインストールします。

  "Bluefruit Connect"のアイコン

A2 XiaoESP32S3と"Bluefruit Connect"の通信

先にXiaoESP32S3に電源を与え,立ち上げておきます。

その後,"Bluefruit Connect"を立ち上げると最初にSelect Deviceの画面になります。
ここでは,XiaoESP32S3のプログラムの
   #define DEVICENAME "UART ESP32S3"
でつけた名前"UART ESP32S3"が見つかるのでconnectボタンをタップします。

  Bluefruit Connectデバイス選択画面

次にModulesと書かれたモジュール選択画面になりますので,UARTを選択します。

  Bluefruit Connectモジュール選択画面

UARTの白い画面になったら,"Bluefruit Connect"から"start"を送信すると,1秒ごとにデータが送信されてきます。
受信した3つの数値は温度[℃],気圧[hPa],標高[m]を表しています。
"Bluefruit Connect"から"stop"を送信すると,データ送信が止まります。
"Bluefruit Connect"から"start"や"stop"を送信するときは,画面下部のテキストボックスに入力してSENDボタンをタップします。


    Bluefruit Connect通信画面

画面上の送受信データの表示形式は,右上メニューからDisplay Modeで切り替えられます。
(time stamp付きの表示もできます。)

画面上の送受信データのファイルへの保存は,右上メニューからExportで出来ます。
保存形式をcsvにするとtime stamp付きでの保存になります。