今から始める電子工作 ㉒ I2Cバス その3-3 温湿度センサSHT45 BLEセントラル
ここでは、前回製作した「温湿度センサSHT45のデータを利用したBLEペリフェラル」に対応するBLEセントラルを作ります。
●環境
- Arduino IDE;2.3.4
- Windows11;24H2
- Arduino UNO R4 WiFi
- ArduinoBLEライブラリ1.3.7
●前回作成したBLEペリフェラル
スケッチは、コンソールへの出力を全部コメントアウトしました。
12Vの電源をDCジャックに入れ、動作させます。
RSL10で、動作を確認します。
●BLEセントラルの構成
もう一台マイコン・ボードArduino UNO R4 WiFiを用意します。PCとはUSBケーブルで接続します。QWIICケーブルで、OLEDグラフィック・ディスプレイを接続します。
●BLEscanする
BLEで接続できる機器を探します。
ArduinoBLE/examples/Central/Scan/Scan.ino
を新規スケッチでコピペして動かします。保存名はBLEscanにしました。
コンパイルして実行すると、SHT45がつながったBLEペリフェラルを探してきました。RSSIは信号の強さです。
●BLEの各種定義
BLEペリフェラルとはlocalNAMEで選択します。
#define localNAME "SHT45_float"
接続できたら、キャラクタリスティックを指定して読み出します。
#define SHT45_Temp_Characteristic_UUID "F000AA31-0451-4000-B000-000000000000" // BLE Characteristic #define SHT45_Humidity_Characteristic_UUID "F000AA32-0451-4000-B000-000000000000"
●setupーBLE
最初に初期化します。
BLE.begin();
localNAMEで探します。
BLE.scanForName(localNAME);
●loopーBLE
ペリフェラルが見つかったらアドレス、localNAME、サービスUUIDを印字します。
// 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();
スキャンを止めます。
BLE.stopScan();
読み出し関数を実行します。
readData(peripheral);
読み出し関数 readData() では、最初にconnectします。
if (peripheral.connect()) {
次にdiscoverします。
if (peripheral.discoverAttributes()) {
温度と湿度のUUIDでデータを取得します。
BLECharacteristic Temperature_Characteristic = peripheral.characteristic(SHT45_Temp_Characteristic_UUID); BLECharacteristic Humidity_Characteristic = peripheral.characteristic(SHT45_Humidity_Characteristic_UUID);
温度のバイナリ・データを読み出し、IEEE-754 フォーマット(単精度浮動小数点数)を実数に変換して印字します。
参考;IEEE754 単精度浮動小数点数の形式:binary32 の変換
Temperature_Characteristic.read(); if (Temperature_Characteristic.valueLength() > 0) { uint32_t data = ((uint8_t)*(Temperature_Characteristic.value()+3) << 24) + ((uint8_t)*(Temperature_Characteristic.value()+2) << 16) + ((uint8_t)*(Temperature_Characteristic.value()+1) << 8) + ((uint8_t)*Temperature_Characteristic.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);
湿度のデータも同様に読み出して実数に変換して印字します。
スケッチです。
#include <ArduinoBLE.h> #define localNAME "SHT45_float" #define SHT45_Temp_Characteristic_UUID "F000AA31-0451-4000-B000-000000000000" // BLE Characteristic #define SHT45_Humidity_Characteristic_UUID "F000AA32-0451-4000-B000-000000000000" void setup() { Serial.begin(9600); delay(1000); BLE.begin(); Serial.println("\n start BLE peripherals - Temperature/Humidity"); // 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(); readData(peripheral); // peripheral disconnected, start scanning again BLE.scanForName(localNAME); } } void readData(BLEDevice peripheral) { byte buffer[2] ; // connect to the peripheral Serial.print("\nConnecting ..."); 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 characteristic BLECharacteristic Temperature_Characteristic = peripheral.characteristic(SHT45_Temp_Characteristic_UUID); BLECharacteristic Humidity_Characteristic = peripheral.characteristic(SHT45_Humidity_Characteristic_UUID); if (!Temperature_Characteristic) { Serial.println("Peripheral does not have Temp characteristic!"); peripheral.disconnect(); return; } Serial.println("---Found CHARACTERISTIC_UUID"); while (peripheral.connected()) { if (Temperature_Characteristic.canRead()) { // read the characteristic value Temperature_Characteristic.read(); if (Temperature_Characteristic.valueLength() > 0) { uint32_t data = ((uint8_t)*(Temperature_Characteristic.value()+3) << 24) + ((uint8_t)*(Temperature_Characteristic.value()+2) << 16) + ((uint8_t)*(Temperature_Characteristic.value()+1) << 8) + ((uint8_t)*Temperature_Characteristic.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); Humidity_Characteristic.read(); data = ((uint8_t)*(Humidity_Characteristic.value()+3) << 24) + ((uint8_t)*(Humidity_Characteristic.value()+2) << 16) + ((uint8_t)*(Humidity_Characteristic.value()+1) << 8) + ((uint8_t)*Humidity_Characteristic.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(1000); } } } Serial.println("Peripheral disconnected"); }
実行します。
●OLEDグラフィック・ディスプレイに受信したデータを表示
AdafruitのOLEDライブラリ、グラフィック・ライブラリ類の記述を追加します。
#include <ArduinoBLE.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_SH110X.h>
#include <Fonts/FreeSans9pt7b.h> #define localNAME "SHT45_float" #define SHT45_Temp_Characteristic_UUID "F000AA31-0451-4000-B000-000000000000" // BLE Characteristic #define SHT45_Humidity_Characteristic_UUID "F000AA32-0451-4000-B000-000000000000" Adafruit_SSD1306 display(128, 64, &Wire1); void setup() { Serial.begin(9600); delay(1000); BLE.begin(); Serial.println("\n start BLE central - Temperature/Humidity"); BLE.scanForName(localNAME); Wire1.begin(); if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3D)) { Serial.println(F("SSD1306 allocation failed")); for(;;); // Don't proceed, loop forever } Serial.println("OLED begun"); display.clearDisplay(); display.display(); display.setRotation(0); display.setFont(&FreeSans9pt7b); display.setTextColor(SH110X_WHITE); } 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(); readData(peripheral); // peripheral disconnected, start scanning again BLE.scanForName(localNAME); } } void readData(BLEDevice peripheral) { byte buffer[2] ; // connect to the peripheral Serial.print("\nConnecting ..."); 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 characteristic BLECharacteristic Temperature_Characteristic = peripheral.characteristic(SHT45_Temp_Characteristic_UUID); BLECharacteristic Humidity_Characteristic = peripheral.characteristic(SHT45_Humidity_Characteristic_UUID); if (!Temperature_Characteristic) { Serial.println("Peripheral does not have Temp characteristic!"); peripheral.disconnect(); return; } Serial.println("---Found CHARACTERISTIC_UUID"); while (peripheral.connected()) { if (Temperature_Characteristic.canRead()) { // read the characteristic value Temperature_Characteristic.read(); if (Temperature_Characteristic.valueLength() > 0) { uint32_t data = ((uint8_t)*(Temperature_Characteristic.value()+3) << 24) + ((uint8_t)*(Temperature_Characteristic.value()+2) << 16) + ((uint8_t)*(Temperature_Characteristic.value()+1) << 8) + ((uint8_t)*Temperature_Characteristic.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)); float aTemperature = f*k*s; Serial.print("\ntemp = ") ; Serial.println(aTemperature); Humidity_Characteristic.read(); data = ((uint8_t)*(Humidity_Characteristic.value()+3) << 24) + ((uint8_t)*(Humidity_Characteristic.value()+2) << 16) + ((uint8_t)*(Humidity_Characteristic.value()+1) << 8) + ((uint8_t)*Humidity_Characteristic.value()); f = pow(-1, int(bitRead(data,31))); k =1 + ((((data<<1)<<8)>>9))/pow(2,23); s = pow(2,((((data<<1)>>24))-127)); float aHumidity = f*k*s; Serial.print("Humi = "); Serial.println(aHumidity); display.clearDisplay(); display.setCursor(0, 20); display.println("SHT45 /w BLE"); display.setCursor(0, 40); display.print("Temp: "); display.print(aTemperature,1); display.println(" 'C"); display.print("Hum: "); display.print(aHumidity,1); display.println(" %"); display.display(); delay(1000); } } } Serial.println("Peripheral disconnected"); }
実行中の様子です。