【BLE】【Swift3】浅草ギ研 BLESerial3最速レビュー（サンプルコードあり）

※ この記事は[ツクロア – DESIGN LAB](http://design-lab.tuqulore.com/bleselial3/)に投稿したものです。

浅草ギ研さんから近日発売予定の**「BLESerial3」**の試作品をいただきました。Swift3のサンプルコードとともに、BLESerial3を使ってみた感想を書きました。

## アウトライン

1. BLESerial3って
2. iOSアプリからBLESerial3 with Arduinoに信号を送ってLチカをしてみる
3. BLESerial3を使って作っている物の紹介
4. まとめ

## 1. BLESerial3って

浅草ギ研から発売される、BLEシリアル通信モジュールです。（[商品紹介ページ](http://www.robotsfx.com/robot/BLESerial3.html)）

### 特徴

下にいくつか自分が気になった特徴をピックアップしてみました。技術基準適合証明を受けているので安心して使うことができます。

- 電源電圧: 3.3V
- 使用ピン: 4本 
    - 電源
    - GND
    - RX
    - TX
- サイズ: 30x20x8.7(H)mm
- 技術基準適合証明を受けている

### BLESerial2との比較

BLESerialシリーズの第三弾ということでBLESerial2もありました。現在は生産を停止しています。ここで少し2と3の比較をしてみましょう。

![IMG_7013.png](https://qiita-image-store.s3.amazonaws.com/0/46645/cf1b5cba-9fa6-3f6d-973c-61621c14f3c2.png)
左がBLESerial2, 右がBLESerial3（BLESerial3にコードが付いていますが、これは自分でつけたものです。）

大きさは、2と比べると若干大きくなっています。

**BLESerial3からSSID（BLEセントラルから見た場合の名前）を変更できるようになりました。** 「BLESerial_F」（お使いのもので違うかも）とSSIDが付いています。このSSIDの最後の１文字を変更することが出来ます。（１６種類）


### いいなと思うポイント

何よりも、ピンを４本しか使わなくていいことが個人的に一番気に入っています。

またSSID（BLEセントラルから見た場合の名前）が変更できるようになったことは本当に嬉しい！！これで復数のBLESerial3を同時に利用しやすくなりした。感謝感謝です。しかも基板上のジャンパ設定で物理的に変えることが出来ます。もうやさしさしかない。。。

BLESerial3は、シンプル＆コンパクトなモジュールです。「BLEを用いてパパッと何か作りたいなぁ」なんて時は、BLESerial3がおすすめです。

## 2. iOSアプリからBLESerial3 with Arduinoに信号を送ってLチカをしてみる

BLESerial3に接続して、Lチカをやってみようと思います！

GitHubに今回のソースコードを公開しています。[tomonari-t/BLESerial3](https://github.com/tomonari-t/BLESerial3)

今回のアプリ画面のイメージです。

[デモ動画 - Vimeo](https://vimeo.com/197239880)

![Artboard.png](https://qiita-image-store.s3.amazonaws.com/0/46645/287be0c9-7d0e-bbbe-3814-0ce0dc3cbd4d.png)

「Connect BLE」をタップすると、BLESerial3を探し始め、見つかり接続するとアプリ画面上部にSSIDが表示されます。

## Arduino側

### 配線

ArduinoとBLESerialは以下の図のように接続してください

![Artboard 2.png](https://qiita-image-store.s3.amazonaws.com/0/46645/be5eb4db-e6d6-b48e-d873-6302da59f5a7.png)


注意ポイントとしてはRX,TXのつなぎ方を間違わないようにしてください。以下につなぎ方を示しました。

- BLESerial3のT（TX）はArduinoのRXへ
- BLESerial3のR（RX）はArduinoのTXへ

またLEDをArduinoの６番ピンにつないでください。

### ソースコード

[Arduino側のコード](https://github.com/tomonari-t/BLESerial3/blob/master/Arduino/BLESerial3.ino)です。Arduino Microを使用しています。

iOS側からは整数「**１** or **２**」を受け取ります。それに応じて、LEDが１回チカor２回チカします。

```cpp:BLESerial3.ino
const int PIN_LED = 6;

void blinkLED() {
   digitalWrite(PIN_LED, HIGH);
   delay(100);
   digitalWrite(PIN_LED, LOW);
}

void doubleBlinkLED() {
   digitalWrite(PIN_LED, HIGH);
   delay(100);
   digitalWrite(PIN_LED, LOW);
   delay(100);
   digitalWrite(PIN_LED, HIGH);
   delay(100);
   digitalWrite(PIN_LED, LOW);
}

void setup() {
  pinMode(PIN_LED, OUTPUT);
  Serial1.begin(9600);
}

void loop() {
  // データが送られてきたら
  if (Serial1.available() > 0) {
    int data = Serial1.read();

    if (data == 1) {
        blinkLED();
    }

    if (data == 2) {
        doubleBlinkLED();
    }
  }
}
```

## iOS側

続いてiOS側のコードです。ViewControllerに全てのコードを書いてあります。コード量が少しありますので、[こちらのリンクの](https://github.com/tomonari-t/BLESerial3/blob/master/BLESerial3-sample/BLESerial3-sample/ViewController.swift)ソースコードも併せて見てみてください。

以下はViewControllerのソースコードです。

```swift:ViewController.swift

import UIKit
import CoreBluetooth

class ViewController: UIViewController, CBCentralManagerDelegate, CBPeripheralDelegate {
    
    var centralManager: CBCentralManager!
    var peripheral: CBPeripheral!
    var characteristic: CBCharacteristic!
    var centralManagerReady: Bool = false
    var peripheralReady: Bool = false
    
    // MARK: - IBOutlet
    
    @IBOutlet weak var SSIDUILabel: UILabel!
    
    // MARK: - IBAction
    
    @IBAction func connectBtnTapped(_ sender: Any) {
        if !self.centralManagerReady {
            return
        }
        
        self.scanBLESerial3()
    }
    
    @IBAction func send1BtnTapped(_ sender: Any) {
        if !peripheralReady {
            return
        }
        
        var val1: Int = 1
        let data: NSData = NSData.init(bytes: &val1, length: 1)
        self.peripheral.writeValue(data as Data, for: self.characteristic, type: .withoutResponse)
    }
    
    @IBAction func send2BtnTapped(_ sender: Any) {
        if !peripheralReady {
            return
        }
        
        var val2: Int = 2
        let data: NSData = NSData.init(bytes: &val2, length: 1)
        self.peripheral.writeValue(data as Data, for: self.characteristic, type: .withoutResponse)
    }
    
    // MARK: - CBCentralManager Delegate
    
    // CBCentralManagerの状態が変化するたびに呼ばれる
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        switch central.state {
        case .poweredOn:
            self.centralManagerReady = true
        default:
             break
        }
    }
    
    // Scanをして、該当のBLE(ペリフェラル)が見つかると呼ばれる
    // 第2引数に該当のBLE（ペリフェラル）が渡されてくる
    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        print("発見したBLE: \(peripheral)")
        self.stopScan()
        self.connectPeripheral(peripheral: peripheral)
    }
    
    // BLE（ペリフェラル）に接続が成功すると呼ばれる
    // 第2引数に接続したBLE（ペリフェラル）が渡されてくる
    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        print("接続したBLE: \(peripheral)")
        self.SSIDUILabel.text = peripheral.name
        self.scanService()
    }
    
    // MARK: - CBPeripheralDelegate Delegate
    
    // サービスを発見すると呼ばれる
    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
        let service: CBService = peripheral.services![0]
        self.scanCharacteristics(service)
    }
    
    // キャラスタリスティックを発見すると呼ばれる
    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
        let characteristic: CBCharacteristic = service.characteristics![0]
        self.characteristic = characteristic
        
        peripheralReady = true
    }
    
    // MARK: - Method
    
    func scanBLESerial3() {
        let BLESerial3UUID: [CBUUID] = [CBUUID.init(string: "FEED0001-C497-4476-A7ED-727DE7648AB1")]
        self.centralManager?.scanForPeripherals(withServices: BLESerial3UUID, options: nil)
    }
    
    func stopScan() {
        self.centralManager.stopScan()
    }
    
    func connectPeripheral(peripheral: CBPeripheral) {
        self.peripheral = peripheral
        self.centralManager.connect(self.peripheral, options: nil)
    }
    
    func scanService() {
        self.peripheral.delegate = self
        let TXCBUUID: [CBUUID] = [CBUUID.init(string: "FEED0001-C497-4476-A7ED-727DE7648AB1")]
        self.peripheral.discoverServices(TXCBUUID)
    }
    
    func scanCharacteristics(_ service: CBService) {
        let characteristics: [CBUUID] = [CBUUID.init(string: "FEEDAA02-C497-4476-A7ED-727DE7648AB1")]
        self.peripheral.discoverCharacteristics(characteristics, for: service)
    }
    
    // MARK: - LifeCycle
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // centralManagerを初期化する
        self.centralManager = CBCentralManager(delegate: self, queue: nil)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

```

データを送るまでに以下３つの手順を踏んでいます。
1. ペリフェラルを見つけて登録(100行目付近)
2. 見つけたペリフェラルが持っているサービスを見つけて登録（114行目付近）
3. 見つけたサービスが持っている書き込み用のキャラスタリスティックを見つけて登録(120行目付近)

### Lチカ

1. BLESerial3とLEDを接続し、ソースコードを書き込んだArduinoの電源を入れます
2. iOSのアプリを起動します
3. Connect BLEボタンをタップ
4. 接続が成功すると、BLESerial3の赤いランプが点灯します
5. SendボタンをタップしてLチカ

### 補足

ペリフェラル: 子機のことです。今回はiOSを親機、BLESerial3を子機として動かしています。ペリフェラルが機能ごとにサービスをもっており、そのなかに復数のキャラスタリスティックがあります。

BLESerial3は**サービスは１つ（UUID: FEED0001-C497-4476-A7ED-727DE7648AB1）**。キャラスタリスティックは**データ書き込み用（UUID: FEEDAA02-C497-4476-A7ED-727DE7648AB1）**、**データ受信用（UUID: FEEDAA03-C497-4476-A7ED-727DE7648AB1）**の２つが存在しています。

## 3. BLESerial3を使って作っている物の紹介

![img08.png](https://qiita-image-store.s3.amazonaws.com/0/46645/2f3b3ee2-0bad-d9ea-a201-baf3563037b4.png)

「[Bubbly（バブリー）](http://cityanddots.com/#works01)」というストリートパフォーマのための投げ銭ガジェットを作っています。このガジェット（BLESerial3とArduinoが中に入っています）のコントロールやパラメーター（光り方・ファンスピードなど）の調整をiOSアプリから行なっています。

## 4. まとめ

BLESerial3はシンプルで使いやすいモジュールです。ぜひ使ってみてください！

[BLESerial3 - 販売ページ](http://shop.robotsfx.com/shopdetail/000000000204/)

## 最後に

至らぬ点があるかもしれません。何かありましたらお手数ですがご指摘をお願いします。

浅草ギ研さん、いつも快適に開発ができています。本当にありがとうございます。