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
セントラルとの接続を待ちます。
つながったら、メッセージを出します。
接続が切れると、メッセージを出します。
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
}
}

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