LoginSignup
9
8

More than 3 years have passed since last update.

BLEマイコンnRF52832覚書

Last updated at Posted at 2020-03-07

はじめに

Nordic社のnRF52シリーズを使うことになり、いろいろと調べることが多いのでその覚書として記載していきます。nRF5シリーズではnRF5SDKが用意されており、その中に豊富なサンプルコードがあり、これらを組み合わせることで目的のコードを作っていくのが、早道になります。
自分は組込みソフト開発の経験が浅いので、まずは環境構築やサンプルコードを読み解いて分かったことをつらつらと書いていき、勉強に役立てようと思います。

ハードウェア

これはNordicの純正品でnRF52832を搭載しています。残念ながら技適未取得のため、BLE部分を使用する場合には電波暗室などで作業をする必要がありますが、単にGPIOやI2Cなどのペリフェラル機能を試す分には、問題ないはずです。また、口述しますが書き込み機としても使えますので、一台あると他のnRF5シリーズへのプログラム書き込みができ、便利です。

これはAdafruit社製の評価ボードです。Raytac社が技適を取得したアンテナがパッケージになったモジュールを搭載しており、電波を出しても問題ありません。
また、Arduino環境で動作することができる点も魅力的ですが、今回はnRFSDKの環境での開発を行います。

 

環境構築

Armマイコン向けの開発環境であるSegger Embedded Studio(SES)を使います。
Keilなどいくつか開発環境はあるのですが、SESに関してはNordic社製のモジュールを使っている限りライセンス制限なく使うことができます。(Keilではビルド後のバイナリサイズに制限があります)

手順 

基本的には公式のドキュメントにすべて記載されています。
今回見るべきは、nRF52 Get Startedです。こちらにSeggerで始める場合の手順が記載されています
1. Segger Embedded studioをインストールします
2. nRF52SDKをダウンロードします(インストールは必要ありません)
3. SESを起動し、Nordicのデバイスを使っていることを選択し、mailアドレスの登録からライセンスキーが発行されます
4. SDKのディレクトリからsesのprojectを開きます

まずはLチカする

プログラムの場所

C直下にSDKを配置している場合、下記のディレクトリにLチカ用のプログラムが入っています。
C:\nRF5SDK160098a08e2\examples\peripheral\blinky\pca10040\s132\ses\blinky_pca10040_s132.emProject
nRFシリーズにはソフトデバイスというものがあり、nRF52832ではs132になります。
別のモジュールを使う場合には、適宜ソフトデバイスを変更してください

書き込み方

PCにUSBケーブルでDKを接続すると、JLINKという名前で認識されるはずです。
この状態でBuild -> Bulid and Runを押すとビルドと書き込みが実行され、Lチカが始まります。
※画像は、Lチカのサンプルではないですが、すべてのプロジェクトで共通です
image.png

DK以外のボードに書き込みをする場合

他のボードには、nRF52SDK経由で書き込みをすることができます。
DKから対象のデバイスに対してラインをつなぎます。GNDdetectとVTGを繋ぐことでDKは自分用のプログラムではないと判断し、接続されているほかデバイスにプログラムが書き込まれます。
詳しくは下記のリンクで丁寧に説明されているのでこちらをご覧ください

【配線早見表】

DK ターゲット
VTG VDD
GND Detect GND
SWDIO SWDIO
SWDCLK SWDCLK

ピンアサインメント

ピンの割り振りはかなり自由です。GPIOをI2C(Nordicではtwiと呼んでます)やSPIなどに割り当てることができます。回路の取り回しが楽になって良いですね。
ただし、SDKではピンのデフォルト設定があり、それを無効化しないと意図したアサインメントができないという罠がありますので、注意事項として後述します。

image.png

注意事項

前述のとおり、いくつかのピンではデフォルトの設定が入っているので、それを無効化する必要があります。下記に具体例を紹介します。

P0.06
  • UARTのTXとしてデフォルトの設定が入っています。これを解除しないと常にHiになってしまいます(6番でLチカしようとしたけどうまくいかなくて気が付いた)
  • sdk_config.h内に設定があるので、これを書き換えましょう!自分は25番にしましたが、何でもいいです。

image.png

★この事象に関連するdev zone

P0.09、P0.10

  • デフォルトではNRFCという短距離通信のアンテナとして設定されています。
  • system_nrf52.cの196行目です。デフォルトだとCONFIG_NFCT_PINS_AS_GPIOSが定義されていません。
  • system_nrf52.hでCONFIG_NFCT_PINS_AS_GPIOSを定義しましょう
system_nrf52.c
    /* Configure NFCT pins as GPIOs if NFCT is not to be used in your code. If CONFIG_NFCT_PINS_AS_GPIOS is not defined,
       two GPIOs (see Product Specification to see which ones) will be reserved for NFC and will not be available as
       normal GPIOs. */
    #if defined (CONFIG_NFCT_PINS_AS_GPIOS)
        if ((NRF_UICR->NFCPINS & UICR_NFCPINS_PROTECT_Msk) == (UICR_NFCPINS_PROTECT_NFC << UICR_NFCPINS_PROTECT_Pos)){
            NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
            while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
            NRF_UICR->NFCPINS &= ~UICR_NFCPINS_PROTECT_Msk;
            while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
            NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
            while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
            NVIC_SystemReset();
        }
    #endif
system_nrf52.h
#define CONFIG_NFCT_PINS_AS_GPIOS
  • もしくは、レジスタから直接設定する方法もあります。main.c下記のコマンドを加えましょう。
main.c
    NRF_UICR->NFCPINS = 0xFFFFFFFE;
  • DKを使っている場合は、さらなる壁があります。P0.09,P0.10はDK上で実はピンソケットに接続されていません。こちらをはんだ付けしましょう。R25,R26を外し、R27,R28をショートします。詳しくはこちら
  • 以上さらっと書きましたが、丸一日はまってしまいました。特にDKのはんだ付けの罠... 関連リンクを乱雑ですが貼っておきます。
ピンアサインメント関連リンク集

そのほかのサンプル

ここから先は自分の書きたいコードを構築するにあたって必要なサンプルを見ていきます。

NRF_LOG

nRFでログを吐く方法として、UART, NRF_LOG, NRF_SEGGER_RTTがあります。
UARTは重いので後者の2つを使うことが推奨されています。
NRF_LOGはどのサンプルでも最初にライブラリがインクルードされているので、これをUARTに経由してターミナルに表示させることでデバッグに役立ちます。

sdk_config.hの編集

このファイルの中に、SDKの様々な機能をenableにするか、disableにするかが記載されています
なので、こちらからNRF_LOGを有効にしてやればよいだけなのですが、ここで非常にはまりました。
自分はdev_zoneなどで言われている、sdk_config.hを直接編集するやり方を何度試してもうまくいきませんでした。ネットを漁ったところ同様の状況に陥っている方も他にいたようです。

結局のところ、CMSIS Configuration Wizardをインストールし、ここからsdk_config.hを編集することで解決しました。
下記の画面で、NRF_LOG_BACKEND_UART_ENABLEDとNRF_LOG_ENABLEDにチェックを付けます。

image.png

ターミナルを開く

Tools -> Terminal Emulator -> Connect COMXX から接続することができます。
image.png

注意点

下記のNRF_LOG_USES_TIMESTAMPにはチェックを入れないでください。
ここにチェックを入れることで、ログだけでなくすべてのプログラムが動作しないという現象が起こりました。
image.png

SAADC

アナログ値の読み出しのためのインターフェースです。
config内に何ビット分解能にするかの設定値があります。
値の読み取りはサンプルプログラムそのままですが、VCCと直結させて読むとVCCの値よりもやや小さい値が返ってくる?ので、現在調査中です。
VCCとアナログを直結して確かめたので、電流が流れて全体の電圧がドロップしているのかもしれません。

ビーコン

sample beaconのプログラムを改変していきます。
sd_ble_gap_adv_set_configure()でビーコンで送る内容を規定しています。パケットの内容に更新が必要な時もこの関数を呼び出せばよいです。
しかし、これをそのままメイン関数内で呼び出ししたところ、APP_ERROR_CHECKでfatal errorが発生してしまい、マイコンがリセットする現象に見舞われてしまいました。
ではどうするかというと、sd_ble_gap_adv_stop()を呼び出して一回アドバタイズにストップをかけます。
すなわち、パケット改変の順序としては、以下の順序を踏むことになります。(ここでも3日はまりました。)devzoneでは、sd_ble_gap_adv_set_configure()を呼び出せというのはすぐ出てくるのですがsd_ble_gap_adv_stop()を呼ばないといけないという記事には自分は当たりませんでした。

  • sd_ble_gap_adv_stop()
  • sd_ble_gap_adv_set_configure()
  • advertising_start(void)

ビーコンにセンサデータを乗っける

beaconのプログラムにtwiのプログラムを移植していき、twiで読んだデータを上記のパケット改変で送信データに乗せます。
基本はapp_beaconのプロジェクトに対してtwiのサンプルからの必要な部分をコピペしてくるスタンスでよいのですが、インスタンスをenableにし忘れるとコンパイルエラーが出ます。
対処法は、twi_instance 0を使う場合は、sdk_config.hを下記のように編集することです。

sdk_config.h
// <e> TWI0_ENABLED - Enable TWI0 instance
//==========================================================
#ifndef TWI0_ENABLED
#define TWI0_ENABLED 1
#endif

上記でコンパイルは通りますが、リンクで失敗しました。
nrf_drv_twi_tx, nrf_drv_twi_rxが定義されていないというエラーです。
dev_zoneを見に行くと、上記のENABLEを有効にしろという記述ばかりが引っかかりますが、今回の問題はそこではなく、単純にプロジェクトに上記の関数を定義しているファイルを配置しろということのようです。下記のファイルをnRF_Driversのディレクトリに配置しましょう。地味ですが、コードを統合していく際にはこういう問題に結構ひっかかりますね。

  • nrfx_twi.c
  • nrfx_twim.c
  • nrfx_drv_twi.c

具体的には、nRF_Driversのフォルダを右クリックし、add existing filesから配置することができます。
上記のファイルは、twiのサンプルコードのnRF_Driversには元々入っているので、右クリックからCopy Full Pathすればどこにあるかすぐに見つけられて便利です。
ファイルの追加方法はこちらの動画から

消費電力に関する注意

twiインスタンスを作成し、レジスタにアクセスする関数を呼び出すと消費電力が跳ね上がりました。常時300μA程度食います。
twiのイニシャライズだけでは起こりませんが、twi通信の関数を呼び出した瞬間にそうなります。
回避するには、都度twiをdisable、enableにするしかないです。
公式のエラッタにも記述がありますが、こちらのdevzoneが参考なりましたので参照してください。

DCDCを使って省電力化する

nRF52832 Product Specificationv1.4の78ページにLDOとDCDCについての記述があります。DCDCを使用したほうが省電力にできるようですが、LCフィルターのハードウェアを追加したときのみ可能です。
enableにするには、main.cで下記を追加します。

main.c
    // enable_dcdc
    NRF_POWER->DCDCEN = 1;

PPIとは

今回自分が使う予定がないので箇条書きですが、PPIという便利機能があるので書き残します。
* Programmable Peripheral Interconnectのこと。

The Programmable peripheral interconnect (PPI) enables peripherals to interact autonomously with each other using tasks and events independent of the CPU. The PPI allows precise synchronization between peripherals when real-time application constraints exist and eliminates the need for CPU activity to implement behavior which can be predefined using PPI.

  • その名の通り、あるペリフェラルの変化がトリガーとなり、他のペリフェラルのイベントが駆動されます
  • 例えば、あるピンが変化したらLEDがついたり、消えたりする機能が実装できるものです。
  • CPUとは独立に制御するためnon-blockingになるのが利点と思われます。i2cのDMAのペリフェラルバージョンのような理解ですかね。?
  • 1つのイベントで複数のタスクをドリブンできるとのこと
  • PPI公式リンク
  • タスクとイベントの対応について

GPIOによるイベント生成

ペリフェラルとセントラル

[参考リンク]

9
8
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
8