今から始める電子工作 ㉑ 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());
while (central.connected()) {
updateValue();
delay(1000);
}
接続が切れると、メッセージを出します。
// when the central disconnects
Serial.print("Disconnected from central: ");
Serial.println(central.address());
}
// update characteristic
SHT45_Temp.writeValue(temperature);
SHT45_Humi.writeValue(humidity);
#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
}
}
実数の4バイトのデータは直読できませんから、次のWebサイトで変換しました。Swap to use big-endianにチャックを入れて使います。