nRF52840を使ったLowPowerデバイスの開発 その1

nRF52840を使ったBLEデバイスの開発記録です。CR2032コイン電池を使って数週間動くデバイスの作成を行います。体温センサを使い常時装着型の体温計を開発します。ソフトウェアの開発にはArduino IDEを使います。

nRF52840はNordic社のBLEチップです。これ単体では技適をとっていませんが、BLEアンテナを組み込んだモジュールMDBT50Qが技適を取得しています。さらにこれを搭載したAdafruits nRF52840 ItsyBitsyがあります。

nRF52840の情報はこちら
https://www.nordicsemi.com/Products/Low-power-short-range-wireless/nRF52840/GetStarted?lang=ja-JP

MDBT50Qの情報はこちら
https://www.raytac.com/product/ins.php?index_id=24
https://www.switch-science.com/catalog/5530/
https://www.switch-science.com/catalog/5529/

Adafruits nRF52840 ItsyBitsyの情報はこちら
https://www.adafruit.com/product/4481
https://learn.adafruit.com/adafruit-itsybitsy-nrf52840-express
https://github.com/adafruit/Adafruit-ItsyBitsy-nRF52840-Express-PCB

Arduino IDEの環境を作る

Arduino IDEでnRF52840の開発をできるようにするためにセットアップを行う必要があります。そんなに面倒ではありません。

Aruduino→Prefarence…で追加ボードマネージャに
https://www.adafruit.com/package_adafruit_index.json
を追加しておきます。私は以下のURLも入れてますが、これはいらないかも?
https://sandeepmistry.github.io/arduino-nRF5/package_nRF5_boards_index.json

Arduino→ツール→ボードマネージャでAdafruit nRF52をインストールします。

以上で使えるようになると思いますが、詳しくは以下のサイトなどを参考にしてください。
https://qiita.com/Kosuke_Matsui/items/678489ad212aeeff8d92

構成

Adafruit nRF52840 ItsyBitsyに体温センサーMAX30205を接続して測定値を1分間隔でBLEを使いアドバタイズします。データはアドバタイズデータのコンテナに収納します。受信はESP32やスマートフォンで行います。こちらも専用のソフトを作る必要があります(こちらは別記事で紹介する予定です)。

MAX30205についてはこちら
https://www.maximintegrated.com/en/products/sensors/MAX30205.html
ブレークアウトボードは以下から購入できます。
https://www.tindie.com/products/closedcube/max30205-01c-human-body-temperature-sensor/
Arduinoのライブラリは
https://github.com/closedcube/ClosedCube_MAX30205_Arduino

MAX30205のブレークアウトボードから以下のようにItsyBitsyに配線します。

MAX30205 - ItsyBitsy
GND - GND
VDD - 10
SCL - SDA
SDA - SDA

VDDをポートの10番に繋いでいるのは測定時だけセンサーの電源を入れて消費電力を抑えるためです。

コイン電池CR2032のプラスから3Vへ、マイナスからGNDへ接続しています。

Arduinoのスケッチ

#include <bluefruit.h>
#include "nrf_rtc.h"
#include "ClosedCube_MAX30205.h"

#define LED_BUILTIN 3

ClosedCube_MAX30205 max30205;
const int max30205Pin = 10;         //max30205の電源にするためのピン

BLEUart bleuart; // uart over ble

#define DEVICE_NAME "nRF52_bodyTemp"
#define DEVICE_NUMBER 1

void setup() {
  pinMode(max30205Pin, OUTPUT);
  pinMode(LED_BUILTIN, OUTPUT);

  digitalWrite(max30205Pin, LOW);
  
  delay(1000*60);//1min ~950uA
  startAdv();
}


void startAdv(void)
{
   float temp;
   int dataCount=0;
   
  //i2cの準備 測定
  digitalWrite(max30205Pin, HIGH);
  delay(100);
  max30205.begin(0x48);
  temp = max30205.readTemperature();

  digitalWrite(max30205Pin, LOW);

  // Config the peripheral connection with maximum bandwidth
  Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);

  Bluefruit.begin();
  Bluefruit.setTxPower(4);    // Check bluefruit.h for supported values
  Bluefruit.setName(DEVICE_NAME);

  // Advertising packet
  Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
  Bluefruit.Advertising.addTxPower();
  Bluefruit.Advertising.addService(bleuart);// Include bleuart 128-bit uuid

  Bluefruit.ScanResponse.addName();

  uint8_t msd_payload[5]; //送信データサイズ 5バイト

  int tempInt = temp * 100;//温度を100倍して整数に


  msd_payload[0] = 0xf3;                        // manufacturer ID low byte  0
  msd_payload[1] = (char)dataCount;
  msd_payload[2] = (char)DEVICE_NUMBER;         // デバイス番号 2
  msd_payload[3] = (char)(tempInt & 0xff);         // 温度の下位バイト 3
  msd_payload[4] = (char)((tempInt >> 8) & 0xff);  // 温度の上位バイト 4

  Bluefruit.Advertising.addData(BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA, msd_payload, sizeof(msd_payload));

  Bluefruit.Advertising.restartOnDisconnect(true);
  Bluefruit.Advertising.setInterval(32, 244);    // in unit of 0.625 ms
  Bluefruit.Advertising.setFastTimeout(3);      // number of seconds in fast mode
  Bluefruit.Advertising.start(2);                // 0 = Don't stop advertising after n seconds 5秒間BLEの信号出して止まる
}


void loop() {
  digitalWrite(LED_BUILTIN, HIGH);
  delay(500);
  digitalWrite(LED_BUILTIN, LOW);


  NVIC_SystemReset();
}

消費電力を抑えるためにsetupの中で60秒間delayしています。ここがsleepになります。
その後測定と送信をしてNVIC_SystemReset();でリセットをかけます。これで再起動してsetupから処理を繰り返すという動作になります。
BLEの機能を使うためにはBluefruit.begin();が必要なのですが、これが入るとその後の消費電力が跳ね上がります。そのため必要な部分だけでこの処理をして、それ以外は低電力にするためにこのようになっています。本当は測定してその後sleepしたかったのですが、それだとsleep時の電流が下がらなかったのでこのようになってます。

消費電流の測定

PowerProfiler Kit IIを使いこのデバイスの消費電流を測定しました。

ピークは測定と送信を行なっている部分。それ以外はdelayでsleepしている部分です。delayしている部分は平均で742.84μA。
1分間合計で見ると平均電流が882.34μA。Chargeは52.94mCとなります。
CR2032の電池容量は220mAh。これをクーロンに換算すると792C
これを52.94mCで割って14,960分=249時間。10日間程度は動く計算になります。

nRF52840のdeep Sleepは数μAの消費電流でさらに下げることも可能なのですが、それはまた後ほど。