M5stickC(esp32)を使ったBLE通信によるRSSIの取得方法

# はじめに
「esp32を複数台使って電波強度から自己位置推定を行いたい！」という目的で手始めにRSSIの値を調べてみたのでその記録です。

## RSSIとは？
RSSIは"Received Signal Strength Indicator"の略でありアクセスポイントやルーターから発信される信号をデバイスがどれくらい受信できるかを測定したものです。
[参考サイト](https://milestone-of-se.nesuke.com/nw-basic/wireless/rssi-snr-definition/#:~:text=SNR%20%E3%81%A8%E3%81%AF%EF%BC%9F-,RSSI%20%E3%81%A8%E3%81%AF%E9%9B%BB%E6%B3%A2%E3%81%AE%E5%BC%B7%E3%81%95,%E9%81%A9%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E7%8A%B6%E6%85%8B%E3%81%A7%E3%81%99%E3%80%82)

# 準備するもの
MacBook Pro (M1Pro)
M5stickC（２台〜４台）
ArduinoIDE

## 流れ
1. M5stickCの準備
    - １台目をBLEの送信側、２台目を受信側としてBLE通信を行います。

2. BLE通信の設定
    - 送信側のM5stickCでBLEビーコンを作成し、受信側のM5stickCでBLEスキャンを行うように設定します。ソースコード内で適切なUUID（ユニバーサルユニーク識別子）を指定してください。

3. RSSIの取得
    - 受信側のM5stickCでRSSIを取得するためのコードを追加します。RSSIはBLEビーコンからの信号強度を示す値です。M5stickCのBLEライブラリを使用してRSSIを取得し、必要に応じてデータを処理します。

4. 結果の表示
    - 受信側のM5stickCで取得したRSSIの値を表示します。デバイス間の距離や環境の変化によって、RSSIの値がどのように変化するか確認してください。

### ソースコード
```arduino:送信（ビーコン）側

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <M5StickC.h>

BLEServer* pServer;

void setup() {
  M5.begin();
  Serial.begin(115200);
  BLEDevice::init("ESP32");

  pServer = BLEDevice::createServer();
  BLEAdvertising* pAdvertising = pServer->getAdvertising();
  pAdvertising->addServiceUUID("0000XXXX-0000-1000-8000-00805F9B34FB"); // 1台目のESP32のスキャンUUIDを指定
  pAdvertising->start();
}

void loop() {
  M5.Lcd.setRotation(3);
  M5.Lcd.setCursor(M5.Lcd.width()/3, M5.Lcd.height()/2);
  M5.Lcd.printf("Number 1");
  
}
```

```arduino:受信側
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
#include <M5StickC.h>

int RSSI1,RSSI2,RSSI3;


BLEUUID serviceUUID1("0000XXXX-0000-1000-8000-00805F9B34FB"); // 1台目のESP32のアドバタイズUUIDを指定
BLEUUID serviceUUID2("0000XXXX-0000-1000-8000-00805F9B34FC"); // 2台目のESP32のアドバタイズUUIDを指定
BLEUUID serviceUUID3("0000XXXX-0000-1000-8000-00805F9B34FD"); // 2台目のESP32のアドバタイズUUIDを指定


void setup() {
  M5.begin();
  Serial.begin(115200);
  BLEDevice::init("ESP32");
}

void loop() {
   
  BLEScan* pBLEScan = BLEDevice::getScan();

  pBLEScan->start(1);

  BLEScanResults foundDevices = pBLEScan->getResults();

  for (int i = 0; i < foundDevices.getCount(); i++) {
    BLEAdvertisedDevice device = foundDevices.getDevice(i);
    if (device.haveServiceUUID() && device.isAdvertisingService(serviceUUID1)) {
      RSSI1 = device.getRSSI();
      
      Serial.print("Device found: ");
      Serial.print("RSSI1=");
      Serial.print(device.getRSSI());
      Serial.print(" dBm, Address=");
      Serial.println(device.getAddress().toString().c_str());
    }
    if (device.haveServiceUUID() && device.isAdvertisingService(serviceUUID2)) {
      RSSI2 = device.getRSSI();
      
      Serial.print("Device found: ");
      Serial.print("RSSI2=");
      Serial.print(device.getRSSI());
      Serial.print(" dBm, Address=");
      Serial.println(device.getAddress().toString().c_str());
    }
    if (device.haveServiceUUID() && device.isAdvertisingService(serviceUUID3)) {
      RSSI3 = device.getRSSI();
      
      Serial.print("Device found: ");
      Serial.print("RSSI3=");
      Serial.print(device.getRSSI());
      Serial.print(" dBm, Address=");
      Serial.println(device.getAddress().toString().c_str());
    }
  }

  pBLEScan->clearResults();
  delay(500);

  M5.Lcd.setRotation(3);
  M5.Lcd.setCursor(M5.Lcd.width()/3, M5.Lcd.height()/4);
  M5.Lcd.printf("RSSI1 = %d",RSSI1);
  M5.Lcd.setCursor(M5.Lcd.width()/3, M5.Lcd.height()/4*2);
  M5.Lcd.printf("RSSI2 = %d",RSSI2);
  M5.Lcd.setCursor(M5.Lcd.width()/3, M5.Lcd.height()/4*3);
  M5.Lcd.printf("RSSI3 = %d",RSSI3);
    
}
```

## 注意点
このソースコードでは３つのビーコンからの値を取得しています。ビーコンを追加する場合はUUIDのところを送信側の２台目の値（"0000XXXX-0000-1000-8000-00805F9B34FC"）にしてあげてください。

## まとめ
今回はM5stickCを複数台使い電波強度を取得しました。最終的には今回取得したRSSIの値を使って自己位置推定を行いたいのですが、他の電波に邪魔をされてうまく通信強度が拾えるかが課題になりそうですね。