今から始める電子工作 ㉑ I2Cバス その3-2 温湿度センサSHT45 BLEペリフェラル

 ここでは、温湿度センサSHT45のデータを利用して、BLEペリフェラルを作ります。

環境

  • Arduino IDE;2.3.4
  • Windows11;24H2
  • Arduino UNO R4 WiFi 
  • ArduinoBLEライブラリ1.3.7

BLEの各種定義

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

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

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

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

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

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

 ここでUUIDは、"F000AA30-0451-4000-B000-000000000000"を使い、最上位から8バイト目の数値をそれぞれのUUIDに変更して使っています。

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

#define SHT45_Temp_Characteristic_UUID   "F000AA31-0451-4000-B000-000000000000"  // BLE  Characteristic
#define SHT45_Humi_Characteristic_UUID   "F000AA32-0451-4000-B000-000000000000"
BLEFloatCharacteristic  SHT45_Temp(SHT45_Temp_Characteristic_UUID, BLERead | BLENotify);
BLEFloatCharacteristic  SHT45_Humi(SHT45_Humi_Characteristic_UUID, BLERead | BLENotify);

#define SHT45_Temp_Descriptor_UUID   "2901"  // BLE  Descriptor
#define SHT45_Humi_Descriptor_UUID   "2901"
BLEDescriptor   SHT45_Temp_Descriptor(SHT45_Temp_Descriptor_UUID, "Temperature: `C IEEE-754 format");
BLEDescriptor   SHT45_Humi_Descriptor(SHT45_Humi_Descriptor_UUID, "Humidity: %RH");

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

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

#define localNAME  "SHT45_float"

 BLEペリフェラルの名前です。BLE機器をスキャンするときにこの名称が見えます。

●setupーBLE

 最初に初期化します。

BLE.begin()


 localnameを登録します。

  BLE.setLocalName(localNAME);


 service、characteristic、descriptorをBLEに追加登録します。それぞれ入れ子になっていることを意識しています。

  BLE.setAdvertisedService(Sensor_SHT45_Service);  // add the service UUID
  Sensor_SHT45_Service.addCharacteristic(SHT45_Temp);  // add characteristic
  Sensor_SHT45_Service.addCharacteristic(SHT45_Humi);
  SHT45_Temp.addDescriptor(SHT45_Temp_Descriptor);  // add descriptor
  SHT45_Humi.addDescriptor(SHT45_Humi_Descriptor);
  BLE.addService(Sensor_SHT45_Service);  // Add service


 Characteristicに初期値を入れます。oldValueは0です。もちろん、実際に測定してきた値を入れてもOKです。

  SHT45_Temp.writeValue(oldValue);  // set initial value for this characteristic
  SHT45_Humi.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();


 BLEセントラルとつながったら、メッセージを出します。

  // 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() {}関数内で、気圧と温度を送ります。
 

    // update  characteristic
    SHT45_Temp.writeValue(temperature);
    SHT45_Humi.writeValue(humidity);
 
ArduinoBLEライブラリをインストール
 
 

 
全体のスケッチ
#include <ArduinoBLE.h>

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

#define SHT45_Temp_Characteristic_UUID   "F000AA31-0451-4000-B000-000000000000"  // BLE  Characteristic
#define SHT45_Humi_Characteristic_UUID   "F000AA32-0451-4000-B000-000000000000"
BLEFloatCharacteristic  SHT45_Temp(SHT45_Temp_Characteristic_UUID, BLERead | BLENotify);
BLEFloatCharacteristic  SHT45_Humi(SHT45_Humi_Characteristic_UUID, BLERead | BLENotify);

#define SHT45_Temp_Descriptor_UUID   "2901"  // BLE  Descriptor
#define SHT45_Humi_Descriptor_UUID   "2901"
BLEDescriptor   SHT45_Temp_Descriptor(SHT45_Temp_Descriptor_UUID, "Temperature: `C IEEE-754 format");
BLEDescriptor   SHT45_Humi_Descriptor(SHT45_Humi_Descriptor_UUID, "Humidity: %RH");

#include  <Wire.h>
const uint8_t SHT45_address = 0x44;
uint8_t readbuffer[6];


#define localNAME  "SHT45_float"
float oldValue = 0;  // last value 

void setup(void) {
  Serial.begin(115200);
  delay(1000);
  Serial.println("Adafruit SHT45 + BLE");

  // begin initialization
  if (!BLE.begin()) {
    Serial.println("starting BLE failed!");
    while (1);
  }

  Wire1.begin();

  BLE.setLocalName(localNAME);
  BLE.setAdvertisedService(Sensor_SHT45_Service);  // add the service UUID
  Sensor_SHT45_Service.addCharacteristic(SHT45_Temp);  // add characteristic
  Sensor_SHT45_Service.addCharacteristic(SHT45_Humi);
  SHT45_Temp.addDescriptor(SHT45_Temp_Descriptor);  // add descriptor
  SHT45_Humi.addDescriptor(SHT45_Humi_Descriptor);
  BLE.addService(Sensor_SHT45_Service);  // Add service
  SHT45_Temp.writeValue(oldValue);  // set initial value for this characteristic
  SHT45_Humi.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() {
    Wire1.beginTransmission(SHT45_address);
        Wire1.write(0xfd);
    Wire1.endTransmission();
    delay(10);
    Wire1.requestFrom(SHT45_address, 6);
    readbuffer[0] = Wire1.read();
    readbuffer[1] = Wire1.read();
    readbuffer[2] = Wire1.read(); // CRC
    readbuffer[3] = Wire1.read();
    readbuffer[4] = Wire1.read();
    readbuffer[5] = Wire1.read(); // CRC
 
    int temp = readbuffer[0] * 256 + readbuffer[1];
    int humi = readbuffer[3] * 256 + readbuffer[4];
    float temperature = -45 + 175 * temp / 65535.0;
    float humidity = -6 + 125 * humi / 65535.0;
 
    Serial.println(" temperature= "+String(temperature,1)+"'C");
    Serial.println(" RH%= "+String(humidity,0));

  // if value has changed
  if (temperature != oldValue) {
    // update  characteristic
    SHT45_Temp.writeValue(temperature);
    SHT45_Humi.writeValue(humidity);
    oldValue = temperature; // save the level for next comparison
  }
}
 

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

 実数の4バイトのデータは直読できませんから、次のWebサイトで変換しました。Swap to use big-endianにチャックを入れて使います。

  Floating Point to Hex Converter

前へ

今から始める電子工作 ⑳ I2Cバス その3-1 温湿度センサSHT45 BLEの概要

次へ

今から始める電子工作 ㉒ I2Cバス その3-3 温湿度センサSHT45 BLEセントラル