初めてのBLE (18) CircuitPythonでペリフェラル② Nano 33 BLE senseでセントラル
前回、AdafruitのFeather nRF52840 Expressを用い、CircuitPythonでペリフェラルが動きました。送っているのはCPUの温度値です。ここでは、マイコン・ボードNano 33 BLE senseを使ってArduino IDEでセントラルを作ります。
●セントラルのスケッチ
第16回で作成したセントラルのスケッチをベースに修正します。
CircuitPythonでペリフェラルは、3秒おきにデータを送ってきます。ソースを読むと、NotifyはONになっています。前回、オン・セミコンダクターのBLEであるRSL10 Bluetooth Low Enaergy Exploerを使って情報をやり取りしたときも、Notificationをチェックしたら、データを受信始めました。しかし、ArduinoBLEにstart notifyに相当する関数が見つかりません。実験をしていると、
if (UARTCharacteristic.canRead()) {
canRead()関数でエラーになったときに、start notifyが発行されているようです。
前回作ったCircuitPythonのプログラムでは、binary32 のデータをビッグ・エンディアンで送ってきますから、readしたデータを1バイトずつ順に読み出し、順に上位にシフトし、合成し、32ビットのバイト列を作ります。
連載の第15回でも利用しましたが、その32ビットのデータの先頭1ビットを符号(f)で取り出し、次の8ビットを指数(s)、残りの22ビットの先頭に1を加えて仮数(k)とします。三つの結果をかけあわせると浮動小数点の値に戻ります。
#include <ArduinoBLE.h>
#define SERVICE_UUID "6e400001-b5a3-f393-e0a9-e50e24dcca9e" // UART
#define characteristicTxUUID "6e400002-b5a3-f393-e0a9-e50e24dcca9e" // Tx
#define characteristicRxUUID "6e400003-b5a3-f393-e0a9-e50e24dcca9e" // Rx
#define localNAME "Feather nRF52840 Express"
void setup() {
Serial.begin(9600);
while (!Serial);
BLE.begin();
Serial.println("\nstart BLE Central - temp");
// 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();
readUARTdata(peripheral);
// peripheral disconnected, start scanning again
BLE.scanForName(localNAME);
}
}
void readUARTdata(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 LED characteristic
BLECharacteristic UARTCharacteristic = peripheral.characteristic(characteristicRxUUID);
if (!UARTCharacteristic) {
Serial.println("Peripheral does not have UART characteristic!");
peripheral.disconnect();
return;
}
Serial.println("---Found CHARACTERISTIC_UUID");
while (peripheral.connected()) {
// Serial.println("connected");
if (UARTCharacteristic.canRead()) {
Serial.println("canread");
} else {
// Serial.println("error reading characteristic value");
// read the characteristic value
UARTCharacteristic.read();
Serial.println("read");
if (UARTCharacteristic.valueLength() > 0) {
uint32_t data = ((uint8_t)*(UARTCharacteristic.value()) << 24) + ((uint8_t)*(UARTCharacteristic.value()+1) << 16) + ((uint8_t)*(UARTCharacteristic.value()+2) << 8) + ((uint8_t)*UARTCharacteristic.value()+3);
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);
delay(5000);
}
}
}
Serial.println("Peripheral disconnected");
}
実行した様子です。ペリフェラルが動いているFeather nRF52840 Expressボード上のモジュールを指でつまむと、温度が上がってくるので、正常に動いているようです。