2015年11月17日火曜日

nrf51822 で Real Time Clock を使って起動時間を取得する方法

概要

nrf51822 上で起動時間を取得するために RTC (RealTimeClock) の仕組みを使ってみました
RTC の値はデバイスの電源の ON/OFF でリセットされる値になります

環境

  • Windows7 64bit
  • nRF51822
  • nRF51 DK
  • nRF51 SDK 9.0.0

実装方法

nRF51 DK に含まれる App Timer (以下タイマー) という機能を使って実現します

nRF51 SDK に含まれているサンプルを見るといろいろなサンプルでこのタイマーを使っているので基本はそれをベースにすれば OK です
今回はバッテリーレベル用のタイマーを定義して、それを例に
流れを説明していきます

初期化

まず、タイマーを使うために APP_TIMER_INIT というマクロをコールする必要があります
サンプルではだいたいこんな感じで実装されていると思います

APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_MAX_TIMERS, APP_TIMER_OP_QUEUE_SIZE, false);

基本はこれで問題ないです

タイマーの生成

次にタイマーを生成します
生成するには app_timer_create をコールします

uint32_t err_code;
err_code = app_timer_create(&m_battery_timer_id, APP_TIMER_MODE_REPEATED, battery_level_meas_timeout_handler);
APP_ERROR_CHECK(err_code);
static app_timer_id_t m_battery_timer_id;

app_timer_id_t は typedef されている型で実体は uint32_t になります
この ID に対するタイマーを生成していることになります
また、 battery_level_meas_timeout_handler ですがこれは関数になっており、タイマーがタイムアウトしたときにコールされる関数を指定できます
この辺もサンプルを見ると流れが把握できると思いますが、この関数内でバッテリーレベルの再取得を実施し Characteristics の value の更新を行っています

タイマーが生成できたらタイマーをスタートします

タイマーを開始する

タイマーを開始するには app_timer_start をコールします

uint32_t err_code;
err_code = app_timer_start(m_battery_timer_id, BATTERY_LEVEL_MEAS_INTERVAL, NULL);
APP_ERROR_CHECK(err_code);

これをコールしたタイミングから RTC によるカウントが開始されます

現在のカウントを取得する

タイマーを開始したら、現在のカウントを取得してみます
現在のカウントを取得するには app_timer_cnt_get をコールします

uint32_t p_ticks;
app_timer_cnt_get(&p_ticks);
printf("%d \r\n", p_ticks);

こんな感じでカウントしている値を取得できます

ここでちょっとはまったのは app_timer_cnt_get の返り値を参照してもずっと 0 でした
リファレンスを見たのですが、この関数の返り値は正常に取得できたかのフラグを return しているだけなので常に 0 が返っていました
関数側では、受け取った引数のポインタに対して書き込みを行っているので、引数として渡した変数を参照する必要がありました

で実際にこの値を定期的に出力してみたのですが、値を見ると 1, 2, 3, … のような秒数を刻む値ではなく 3256, 6785, 125678, … のようにガンガン値が増えていました
ちょっとこの値に説明します

カウント値について

以下もしかすると、間違いがあるかもしれません

この値について目視でどの程度増えているのか計測してみたのですが、だいたい 30 秒で 1,000,000 カウント増えている感じでした
なので 1 秒間で約 33,000 ほど増えていることになります

何かそれっぽい値を定義している箇所がないか調べてみたのですが、APP_TIMER_CLOCK_FREQ というマクロが定義されておりこの値が 32768 になっていました
おそらくですが 1 秒間にこの APP_TIMER_CLOCK_FREQ の値だけ増加しており、app_timer_cnt_get ではそれが取得できているのだと思います
なので、時間を取得したいのであれば、取得した値を APP_TIMER_CLOCK_FREQ で割り算すればそれっぽい起動時間が取得できると思います

また、値の最大値なのですが、約 16, 800,000 くらいになるとまた 0 にリセットされてカウントが始まりました
( 16, 800, 000 / 33,000 = 510 (sec) = 8 min 30 sec )
なので何回リセットされたかどうかも管理しないとダメそうな感じです
最大値を伸ばす方法とリセットされた回数を取得できる方法があるかどうかは、すいません、調査しきれていません、、、

ちょっとこの辺が曖昧な記載なのは、そこまで深く調べていないので自信がないためです
間違いがや追加の情報あればご指摘いただけると助かります

最後に

とりあえず nrf51822 で起動時間っぽい値を取得できるようになりました
完全に使うためにはもう少し実装が必要そうですが、ベースとなる呼び出し方は理解できたと思います

10分くらいでリセットされるタイマーだとちょっと管理が大変なので、半日分くらいは管理できるようにしたいなと思っています

0 件のコメント:

コメントを投稿