初めてのBLE (16) ESP32でペリフェラル④BME280
ESP32のI2CインターフェースにMEMSセンサのBME280をつなぎ、温度、湿度、気温を送れるBLEペリフェラルを作ります。ESP32ボードは製品によってピン配置は異なります。ここで利用しているは、22ピンがSCL、21ピンがSDAです。
●接続
| BME280 | ESP32 |
|---|---|
| Vcc | 3V(3.3V) |
| GND | GND |
| SCL | 22 |
| SDA | 21 |
●BME280のライブラリを利用
ライブラリ管理でBME280を検索するとたくさんのライブラリが出てきます。ここではAdafruitのライブラリを利用します。同時にSensor関連もインストールするかと聞かれたら、全部インストールしておきます。I2Cのインターフェースで接続しているので、最初にi2cscannerを動かします。見つけてきたスレーブ・アドレスは0x76でした。したがって、setup()内で、status = bme.begin(0x76);とアドレスを変更しておきます。BME280は2種類のアドレスが利用できます。
動作が確認できたら、Wireライブラリだけ残して、Adaruitのbme280testをスリムにします。
// Designed specifically to work with the Adafruit BME280 Breakout // Written by Limor Fried & Kevin Townsend for Adafruit Industries. #include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h> Adafruit_BME280 bme; // I2C void setup() { Serial.begin(9600); while(!Serial); // time to get serial running Serial.println(F("BME280 test")); unsigned status; status = bme.begin(0x76); Serial.println(); } void loop() { printValues(); delay(2000); } void printValues() { Serial.print("Temperature = "); Serial.print(bme.readTemperature()); Serial.println(" *C"); Serial.print("Pressure = "); Serial.print(bme.readPressure() / 100.0F); Serial.println(" hPa"); Serial.print("Humidity = "); Serial.print(bme.readHumidity()); Serial.println(" %"); Serial.println(); }
●ESP32-BLE_serverと合体
前回までで作ったCPU温度を送るスケッチに上記のBME280のデータを組み合わせます。
BLEでは、一番外側がGATTと呼ばれ、その中に複数のServiceがあります。デフォルトの二つのService以外に、
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
をCPU温度用に使っていました。サービスは一つ以上のCHARACTERISTICがあります。今回、温度、気圧、湿度ように三つ用意しました。
#define CHARACTERISTIC_T_UUID "beb5483d-36e1-4688-b7f5-ea07361b26a8"
#define CHARACTERISTIC_P_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
#define CHARACTERISTIC_H_UUID "beb5483f-36e1-4688-b7f5-ea07361b26a8"
/*
Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleServer.cpp
Ported to Arduino ESP32 by Evandro Copercini
updates by chegewara
// Designed specifically to work with the Adafruit BME280 Breakout
// Written by Limor Fried & Kevin Townsend for Adafruit Industries.
*/
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
float temp = 0;
float press = 0;
float humi = 0;
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_T_UUID "beb5483d-36e1-4688-b7f5-ea07361b26a8"
#define CHARACTERISTIC_P_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
#define CHARACTERISTIC_H_UUID "beb5483f-36e1-4688-b7f5-ea07361b26a8"
BLECharacteristic *tCharacteristic;
BLECharacteristic *pCharacteristic;
BLECharacteristic *hCharacteristic;
Adafruit_BME280 bme; // I2C
void setup() {
Serial.begin(115200);
while(!Serial);
Serial.println("Starting BLE work!");
bme.begin(0x76);
BLEDevice::init("ESP32-BME280 peripheral");
BLEServer *pServer = BLEDevice::createServer();
BLEService *pService = pServer->createService(SERVICE_UUID);
tCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_T_UUID,
BLECharacteristic::PROPERTY_READ
);
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_P_UUID,
BLECharacteristic::PROPERTY_READ
);
hCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_H_UUID,
BLECharacteristic::PROPERTY_READ
);
/*
tCharacteristic->setValue("1");
pCharacteristic->setValue("10");
hCharacteristic->setValue("100");
*/
pService->start();
// BLEAdvertising *pAdvertising = pServer->getAdvertising(); // this still is working for backward compatibility
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(true);
pAdvertising->setMinPreferred(0x06); // functions that help with iPhone connections issue
pAdvertising->setMinPreferred(0x12);
BLEDevice::startAdvertising();
// Serial.println("Characteristic defined! Now you can read it in your phone!");
}
void loop() {
readBME280();
tCharacteristic->setValue(temp);
tCharacteristic->notify();
pCharacteristic->setValue(press);
pCharacteristic->notify();
hCharacteristic->setValue(humi);
hCharacteristic->notify();
delay(2000);
}
void readBME280() {
Serial.print("Temperature = ");
temp = bme.readTemperature();
Serial.print(temp);
Serial.println(" *C");
Serial.print("Pressure = ");
press = bme.readPressure() / 100.0F;
Serial.print(press);
Serial.println(" hPa");
Serial.print("Humidity = ");
humi = bme.readHumidity();
Serial.print(humi);
Serial.println(" %");
Serial.println();
}
オン・セミコンダクターのBLEであるRSL10 Bluetooth Low Enaergy Exploerを使って情報を見ます。connectで接続し、Discover Serviceでサービスを表示しました。三つのデータが送られていることが確認できました。
●セントラルはNANO 33 BLE Sense
上記のペリフェラルのLocal NameはESP32-BME280 peripheralにしました。セントラルのスケッチを作ります。三つのキャラのデータを読み込み、IEEE754のunsign32ビット・データをデコードします。まったく同じ処理なので、関数にしたほうがすっきりすると思います。
#include <ArduinoBLE.h>
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_T_UUID "beb5483d-36e1-4688-b7f5-ea07361b26a8"
#define CHARACTERISTIC_P_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
#define CHARACTERISTIC_H_UUID "beb5483f-36e1-4688-b7f5-ea07361b26a8"
#define localNAME "ESP32-BME280 peripheral"
void setup() {
Serial.begin(9600);
while (!Serial);
BLE.begin();
Serial.println("\nstart BLE Central - BME280");
// start scanning for peripherals
BLE.scanForName(localNAME);
}
void loop() {
// check if a peripheral has been discovered
BLEDevice peripheral = BLE.available();
if (peripheral) {
// discovered a peripheral, print out address, local name, and advertised service
Serial.print("Found ");
Serial.print(peripheral.address());
Serial.print(" '");
Serial.print(peripheral.localName());
Serial.print("' ");
Serial.print(peripheral.advertisedServiceUuid());
Serial.println();
if (peripheral.localName() != localNAME) {
return;
}
// stop scanning
BLE.stopScan();
readBME280data(peripheral);
// peripheral disconnected, start scanning again
BLE.scanForName(localNAME);
}
}
void readBME280data(BLEDevice peripheral) {
// connect to the peripheral
Serial.print("Connecting ...");
if (peripheral.connect()) {
Serial.println("Connected");
} else {
Serial.println("Failed to connect!");
return;
}
// discover peripheral attributes
Serial.print("Discovering attributes ...");
if (peripheral.discoverAttributes()) {
Serial.println("Attributes discovered\n");
} else {
Serial.println("Attribute discovery failed!");
peripheral.disconnect();
return;
}
// retrieve the BME280 characteristic
BLECharacteristic tempCharacteristic = peripheral.characteristic(CHARACTERISTIC_T_UUID);
BLECharacteristic pressCharacteristic = peripheral.characteristic(CHARACTERISTIC_P_UUID);
BLECharacteristic humiCharacteristic = peripheral.characteristic(CHARACTERISTIC_H_UUID);
if (!tempCharacteristic) {
Serial.println("Peripheral does not have Temp characteristic!");
peripheral.disconnect();
return;
} // else if (!ledCharacteristic.canWrite()) {
// Serial.println("Peripheral does not have a writable LED characteristic!");
// peripheral.disconnect();
// return;
// }
Serial.println("---Found CHARACTERISTIC_UUID");
while (peripheral.connected()) {
if (tempCharacteristic.canRead()) {
// read the characteristic value
tempCharacteristic.read();
if (tempCharacteristic.valueLength() > 0) {
uint32_t data = ((uint8_t)*(tempCharacteristic.value()+3) << 24) + ((uint8_t)*(tempCharacteristic.value()+2) << 16) + ((uint8_t)*(tempCharacteristic.value()+1) << 8) + ((uint8_t)*tempCharacteristic.value());
int32_t f = pow(-1, int(bitRead(data,31)));
double k =1 + ((((data<<1)<<8)>>9))/pow(2,23);
int32_t s = pow(2,((((data<<1)>>24))-127));
Serial.print("\ntemp =");
Serial.println(f*k*s);
pressCharacteristic.read();
data = ((uint8_t)*(pressCharacteristic.value()+3) << 24) + ((uint8_t)*(pressCharacteristic.value()+2) << 16) + ((uint8_t)*(pressCharacteristic.value()+1) << 8) + ((uint8_t)*pressCharacteristic.value());
f = pow(-1, int(bitRead(data,31)));
k =1 + ((((data<<1)<<8)>>9))/pow(2,23);
s = pow(2,((((data<<1)>>24))-127));
Serial.print("press =");
Serial.println(f*k*s);
humiCharacteristic.read();
data = ((uint8_t)*(humiCharacteristic.value()+3) << 24) + ((uint8_t)*(humiCharacteristic.value()+2) << 16) + ((uint8_t)*(humiCharacteristic.value()+1) << 8) + ((uint8_t)*humiCharacteristic.value());
f = pow(-1, int(bitRead(data,31)));
k =1 + ((((data<<1)<<8)>>9))/pow(2,23);
s = pow(2,((((data<<1)>>24))-127));
Serial.print("humi =");
Serial.println(f*k*s);
delay(5000);
}
}
}
Serial.println("Peripheral disconnected");
}
実行結果です。