iPhoneからBLEで自作機器をコントロールする案件で、MBED HRM1017が売り切れで入手できなかったので代わりとなるものを探したところBlend Microなるものを見つけました。Arduino互換のBLE受信器付きマイコンボードです。マイコンはATMega32U4で3.3V/8MHz駆動となります。
ポートはD0〜D13(D4,6,7を除く)、A0〜A5、SPIが使えます。BLEの通信は、ble_write('a')、ble_read()みたいな感じで何も考えずに使うことができます。
開発環境としてCodeBenderというmbed風のオンラインIDEが提供されていて、こちらもなかなか快適です。コンパイルや基板へのダウンロードは本家のIDEよりもかなり速い印象です。
ただし重大な欠点がひとつあって、コンパイル(ベリファイ)してもソースコードファイルが保存されません。他の開発環境はだいたいcompile==saveになっているので、ついつい保存しないまま終了してしまいすべて失うというミスを何度か冒しました。
***サンプル***
・BlendMicro側
//"SPI.h/Nordic_nRF8001.h/RBL_nRF8001.h" are needed in every new project #include <SPI.h> #include <Nordic_nRF8001.h> #include <RBL_nRF8001.h> const int ledPort = 0; void setup() { pinMode(ledPort, OUTPUT); // Init. and start BLE library. ble_begin(); } void loop() { while ( ble_available() ) { switch(ble_read()){ case 0: digitalWrite(ledPort, 0); break; case 1: digitalWrite(ledPort, 1); break; } } ble_do_events(); }
・iPhone側
書籍「iOSxBLE CoreBluetoothプログラミング」を参考にしました。
viewController.h
#import <UIKit/UIKit.h> @interface ViewController : UIViewController { unsigned char value; } @end
viewController.m
#define SERVICE_UUID @"713D0000-503E-4C75-BA94-3148F18D941E" #define CHARA_READ_UUID @"713D0002-503E-4C75-BA94-3148F18D941E" #define CHARA_WRITE_UUID @"713D0003-503E-4C75-BA94-3148F18D941E" #import "ViewController.h" @import CoreBluetooth; @interface ViewController () <CBCentralManagerDelegate, CBPeripheralDelegate> { BOOL isScanning; } @property (nonatomic, strong) CBCentralManager *centralManager; @property (nonatomic, strong) CBPeripheral *peripheral; @property (nonatomic, strong) CBCharacteristic *writeCharacteristic; @property (nonatomic, strong) CBCharacteristic *readCharacteristic; @property (weak, nonatomic) IBOutlet UIButton *scanBtn; - (IBAction)startBtnTapped:(id)sender; - (IBAction)ledBtnTapped:(id)sender; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. value = 0; self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } // ============================================================================= #pragma mark - CBCentralManagerDelegate - (void)centralManagerDidUpdateState:(CBCentralManager *)central { // 特に何もしない NSLog(@"centralManagerDidUpdateState:%ld", (long)central.state); } - (void) centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI { NSLog(@"発見したBLEデバイス:%@", peripheral); if ([peripheral.name hasPrefix:@"BlendMicro"]) { self.peripheral = peripheral; // 接続開始 [self.centralManager connectPeripheral:peripheral options:nil]; } } - (void) centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral { NSLog(@"接続成功!"); peripheral.delegate = self; // サービス探索開始 [peripheral discoverServices:nil]; } - (void) centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error { NSLog(@"接続失敗・・・"); } // ============================================================================= #pragma mark - CBPeripheralDelegate // サービス発見時に呼ばれる - (void) peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error { if (error) { NSLog(@"エラー:%@", error); return; } NSArray *services = peripheral.services; NSLog(@"%lu 個のサービスを発見!:%@", (unsigned long)services.count, services); for (CBService *service in services) { // キャラクタリスティック探索開始 [peripheral discoverCharacteristics:nil forService:service]; } } // キャラクタリスティック発見時に呼ばれる - (void) peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error { if (error) { NSLog(@"エラー:%@", error); return; } NSArray *characteristics = service.characteristics; NSLog(@"%lu 個のキャラクタリスティックを発見!%@", (unsigned long)characteristics.count, characteristics); for (CBCharacteristic *characteristic in characteristics) { if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:CHARA_READ_UUID]]) { self.readCharacteristic = characteristic; NSLog(@"CHARA_READ_UUID を発見!"); } else if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:CHARA_WRITE_UUID]]) { self.writeCharacteristic = characteristic; [_scanBtn setTitle:@"DISCONNECT" forState:UIControlStateNormal]; [_scanBtn setTitleColor:[UIColor greenColor] forState:UIControlStateNormal]; NSLog(@"CHARA_WRITE_UUID を発見!"); } } } // データ書き込みが完了すると呼ばれる - (void) peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error { if (error) { NSLog(@"Write失敗...error:%@", error); return; } NSLog(@"Write成功!"); } - (IBAction)startBtnTapped:(id)sender { if (!isScanning) { isScanning = YES; // スキャン開始 [self.centralManager scanForPeripheralsWithServices:nil options:nil]; //[sender setTitle:@"STOP" forState:UIControlStateNormal]; [_scanBtn setTitleColor:[UIColor yellowColor] forState:UIControlStateNormal]; } else { // スキャン停止 [self.centralManager stopScan]; if ([self.peripheral.name hasPrefix:@"BlendMicro"]) { [self.centralManager cancelPeripheralConnection:self.peripheral]; } [sender setTitle:@"CONNECT" forState:UIControlStateNormal]; isScanning = NO; [_scanBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; } } - (IBAction)ledBtnTapped:(id)sender { NSData *data; value = !value; data = [[NSData alloc] initWithBytes:&value length:1]; [self sendBLE:data]; } - (void)sendBLE:(NSData *)data { [self.peripheral writeValue:data forCharacteristic:self.writeCharacteristic type:CBCharacteristicWriteWithoutResponse]; } @end