Arduino UNO R4 WiFiでBLE ② LPS22のBLEペリフェラル

 前回、気圧センサLPS22HBで、気圧と温度を測定し、グラフィック・ディスプレイに表示しました。

 ここでは、測定した二つのデータをBLE(Bluetooth Low Energy)で送信するBLEペリフェラル(peripheral を作成します。受信するほうはBLEセントラル(central )と呼ばれます。

 ArduinoBLEライブラリを利用してスケッチを作成します。執筆時点では、1.3.6が最新です。

使用環境

  • Arduino UNO R4 WiFi
  • Arduino IDE 2.2.1
  • Windows10 22H2

BLEの各種定義

 ペリフェラルとセントラル間でBLEが接続されたとき、GATT通信が行われます。GATTはGeneric attribute profileの略です。

 GATT通信の中には複数のService(サービス)が入っています。ここでは、LPS22という名称の一つのサービスだけが存在します。

 サービスの中には、複数のCharacteristic(キャラクタリスティック)が含まれています。ここでは、温度気圧の二つです。

 キャラクタリスティックには、説明;Descriptorディスクリプタ)をつけられます。ない場合もあります。

 いろいろな機器の間でそれらのサービスやキャラクタリスティックとかが重ならないようにユニークなUUIDで識別します。

 BLEReadはセントラル側でCharacteristicの値を読み出し、BLENotifyはペリフェラル側でCharacteristicの値を通知する処理内容です。

#define LPS22_SERVICE_UUID   "F000AA30-0451-4000-B000-000000000000"  // BLE Service
BLEService Sensor_LPS22_Service(LPS22_SERVICE_UUID);

#define LPS22_Temp_Characteristic_UUID    "F000AA31-0451-4000-B000-000000000000"  // BLE  Characteristic
#define LPS22_Press_Characteristic_UUID   "F000AA32-0451-4000-B000-000000000000"
BLEFloatCharacteristic  LPS22_Temp(LPS22_Temp_Characteristic_UUID, BLERead | BLENotify);
BLEFloatCharacteristic  LPS22_Press(LPS22_Press_Characteristic_UUID, BLERead | BLENotify);

#define LPS22_Temp_Descriptor_UUID    "2901"  // BLE  Descriptor
#define LPS22_Press_Descriptor_UUID   "2901"
BLEDescriptor   LPS22_Temp_Descriptor(LPS22_Temp_Descriptor_UUID, "Temperature: `C IEEE-754 format");
BLEDescriptor   LPS22_Press_Descriptor(LPS22_Press_Descriptor_UUID, "Pressure: hPa");

 BLEFloatCharacteristicは、 ArduinoBLEライブラリで実数のCharacteristicだということを指定しています。IEEE-754 フォーマット(単精度浮動小数点数;Arduinoの実数がメモリ上に保持される形式)です。このほかに、BLECharCharacteristicやBLEUnsignedCharCharacteristicなどがあります。

 Descriptorの2901は、ユーザが可読できるCharacteristicの説明文字列(UTF-8)の指定です。

●setupーBLE

 最初に初期化します。

BLE.begin();


 localnameを指定します。

#define localNAME  "LPS22_float"

 BLE.setLocalName(localNAME);


 service、characteristic、descriptorをBLEに追加します。

  BLE.setAdvertisedService(Sensor_LPS22_Service);  // add the service UUID
  Sensor_LPS22_Service.addCharacteristic(LPS22_Temp);  // add characteristic
  Sensor_LPS22_Service.addCharacteristic(LPS22_Press);
  LPS22_Temp.addDescriptor(LPS22_Temp_Descriptor);  // add descriptor
  LPS22_Press.addDescriptor(LPS22_Press_Descriptor);
  BLE.addService(Sensor_LPS22_Service);  // Add service


 Characteristicに初期値を入れます。

  LPS22_Temp.writeValue(oldValue);  // set initial value for this characteristic
  LPS22_Press.writeValue(oldValue);


 準備が整ったので、セントラルからの接続待ち=アドバタイズを起動します。

  BLE.advertise();  // start advertising
  Serial.println("Bluetooth device active, waiting for connections...");

loopーBLE

 セントラルとの接続を待ちます。

  // wait for a BLE central
  BLEDevice central = BLE.central();


 つながったら、メッセージを出します。

  // if a central is connected to the peripheral:
  if (central) {
    delay(100);
    Serial.print("Connected to central: ");
    // print the central's BT address:
    Serial.println(central.address());
 
 つながっている間、updateValue();でデータを送信します。
 

    while (central.connected()) {
      updateValue();
      delay(1000);
    }

 接続が切れると、メッセージを出します。
 
 
    // when the central disconnects
    Serial.print("Disconnected from central: ");
    Serial.println(central.address());
 
 
 updateValue() {}関数内で、気圧と温度を送ります。
 

    LPS22_Temp.writeValue(tempC);
    LPS22_Press.writeValue(press);
 
 
全体のスケッチ
 

#include <ArduinoBLE.h>

#define LPS22_SERVICE_UUID   "F000AA30-0451-4000-B000-000000000000"  // BLE Service
BLEService Sensor_LPS22_Service(LPS22_SERVICE_UUID);

#define LPS22_Temp_Characteristic_UUID    "F000AA31-0451-4000-B000-000000000000"  // BLE  Characteristic
#define LPS22_Press_Characteristic_UUID   "F000AA32-0451-4000-B000-000000000000"
BLEFloatCharacteristic  LPS22_Temp(LPS22_Temp_Characteristic_UUID, BLERead | BLENotify);
BLEFloatCharacteristic  LPS22_Press(LPS22_Press_Characteristic_UUID, BLERead | BLENotify);

#define LPS22_Temp_Descriptor_UUID    "2901"  // BLE  Descriptor
#define LPS22_Press_Descriptor_UUID   "2901"
BLEDescriptor   LPS22_Temp_Descriptor(LPS22_Temp_Descriptor_UUID, "Temperature: `C IEEE-754 format");
BLEDescriptor   LPS22_Press_Descriptor(LPS22_Press_Descriptor_UUID, "Pressure: hPa");

#include <Wire.h>
#include <Adafruit_LPS2X.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_SSD1306.h> Adafruit_LPS22 lps; Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire); #define localNAME "LPS22_float" float oldValue = 0; // last value void setup(void) { Serial.begin(115200); while (!Serial) delay(10); // will pause Zero, Leonardo, etc until serial console opens Serial.println("Adafruit LPS22 + ssd1306 + BLE"); // begin initialization if (!BLE.begin()) { Serial.println("starting BLE failed!"); while (1); } // Try to initialize! if (!lps.begin_I2C()) { Serial.println("Failed to find LPS22 chip"); while (1) { delay(10); } } Serial.println("LPS22 Found!"); lps.setDataRate(LPS22_RATE_10_HZ); Serial.print("Data rate set to: "); switch (lps.getDataRate()) { case LPS22_RATE_ONE_SHOT: Serial.println("One Shot / Power Down"); break; case LPS22_RATE_1_HZ: Serial.println("1 Hz"); break; case LPS22_RATE_10_HZ: Serial.println("10 Hz"); break; case LPS22_RATE_25_HZ: Serial.println("25 Hz"); break; case LPS22_RATE_50_HZ: Serial.println("50 Hz"); break; case LPS22_RATE_75_HZ: Serial.println("75 Hz"); break; } // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3D)) { // Address 0x3C for 128x32 Serial.println(F("SSD1306 allocation failed")); for (;;) ; // Don't proceed, loop forever } display.display(); delay(500); // Pause for 2 seconds display.setTextSize(1); display.setTextColor(WHITE); display.setRotation(0); display.clearDisplay(); BLE.setLocalName(localNAME); BLE.setAdvertisedService(Sensor_LPS22_Service); // add the service UUID Sensor_LPS22_Service.addCharacteristic(LPS22_Temp); // add characteristic Sensor_LPS22_Service.addCharacteristic(LPS22_Press); LPS22_Temp.addDescriptor(LPS22_Temp_Descriptor); // add descriptor LPS22_Press.addDescriptor(LPS22_Press_Descriptor); BLE.addService(Sensor_LPS22_Service); // Add service LPS22_Temp.writeValue(oldValue); // set initial value for this characteristic LPS22_Press.writeValue(oldValue); BLE.advertise(); // start advertising Serial.println("Bluetooth device active, waiting for connections..."); } void loop() { // wait for a BLE central BLEDevice central = BLE.central(); // if a central is connected to the peripheral: if (central) { delay(100); Serial.print("Connected to central: "); // print the central's BT address: Serial.println(central.address()); while (central.connected()) { updateValue(); delay(1000); } // when the central disconnects Serial.print("Disconnected from central: "); Serial.println(central.address()); } } void updateValue() { display.clearDisplay(); display.setCursor(0, 0); sensors_event_t temp; sensors_event_t pressure; lps.getEvent(&pressure, &temp);// get pressure float tempC = temp.temperature; float press = pressure.pressure; Serial.print("Temperature: ");Serial.print(tempC);Serial.println(" degrees C"); Serial.print("Pressure: ");Serial.print(press);Serial.println(" hPa"); Serial.println(""); display.println("Temperature: - `C"); display.print(tempC, 2); display.println(""); display.println(""); display.println("Pressure: - hPa"); display.print(press, 1); display.display(); // if value has changed if (tempC != oldValue) { // update characteristic LPS22_Temp.writeValue(tempC); LPS22_Press.writeValue(press); oldValue = tempC; // save the level for next comparison } }

動作の確認
 オン・セミコンダクターのBLEであるRSL10 Bluetooth Low Enaergy Exploerのセントラルの機能を使って、PCで情報を見ます。
 localnameをスキャンします。LPS22_floatを見つけたので、Connectします。Discover Servicesをクリックして、Servicesの内容を表示した画面です。
 Notificationをチェックすると、つねに最新データが送られてきます。
 

 送られてきた実数は、このサイトを利用して変換し、正しい値であることを確認しました。

前へ

Arduino UNO R4 WiFiでBLE ① 気圧センサLPS22をつなぐ

次へ

Arduino UNO R4 WiFiでBLE ③ LPS22のBLEペリフェラルと接続するセントラル