初めての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"); }

 実行結果です。

前へ

初めてのBLE (15) ESP32でペリフェラル③浮動小数点形式

次へ

初めてのBLE (17) CircuitPythonでペリフェラル① 5.1.0の準備