とりあえず第1回としてみた。
https://www.bluetooth.org/ja-jp/Documents/Shenzhen%20Noridc_BLE%20sensor%20app.pdf
この資料がわかりやすかった。
bluetooth.orgって書いてあるから、本家でのプレゼンテーション資料とかかな?
- BLEのプロトコルスタック
- アプリケーションドライバ
この2つがメインかな、と今の感触として思っている。
とりあえず第1回としてみた。
https://www.bluetooth.org/ja-jp/Documents/Shenzhen%20Noridc_BLE%20sensor%20app.pdf
この資料がわかりやすかった。
bluetooth.orgって書いてあるから、本家でのプレゼンテーション資料とかかな?
この2つがメインかな、と今の感触として思っている。
nRF51822というチップが手元にある。
デバッガもあるし、開発環境もある。
さて、どこから手を付けようか?
nRF51 SDKという環境と、それに付随してS110というSoftDeviceなるBLEスタックを含んだファームウェアというかミドルウェアというかがある。
私だってなるべく楽をしたいし、安全に使えるものであれば使いたい。
まず、SoftDeviceにはいくつかあるが、nRF51822には「S110」と「S120」が使える。
S110はBLEのperipheral用、S120はBLEのcentral用だ。
BLE_STACK_SUPPORT_REQDって定義を付けてビルドすると、peripheralとして使えるらしい(SoftDevice Handler Library)。
HPの内容をそのまま抜粋。
S110 SoftDevice
The S110 SoftDevice is a Bluetooth® low energy (BLE) Peripheral/Broadcaster protocol stack solution.
It integrates a Bluetooth low energy controller and host, and provides a full and flexible API for building Bluetooth low energy System on Chip (SoC) solutions.
Key Features
nRF51 SDKを補完するものらしい。
ただ、SoftDeviceを使うようにしておくと、いろいろと面倒なことをせずに済む、という記事もあった。
うーん、もう少し絞りたい。
S110について知ればいいのかな?
比較的、小さいものを作ることが多い。
私がハードを作れないので、そういうのは仕事でしかやれないんだけど、だいたい「省電力」が課題になる。
まあ、小さい→電池で動かす→長持ちさせねば!となるのは、当然な流れだ。
基本的な手段は、こんなところ。
他にもあるけど、まあこんなところで。
マイコンの資料を見ると、消費電流が出ている。
この機能を使うとこのくらい、みたいなことが書いてあるので、じゃあ使うのをやめよう、とか、使う時間を短くしよう、とか、そういうことを考えるのだ。
では、nRF51822はどうかというと・・・ああっ!
スペックシートも、リファレンスマニュアルも、ユーザ登録が必要じゃないか!
ええい、もどかしい。。。
http://www.nordicsemi.com/eng/Products/Bluetooth-R-low-energy/nRF51822
ここにおおざっぱな消費電流が出ている。
送受信がmAオーダーなのに対して、待機中はμAオーダーだ。
これだけでも、送受信する時間を短くすれば消費電流が抑えられることがわかる。
とはいえ、BLEなんだから送受信しないと始まらない。
あるいは、Beacon端末であれば送信しっぱなしでいいのかもしれない。
送信しっぱなし、とはいえ、送信間隔が長くなればなるほど、消費電流は抑えられる。
じゃあ、その間隔を製品の性格に合わせて最大にしたとしよう。
次に待つのは、送信するまでの間をどうするか、だ。
本当に何もしなければ良いのなら、タイマを割込設定して、割込が発生するまで眠らせる、ということもできる。
でも、場合によっては間に受信をしないといけないかもしれない。
その時間がタイマで良いならば、同じようにタイマ割込にしておけば良い。
そうではなくユーザ操作が絡むとかだと、じゃあどうしよう。
いやいや、実は受信が不定期に来るから受信もやらないと、とか・・・。
そういう製品の仕様を考えながら省電力のことをやると、かなり電力を抑えることができる。
できるけど、汎用的なやり方ではなく、かなりOSみたいなことになってくる。
省電力を中心とした仕様設計や実装になる、という感じだろうか。
そういう細々したことをやってるから日本は・・・っていわれるのかもなあ、と思わなくもない。
そんな暇があったら、新しいサービスとかに力を入れろよ、みたいな。
でも、誰かがやらんといかんのよねぇ、とも思う私で、そういう方面が好きなのであった。
では、BVMCN5102-BKにセンサーでも付けてみよう。
まずは付けて動かすだけだ。
うちにあるセンサーで動きがわかりやすいのは・・・FeliCa Plugか。
あれも、13.56MHzの搬送波を検出するセンサーと見なせなくもないだろう。
それっぽく書いてみたが、意味があるのはFeliCa Plugの/RFDETとP0.21につないだLEDだけ。
#include "nrf_gpio.h"static void set_gpio(void){//P0.21にLED接続。//HIGHで消灯。LOWで点灯。nrf_gpio_cfg_output(21);nrf_gpio_pin_write(21, 1);//P0.08 : /RFDETnrf_gpio_cfg_input(8, NRF_GPIO_PIN_PULLUP);}int main(void){set_gpio();while (true){nrf_gpio_pin_write(21, nrf_gpio_pin_read(8));}}
/RFDETを読み、GPIOに出力しているだけだ。
プルアップにしているので、LEDは1出力で消灯、0出力で点灯になる。
/RFDETも負論理なので、未検出時は1、検出時は0になる。
PaSoRiでFeliCaランチャーを立ち上げておくと定期的にポーリングするので、そのタイミングでLED点滅することを確認。
おめでとう、私!
うん、動作に意味はないんだけど、gccのテンプレートからプロジェクトを作ってビルドして動いた、という作業としてはちょうど良かった。
LEDにプルアップ抵抗を付けてたんだけど、大きすぎるのか点灯せず、結局直づけになった。
まずい気はするんだけど、まあいいや。
これがPlugじゃなくてLinkの方だったら、読んだIDmを転送、なんてのもできるんだけどね。
nRF51のブロック図を見ると、SPIやらI2C互換やらのシリアル通信ブロックがあるのだけど、ピンアサインを見てもGPIOくらいしか出てない。
どうなっとるんじゃ?
nRF51のリファレンスマニュアル「9. Peripheral interface」を見ると、APBとAHBをtask/event/interruptレジスタで触ることができるって書いてある。
機能ごとに0x1000の固定ブロック=1024レジスタが割り当てられていて、それを使ってAPBにアクセスするようだ。
このブロックがID0~31ある。これをPeripheral IDと呼んでいる。
メモリマップではAPB peripheralsって書いてあるところだな。
Table 3にPeripheral instantiationという表があり、IDと機能の対応が見て取れる。
Tasksは、機能に働きかけるトリガ。「開始せよ」みたいな。
Eventsは、機能の変化通知。「状態が変わった」みたいな。
Shortcutsは、taskとeventの接続。接続・・・? eventが発生するとtaskが自動的にたたかれるらしい。
Interruptsは、CPU例外処理の、いわゆる割込。
え、これで説明終わり?
どうやってGPIOの割り当てを変更したりするの?
しょうがない、SPIの説明を読んでみるか。
ふむふむ、PSELSCK / PSELMOSI / PSELMISOのレジスタがあり、それにピン番号を書き込むようだ。
動的に変更できるってことですか。。。まさにGeneral Purpose。
しかし、ソフト的に変更できるっていうことは、多少の遅延が発生するのかな?
まあ私が作るようなソフトだったら影響はないだろうけど。
サンプルソースも見てみた。
SDKにレジスタを初期化するソースまで入っているので、全部書かなくてもよいみたいだ。
まあ、自分で書いた方がサイズは小さくなるかもしれんがね。
ちょっと嫌なのは、引数で初期値を渡すのではなく、"spi_master_config.h"というファイルに決められたマクロでピン番号などを書いておかないといかんところか。
まあ、メモリも少ないことだし、引数渡しなんかするよりは直接埋め込んだ方がよいってことなのかな。
まだnRF51822自体がよくわかってないので、サンプルを焼くだけだ。
まず、Nordicのユーザ登録をしよう。
http://www.nordicsemi.com/eng/Products/Bluetooth-R-low-energy/nRF51822
Registerをクリックした先で、いくつか入力して登録。
メールが来たりして登録が完了したら、ログイン。
左側に「MY KEYS」があるので、クリック。
ここで、BVMCN5102-BKを購入したときに入っていた紙に書いてあるプロダクトキーを打ち込んでADD。
そうすることで、ダウンロード保護されていた開発環境などがダウンロードできるようになる。
今の私は、これがダウンロードできるようになった(スペックシートなどは保護されてない)。
とりあえず、全部ダウンロードしてから考えることにした。
nANはアプリケーションノートのPDF。RMはリファレンスマニュアル。PSはスペックシート。
nRF-MCPはMaster Control Panelなんだけど、いるかどうかわからん。
この中でインストールがいると思うのは、これらか。
SDKは統合開発環境とかじゃなくて、ヘッダやサンプルソースのような、純粋の開発環境。
nRFgo Studioは、焼かれているSoftDeviceの確認や、焼き換えに使う。
次は、デバッガの準備。
SEGGER社のJ-Link LITE CortexMが付属しているので、そのドライバをインストールする。
上記サイトに行くと、左側にDownloadsがあるので、クリック。
Productでコンボボックスから「J-Link LITE CortexM」を選択。
ドライバのダウンロードっぽいリンクが出てくるので、クリック。
そうすると、J-Link downloadsに飛ぶ。画像はLITEのじゃないけど、問題なさそう(J-Linkって黄色かと思ってた)。
今回はWindows環境なので、Windows用をダウンロード。
そうすると、シリアル番号の入力を求められる。
シリアル番号は、J-Linkのチップの上に書いてある。下画像の赤いところだ。
打ち込むとダウンロードできるので、ダウンロードして展開してインストール。
なお、このシリアル番号は接続の時にも使う。
BVMCN5102とJ-Link LITEはこんな接続になる。
ピンの穴が埋まっているのだが、逆にすると差し込めてしまうので注意だ。
ケーブルに油性マジックで3本の線が引かれている方がJ-Link側だと思う。
が、もう少し待とう。
まだクロスコンパイラが入っていないのだ。
今回は、gcc + eclipseを使う。
通常のARM開発と一緒のようなので、使い慣れた環境があるならそれでもよさそうだ。
私はあまり考えたくなかったので、NordicのアプリケーションノートnAN29に従うことにした。
「nRF51 Development with GCC and Eclipse」がそのタイトルだ。
では、順番にやっていこう。
と行きたいところだが、サンプルそのままではたぶん動作しない。
理由は前の方のブログ記事を見てほしいが、BVMCN5102は素のままでは32Kの外部クロックがない。
で、サンプルは外部がある前提で書かれている。
内蔵32Kがあるんだから、そっち前提にしてほしいような・・・。
ぶつぶつ言っていても仕方ないので、サンプルを修正する。
その前に、STATIC_ASSERTの解決をしよう。
Include/app_common/app_util.hにSTATIC_ASSERTマクロの定義があるのだが、gccのバージョンが新しいとエラー扱いになってしまうのだ。
https://devzone.nordicsemi.com/question/4192/static_assert-and-gcc-instead-of-keil/
#define STATIC_ASSERT(EXPR) typedef char static_assert_failed[(EXPR) ? 1 : -1] __attribute__((unused))
そして本題の32Kクロック。
main.cのble_stack_init()を書き換え。
元:
SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, false);
変更後:
SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_RC_250_PPM_4000MS_CALIBRATION, false);
4000MSじゃなくてもいいけど、とにかくRC_250_PPMを選ぶ。
これをやっても動かないなら、SoftDeviceのバージョン違いを疑ってnRFgo Studioを使って焼き直そう。
動くと、こんな感じのパケットが吐き出される。
Amazonで購入したBVMCN5102-BK KIT PLUSには、以下が付属していた。
これは半田付け後の写真だ。
付けるのは、ムカデみたいなピンと、DIP-SWだけなので簡単。
ただ、DIP-SWのしたにはジャンパピンが半田付けできそうなところもあり、HPの写真ではなぜかそこも半田で埋まっていたので、実は何かするべきなのでは・・・と悩んだ。
テスターで計測し、SWだけで問題なかったので、それは忘れることにした。
SEGGERと接続すると、こんな感じ。
MicroUSBは、PCとの接続はないので、ACアダプタと接続することにした。
上がSEGGERというか、J-Link LITE CortexM。
ソフト的な環境は、ドキュメント通りだ。
nRFgo Studioは、最初にインストールすべきものだ・・・私の反省から。
組み込み技術者たるもの、すべてを疑ってかかるべきなのだ。
ああ、刑事の寂しい性だとは思いつつもな。
eclipse + gccでのことについては、また明日以降。
サンプルソースが動いたので、これからちゃんと見ていくことにしよう。
まずは、自分が使おうとしている環境がどういうものか、まとめておく。
BLE開発キット with J-Link segger (amazon)
開発環境を作るのに手間取った。
記憶が薄れかかっているので、メモ程度に。
ここで、何をインストールすれば良いかだが・・・とりあえず全部入れてみようって感じでやってしまった。
思うに、以下があればよいと思う。
nRF51 SDKでは、ヘッダとソースとサンプルソースがインストールされる。
このヘッダの中に、S110-SD(SoftDevice)に対応したインクルードファイルがあるのだが、おそらく最新の安定版が入っているようだ。
使うnRF51822にどういうSoftDeviceが入っているかは、nRFgo Studioで確認できる。
SDKと一致してなかったら、S110-SDに入っているインクルードファイルを入れ替えるか、同じく入っているHEXファイルを焼いてしまうかだろう。
前回の私は、焼きかえることで対応した。
nRFgo Studioのインストール時に、もしかしたらJ-Linkのドライバもインストールされたかも。
私はnRFgo Studioをインストールしてなかったので、自分でダウンロードした。
nRF51822にはCortex-M0が入っているので、開発環境はARMのものが使えそうだ。
私は、Nordicのドキュメントを見ながら、gcc+eclipse環境を作った。
gccはドキュメントに書いてあるバージョンじゃなくて最新のを使ったから、それに関する変更は行ったけど、それくらいでほぼPDFそのままできた気がする。
そこに書いてあった、hrsサンプルがようやく動いたのが、昨日だ。
次は、hrsサンプルをいじくって、自分で動かしてみるというところかな。
BLEよりも、まずはボードを動かしてみるというのが先だ。
コメントをいただき、やはり内蔵クロックがうまく出てないのじゃないかという気になってきた。
では、まずなんでマクロが終わらないかを見ていこう。
SOFTDEVICE_HANDLER_INITで止まっている理由を見るのだ。
この範囲をぐるぐる回っていた。
- r1 : 0x4000_0100
- r3 : 0x0000_0000
イベント待ち
0x4000_0104の値をr3にロード
r3が0かどうか比較
0だったら、戻る
0x4000_0104は、LFCLKSTARTEDだ。
それが0以外、つまり開始したらループを抜ける。
値が0なので、ぐるぐる回っている。
でもね・・・
LFCLKSTATのSTATEはRUNNINGなのよねぇ。
うーん・・・アセンブラレベルで追っていくか・・・。
あ、
ぐるぐる回る前に、32Kが外部クロックに指定されてる!
でも、sd_softdevice_enable()呼ぶまでは設定されてなかったし、sd_softdevice_enable()から抜けてないとなると、この中で設定されたことになる。
第Ⅰ引数は10進数で13。enumの順番とは一致している。
うーん・・・・?
今回私が使っているのは、SoftDevice6.0.0が焼かれている、と書いてあった。
6.0.0のenumは、こんな並び。
/**@brief Possible lfclk oscillator sources. */
enum NRF_CLOCK_LFCLKSRCS
{
NRF_CLOCK_LFCLKSRC_SYNTH_250_PPM, /**< LFCLK Synthesized from HFCLK. */
NRF_CLOCK_LFCLKSRC_XTAL_500_PPM, /**< LFCLK crystal oscillator 500 PPM accuracy. */
NRF_CLOCK_LFCLKSRC_XTAL_250_PPM, /**< LFCLK crystal oscillator 250 PPM accuracy. */
NRF_CLOCK_LFCLKSRC_XTAL_150_PPM, /**< LFCLK crystal oscillator 150 PPM accuracy. */
NRF_CLOCK_LFCLKSRC_XTAL_100_PPM, /**< LFCLK crystal oscillator 100 PPM accuracy. */
NRF_CLOCK_LFCLKSRC_XTAL_75_PPM, /**< LFCLK crystal oscillator 75 PPM accuracy. */
NRF_CLOCK_LFCLKSRC_XTAL_50_PPM, /**< LFCLK crystal oscillator 50 PPM accuracy. */
NRF_CLOCK_LFCLKSRC_XTAL_30_PPM, /**< LFCLK crystal oscillator 30 PPM accuracy. */
NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, /**< LFCLK crystal oscillator 20 PPM accuracy. */
NRF_CLOCK_LFCLKSRC_RC_250_PPM_250MS_CALIBRATION, /**< LFCLK RC oscillator, 250ms calibration interval.*/
NRF_CLOCK_LFCLKSRC_RC_250_PPM_500MS_CALIBRATION, /**< LFCLK RC oscillator, 500ms calibration interval.*/
NRF_CLOCK_LFCLKSRC_RC_250_PPM_1000MS_CALIBRATION, /**< LFCLK RC oscillator, 1000ms calibration interval.*/
NRF_CLOCK_LFCLKSRC_RC_250_PPM_2000MS_CALIBRATION, /**< LFCLK RC oscillator, 2000ms calibration interval.*/
NRF_CLOCK_LFCLKSRC_RC_250_PPM_4000MS_CALIBRATION, /**< LFCLK RC oscillator, 4000ms calibration interval.*/
NRF_CLOCK_LFCLKSRC_RC_250_PPM_8000MS_CALIBRATION, /**< LFCLK RC oscillator, 8000ms calibration interval.*/
};
その1つ前、5.2.1は、こんな並び。
/**@brief Possible lfclk oscillator sources. */
enum NRF_CLOCK_LFCLKSRCS
{
NRF_CLOCK_LFCLKSRC_RC_250_PPM_500MS_CALIBRATION, /**< LFCLK RC oscillator, 500ms calibration interval.*/
NRF_CLOCK_LFCLKSRC_RC_250_PPM_1000MS_CALIBRATION, /**< LFCLK RC oscillator, 1000ms calibration interval.*/
NRF_CLOCK_LFCLKSRC_RC_250_PPM_2000MS_CALIBRATION, /**< LFCLK RC oscillator, 2000ms calibration interval.*/
NRF_CLOCK_LFCLKSRC_RC_250_PPM_4000MS_CALIBRATION, /**< LFCLK RC oscillator, 4000ms calibration interval.*/
NRF_CLOCK_LFCLKSRC_RC_250_PPM_8000MS_CALIBRATION, /**< LFCLK RC oscillator, 8000ms calibration interval.*/
NRF_CLOCK_LFCLKSRC_SYNTH_250_PPM, /**< LFCLK Synthesized from HFCLK. */
NRF_CLOCK_LFCLKSRC_XTAL_500_PPM, /**< LFCLK crystal oscillator 500 PPM accuracy. */
NRF_CLOCK_LFCLKSRC_XTAL_250_PPM, /**< LFCLK crystal oscillator 250 PPM accuracy. */
NRF_CLOCK_LFCLKSRC_XTAL_150_PPM, /**< LFCLK crystal oscillator 150 PPM accuracy. */
NRF_CLOCK_LFCLKSRC_XTAL_100_PPM, /**< LFCLK crystal oscillator 100 PPM accuracy. */
NRF_CLOCK_LFCLKSRC_XTAL_75_PPM, /**< LFCLK crystal oscillator 75 PPM accuracy. */
NRF_CLOCK_LFCLKSRC_XTAL_50_PPM, /**< LFCLK crystal oscillator 50 PPM accuracy. */
NRF_CLOCK_LFCLKSRC_XTAL_30_PPM, /**< LFCLK crystal oscillator 30 PPM accuracy. */
NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, /**< LFCLK crystal oscillator 20 PPM accuracy. */
};
赤文字は、13番目。
もしかして・・・6.0.0じゃなくて、5.2.1が焼かれているのでは?
nRFgo Studioをインストールしてみてみると・・・当たり!
バージョン違いだったー--
そりゃ動かんですな。
細かいことはわからんけど、サンプルのHeartRateも動いて、以前買ったスニファにも出てきた。
ふいー、ようやく地面に降りたった、というところだ。