workshop/of/iOSBLE

BLE(Bluetooth Low Energy)

2015年11月2日更新 BLEの細かな内容に関しては適時インターネットで調べてください.

準備

OF

Openframeworksのためにいくつのアドオンが公開されています.このページでは https://github.com/joshuajnoble/ofxBLEDevice を利用して動作を確認しました.(Xcode: 7, OF:0.8.4)

ダウンロードしたフォルダの内,src/以下をOFのaddonフォルダにofxBLEとして保存しておきます.なおこのプロジェクトにはCoreBluetooth.frameworkが 必要になるので,プロジェクトに追加しておいてください.また,Xcode7以降だと,OFのビルド時にbitcodeなるものをNOに変更しておく必要があります. エラーが出た場合は下記画像をみて対処してください.

bit codeに関するエラーになった場合は,Enable BitcodeをNOに変更する

デバイス

このページではRedBearLabのnRF51822(V1.0)を利用しました.これをArduino環境で動作させるには http://redbearlab.com/getting-started-nrf51822/ を参照してください.ExampleであるBLE Serialを書き込んでおきます.ただし現状のサンプルでは送受信の両方を確認できないので,nRF51822から iOS側へデータを送る部分を追加しておきます.具体的には uart_hand関数内の最後に送信部分のコードを追加します.これはArduinoのシリアルモニタから 文字列を送信した場合,直接iOS側にBLE経由でそのデータを送るようになっています.なおBLE Nanoを利用した場合,Bluetoothモジュールは取り外しが できるので,BLE Serialを書き込んだ後は,シリアル通信でデータをやり取りできる無線通信モジュールとして独立して使用できます.例えばBLEモジュールを AVRマイコン単体で小型化することも容易になります.その場合はBLEモジュール側は3.3V供給で,ArduinoのRXピンには3.3V以下がHIGHになるように注意します. ちゃんとやりたい人は,シリアル通信のレベル変換ICとか使ってください.下図のように接続することで,PCのArduinoシリアルモニタでデータのやり取りが確認できます. ただしマイコン単体で動作させる場合はTX,RXの接続が逆になるので注意してください.

BLEモジュールをArduinoの無線通信モジュールとしてシリアルモニタでデバッグする際の配線.(モジュールをモジュースと書いてますが気にしないでください)

void uart_handle(uint32_t id, SerialIrq event)
{ /* Serial1 rx IRQ */
  if (event == RxIrq) {
    if (rx_state == 0) {
      rx_state = 1;
      timeout.attach_us(m_uart_rx_handle, 100000);
      rx_buf_num = 0;
    }
    while (Serial1.available()) {
      if (rx_buf_num < 20) {
        rx_buf[rx_buf_num] = Serial1.read();
        rx_buf_num++;
      }
      else {
        Serial1.read();
      }

    }
    // sending rx_buf data to iOS
    ble.updateCharacteristicValue(characteristic2.getValueAttribute().getHandle(), rx_buf, rx_buf_num);
  }
}

接続テスト

ofApp::didDiscoverBLEDevice(BLEDevice *device);の中身を確認して,接続したいBLEデバイスの名前を 指定してください.これは先程のArduinoコードにて"BLE Serial"と指定されています.deviceNameが任意の文字列と同じであれば,接続が開始するようになっています.馬場の環境では BLEDeviceManager.mにて一箇所エラーがでましたが,次のようにキャスティングをしてあげれば問題なかったです. const uint8_t *bytes = (const uint8_t*)[manufacturerData bytes]; 次に馬場の手元の環境だとデータの受診時にUUIDチェックで受信処理が弾かれていたので BLEDevice.mのperipheral関数を 次のように修正しました.


- (void)peripheral:(CBPeripheral *)aPeripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
    NSLog(@"didUpdateValueForCharacteristic");
    CBUUID *treceive_uuid = [CBUUID UUIDWithString:(customUUID ? customUUID : @"2221")];

//  if ([characteristic.UUID isEqual:treceive_uuid]) {
        SEL didReceive = @selector(didReceive:);
        if ([delegate respondsToSelector:didReceive]) {
            [delegate didReceive:characteristic.value];
        }
//    }
}

なおofApp.mm, ofApp.hそのままでも 構いませんが,接続と受信データがわかるように下記の様に修正しました.

ofApp.mm

#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup()
{
    //BLEDeviceManager = BLEDeviceManager.sharedBLEDeviceManager;
    
    BLEDeviceImpl = [[ofxBLEDeviceDelegate alloc] init];
    [BLEDeviceImpl setApplication:this];
    
    //ofLog(tx);
    
    tx.UUID = @"713D0003-503E-4C75-BA94-3148F18D941E";
    tx.shouldNotify = false;
    
    charas.push_back(tx);
    
    rx.UUID = @"713D0002-503E-4C75-BA94-3148F18D941E";
    rx.shouldNotify = true;
    
    charas.push_back(rx);
    
    ofxBLESetCharacteristics(charas);
  isConnected = false;
}

//--------------------------------------------------------------
void ofApp::update(){
    
}

//--------------------------------------------------------------
void ofApp::draw(){
  if( isConnected == true ){
    ofDrawBitmapString("Connected: " + ble_device, 20, 20);
    ofDrawBitmapString(latest_message, 20, 60);
  }
  else{
    ofDrawBitmapString("Scanning.. : " + ble_device, 20, 20);
  }
}

//--------------------------------------------------------------
void ofApp::exit(){
    
}

//--------------------------------------------------------------
void ofApp::touchDown(ofTouchEventArgs & touch){
    unsigned char data[3];
    data[0] = '1';
    data[1] = '2';
    data[2] = '3';
    ofxBLESendData(BLEDeviceImpl, &data[0], tx, 3);
}

//--------------------------------------------------------------
void ofApp::touchMoved(ofTouchEventArgs & touch){
    
}

//--------------------------------------------------------------
void ofApp::touchUp(ofTouchEventArgs & touch){
    
}

//--------------------------------------------------------------
void ofApp::touchDoubleTap(ofTouchEventArgs & touch){
    
}

//--------------------------------------------------------------
void ofApp::touchCancelled(ofTouchEventArgs & touch){
    
}

//--------------------------------------------------------------
void ofApp::lostFocus(){
    
}

//--------------------------------------------------------------
void ofApp::gotFocus(){
    
}

//--------------------------------------------------------------
void ofApp::gotMemoryWarning(){
    
}

//--------------------------------------------------------------
void ofApp::deviceOrientationChanged(int newOrientation){
    
}

//--------------------------------------------------------------
void ofApp::didDiscoverBLEDevice(BLEDevice *device)
{
  cout << " didDiscoverBLEDevice " << endl;
  if(device.name != nil){
    std::string deviceName([device.name UTF8String]);
    ble_device = deviceName;
    if(deviceName == "BLE Serial") {
      ofxBLEConnectDevice(device);
      ble_device = deviceName;
      isConnected = true;
    }
  }
}

void ofApp::didUpdateDiscoveredBLEDevice(BLEDevice *device)
{
    cout << " didUpdateDiscoveredBLEDevice " << endl;
}

void ofApp::didConnectBLEDevice(BLEDevice *device)
{
    cout << " didConnectBLEDevice " << endl;
}

void ofApp::didLoadServiceBLEDevice(BLEDevice *device)
{
    cout << " didLoadServiceBLEDevice " << endl;
}

void ofApp::didDisconnectBLEDevice(BLEDevice *device)
{
    cout << " didDisconnectBLEDevice " << endl;
  isConnected = false;
}

void ofApp::receivedData( const char *data)
{
    cout << " got some data! :"  << data << endl;
  
  latest_message = string(data);
}


ofApp.h

#pragma once

#include "ofMain.h"
#include "ofxiOS.h"
#include "ofxiOSExtras.h"
#include "ofxBLEDeviceApp.h"
#include "ofxBLEDeviceDelegate.h"
#include "ofxBLEDeviceDelegateCpp.h"
#include "BLEDeviceManager.h"

class ofApp : public ofxiOSApp, public ofxBLEDeviceApp {
    
public:
  
  void setup();
  void update();
  void draw();
  void exit();
  
  void touchDown(ofTouchEventArgs & touch);
  void touchMoved(ofTouchEventArgs & touch);
  void touchUp(ofTouchEventArgs & touch);
  void touchDoubleTap(ofTouchEventArgs & touch);
  void touchCancelled(ofTouchEventArgs & touch);
  
  void lostFocus();
  void gotFocus();
  void gotMemoryWarning();
  void deviceOrientationChanged(int newOrientation);
  
  void didDiscoverBLEDevice(BLEDevice *device);
  void didUpdateDiscoveredBLEDevice(BLEDevice *device);
  void didConnectBLEDevice(BLEDevice *device);
  void didLoadServiceBLEDevice(BLEDevice *device);
  void didDisconnectBLEDevice(BLEDevice *device);
  void receivedData( const char *data);
  
  ofxBLEDeviceDelegate *BLEDeviceImpl;
  
  vector<ofxBLECharacteristic> charas;
  ofxBLECharacteristic rx;
  ofxBLECharacteristic tx;
  string latest_message;
  string ble_device;
  bool isConnected;
};

ではアプリケーションを立ち上げ,ArduinoのシリアルモニタをRedBearLabのシリアルポートに合わせて 開いて下さい.画面をタップするとシリアルポートに"123"の文字列.シリアルポートからテキストを送信すると そのテキストがiOSアプリ上に表示されるのを確認してください.

接続時のアプリスクリーンショット.Arduinoのシリアルモニタに"Hello BLE!!"と入力した文字列が表示されている
以上.日高さんからBLE Serial借りたらそっちのレポートをおってしようとおもいます.

Copyright (c) 2015 Tetsuaki BABA all rights reserved.