初めてのBLE (8) micro:bitでペリフェラル⑤UART温度をArduinoセントラルで受け取る
キャラの温度は読み出すだけでよかったのですが、UARTサービスは、サーバの立場であるペリフェラルとクライアントの立場であるセントラル間でデータのやり取りが発生します。UARTの受信例はペリフェラルのサンプル・スケッチのLEDControlをベースに、送信の例はSensorTagButtonをベースにスケッチを作っていきます。
ペリフェラルを動作させているのは、Arduino Nano 33 BLE Senseです。
●受信のスケッチ
LEDのON/OFFは一部残しました。
scanForUuid()はUARTサービスを探してこれなかったので、scanForName()に変更しました。
ON/OFFするために、ledCharacteristic.writeValue()は1バイトのデータを送っていましたが、文字列データに変更しました。デリミタは「:」です。
つながったら、2番ピンは出力をLowに初期設定しているので、123:を送ります。2番ピンをGNDにつないで離すとBLE:が送られ、LEDに表示が出ます。
#include <ArduinoBLE.h> #define localNAME "BBC micro:bit [gavag]" #define serviceUUID "6e400001-b5a3-f393-e0a9-e50e24dcca9e" // UART #define characteristicTxUUID "6e400002-b5a3-f393-e0a9-e50e24dcca9e" // Tx #define characteristicRxUUID "6e400003-b5a3-f393-e0a9-e50e24dcca9e" // Rx #define ButtonPressed "123:" #define ButtonReleased "BLE:" // variables for button const int buttonPin = 2; int oldButtonState = LOW; void setup() { Serial.begin(9600); while (!Serial); // configure the button pin as input pinMode(buttonPin, INPUT); // initialize the BLE hardware BLE.begin(); Serial.println("start BLE Central - UART control"); // start scanning for peripherals // BLE.scanForUuid("6E400001-B5A3-F393-E0A9-E50E24DCCA9E"); // BLE UART Service 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(); controlLed(peripheral); // peripheral disconnected, start scanning again // BLE.scanForUuid(serviceUUID); // BLE UART Service BLE.scanForName(localNAME); } } void controlLed(BLEDevice peripheral) { // connect to the peripheral Serial.println("Connecting ..."); if (peripheral.connect()) { Serial.println("Connected"); } else { Serial.println("Failed to connect!"); return; } // discover peripheral attributes Serial.println("Discovering attributes ..."); if (peripheral.discoverAttributes()) { Serial.println("Attributes discovered"); } else { Serial.println("Attribute discovery failed!"); peripheral.disconnect(); return; } // retrieve the LED characteristic BLECharacteristic ledCharacteristic = peripheral.characteristic(characteristicRxUUID); if (!ledCharacteristic) { Serial.println("Peripheral does not have LED characteristic!"); peripheral.disconnect(); return; } else if (!ledCharacteristic.canWrite()) { Serial.println("Peripheral does not have a writable LED characteristic!"); peripheral.disconnect(); return; } while (peripheral.connected()) { // while the peripheral is connected // read the button pin int buttonState = digitalRead(buttonPin); if (oldButtonState != buttonState) { // button changed oldButtonState = buttonState; if (buttonState) { Serial.println(ButtonPressed); // button is pressed, write 0x01 to turn the LED on ledCharacteristic.writeValue(ButtonPressed, 4); // send 123: } else { Serial.println(ButtonReleased); // button is released, write 0x00 to turn the LED off ledCharacteristic.writeValue(ButtonReleased, 4); // send BLE: } } } Serial.println("Peripheral disconnected"); }
シリアルモニタの様子です。実験を中断していても、2ピンを触ると、すぐに再接続してくれました。
●送信のスケッチ
サンプル・スケッチSensorTagButtonをベースに修正します。
#include <ArduinoBLE.h> #define localNAME "BBC micro:bit [gavag]" #define serviceUUID "6e400001-b5a3-f393-e0a9-e50e24dcca9e" // UART #define characteristicTxUUID "6e400002-b5a3-f393-e0a9-e50e24dcca9e" // Tx #define characteristicRxUUID "6e400003-b5a3-f393-e0a9-e50e24dcca9e" // Rx void setup() { Serial.begin(9600); while (!Serial); // begin initialization if (!BLE.begin()) { Serial.println("starting BLE failed!"); while (1); } Serial.println("start BLE Central - UART A button"); Serial.println("Make sure to turn on the device."); // start scanning for peripheral BLE.scan(); } 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(); // Check if the peripheral is a SensorTag, the local name will be: // "CC2650 SensorTag" if (peripheral.localName() == localNAME) { // stop scanning BLE.stopScan(); monitorSensorTagButtons(peripheral); // peripheral disconnected, start scanning again BLE.scan(); } } } void monitorSensorTagButtons(BLEDevice peripheral) { // connect to the peripheral Serial.println("Connecting ..."); if (peripheral.connect()) { Serial.println("Connected"); } else { Serial.println("Failed to connect!"); return; } // discover peripheral attributes Serial.println("Discovering service UART ..."); if (peripheral.discoverService(serviceUUID)) { Serial.println("Service discovered"); } else { Serial.println("Attribute discovery failed."); peripheral.disconnect(); while (1); return; } // retrieve the simple key characteristic BLECharacteristic simpleKeyCharacteristic = peripheral.characteristic(characteristicTxUUID); // subscribe to the simple key characteristic Serial.println("Subscribing to simple key characteristic ..."); if (!simpleKeyCharacteristic) { Serial.println("no simple key characteristic found!"); peripheral.disconnect(); return; } else if (!simpleKeyCharacteristic.canSubscribe()) { Serial.println("simple key characteristic is not subscribable!"); peripheral.disconnect(); return; } else if (!simpleKeyCharacteristic.subscribe()) { Serial.println("subscription failed!"); peripheral.disconnect(); return; } else { Serial.println("Subscribed"); Serial.println("Press the A buttons on your micro:bit."); } while (peripheral.connected()) { // while the peripheral is connected // check if the value of the simple key characteristic has been updated if (simpleKeyCharacteristic.valueUpdated()) { // yes, get the value, characteristic is 1 byte so use byte value byte value[2] ; simpleKeyCharacteristic.readValue(value,2); printData(value,2); Serial.println(); } } Serial.println("SensorTag disconnected!"); } void printData(const unsigned char data[], int length) { for (int i = 0; i < length; i++) { unsigned char b = data[i]; if (b < 16) { Serial.print("0"); } //Serial.print(b, HEX);Serial.print(" "); Serial.print((b-48), HEX); } }
シリアルモニタの様子です。micro:bitのCPU上に指を載せて、ボタンAを押しています。
セントラルのmicro:bitはバッテリで動かしています。