今から始める電子工作 ㉑ 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にチャックを入れて使います。