BLE Nano でLED制御 ～BLE Nano + NeoPixel + Android～

BLE Nano で NeoPixel の LED 制御と、BLE GATT 通信を確認したので、今度は、この2つを合わせていきます。

# BLE Nano のバイナリ作成

まず、BLE Nano の制御プログラムを作っています。

## NeoPixel のライブラリの組み込み

BLE GATT 通信のサンプルコードに、NeoPixel の制御用ライブラリ組み込んでいきます。

[前の記事](http://qiita.com/maki02/items/b965331129a959588ce7) で利用した RedBearNano_NeoPixels_Example の中から、次の2つのソースを BLE_GATT_Example にコピーします。 

- neopixel.cpp
- neopixel.h

そして、main.cpp で neopixel.h を読み込み、m_strip をグローバル変数として宣言しておきます。

```cpp:main.cpp
#include "neopixel.h"
neopixel_strip_t m_strip;
```

そして、main 関数の中で、NeoPixel の初期化コードを追加します。

```cpp:main()
    uint8_t dig_pin_num = P0_15;
    uint8_t leds_per_strip = 8;
    // (中略)
    neopixel_init(&m_strip, dig_pin_num, leds_per_strip);
    neopixel_clear(&m_strip);
```

なお、NeoPixel への制御信号を出力するピンを P0_15 に変更しています。

## GATT 通信に応じた LED の表示内容の変更を追加

GATT の writeCharacteristics への書き込みがあった際に呼び出される writeCharCallback 関数に手を加えていきます。

サンプルコードで BLE Nano 上の LED on/off しているコードを探します。

```cpp:writeCharCallback()
        if(params->len == 1) {
            led = params->data[0];
            (params->data[0] == 0x00) ? printf("led on\n\r") : printf("led off\n\r"); // print led toggle
        }
```

ここに、NeoPixel のLED を制御するコードを追加します。

```cpp:writeCharCallback()
    uint8_t error;
    uint8_t led_to_enable = 1;
    uint8_t red = 255;
    uint8_t green = 0;
    uint8_t blue = 159;
    // (中略)
        if(params->len == 1) {
            led = params->data[0];

            if (params->data[0] == 0x00) {
                printf("led on\n\r");
                error = neopixel_set_color(&m_strip, led_to_enable, red, green, blue);
            } else {
                printf("led off\n\r");
                error = neopixel_set_color(&m_strip, led_to_enable, 0, 0, 0);
            }
        }
```

組み込んだ NeoPixel のライブラリでは、LED を ON にするには、neopixel_set_color_and_show を使います。
ただし、BLE スタックと同時に使う場合には、neopixel_set_color と neopixel_show に分けるように注意書きがあります。
(https://github.com/lavallc/nrf51-neopixel/blob/master/neopixel.c)

そこで、GATT通信受信時の callback 関数では、neopixel_set_color で色を指定します。
そして、無線非 active 時に、NeoPixel に制御信号を送ります([後述](#ble-radio-notification-%E3%81%AE%E8%A8%AD%E5%AE%9A))。

ここでは、"00" を受信した場合は、led_to_enable(=1)番目のLEDにRGB(255,0,159)の色を表示するように値をセットします。
また、"00"以外の場合は、RGB(0,0,0)の値ををセットします。

## BLE radio notification の設定

次に、無線が非 active 時に、NeoPixel に制御信号を送る部分を作成していきます。

```cpp:main.cpp
#include "ble_radio_notification.h"

void radio_callback_handler(bool radio_active)
{
    if (radio_active == false)
    {
        neopixel_show(&m_strip);
    }
}
```
```cpp:main()
    // (中略)
    ble.init(bleInitComplete);
    ble_radio_notification_init(NRF_APP_PRIORITY_LOW,
                                  NRF_RADIO_NOTIFICATION_DISTANCE_800US,
                                  radio_callback_handler);
```

ble_radio_notification_init で、無線が active / 非active に切り替わる際の event handler を登録します。
1番目の引数は割込みの優先順位、2番目は event 発生までの時間差になるようです。
3番目の引数で handler として radio_callback_handler を指定します。

そして、radio_callback_handler の中で、無線が非active のときに neopixel_show を呼び出します。
これで、NeoPixel に制御信号が送られます。

# 動作を確認する

LED の制御ピンを P0_8 から P0_15 に変更したので、LED への配線を変更しています。

![P6300016.JPG](https://qiita-image-store.s3.amazonaws.com/0/129898/70d861a6-44a6-f54b-4c78-af66032be663.jpeg)


[前記事](http://qiita.com/maki02/items/a3254a9a24bd6911df78) のように Android のアプリ(nRF Master Control Panel) を使って、"00" の値を書き込むと、無事点灯しました。

![P6300014.JPG](https://qiita-image-store.s3.amazonaws.com/0/129898/552dd386-1654-133c-ff4f-e1b59197a535.jpeg)

なお、制御ピンですが、P0_8 のままでは動作しませんでした。
原因はちゃんと追求していませんが、P0_8 は STDIO や SPI の制御ピンでもあるので、その影響かもしれません。

(BLE Nano のピンレイアウトは http://redbearlab.com/blenano/ にあります)

とりあえず、空いている P0_15 に変更してみると無事動作しました。
ただ、この P0_15 ピンは横に出るので配線が難しくなります。
そこで、P0_5 ピンに変更してみたところ、P0_5 でも無事動きました。

![P6300023.JPG](https://qiita-image-store.s3.amazonaws.com/0/129898/ff028359-7e7d-ef61-29e5-54ca5c2b57a2.jpeg)

(2016年7月21日 修正 mt08 さん、コメントありがとうございました!)