初めての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はバッテリで動かしています。

前へ

初めてのBLE (7) micro:bitでペリフェラル④温度キャラをArduinoセントラルで受け取る

次へ

初めてのBLE (9) Raspberry Piでペリフェラル①bluetoothctlとhciconfig