micro:bit (V2) のデータ ロガーで、その性能（書き込み速度とデータ容量）を確認しました

# micro:bit (V2) の データ ロガー

micro:bit (V2) 向け拡張機能として、データ ロガー（Data Logger）が追加されました。

https://microbit.org/get-started/user-guide/data-logging/

[データ ロガー FAQ](https://support.microbit.org/support/solutions/articles/19000129031-data-logging-faq) によると、最後の**「What is the maximum log size?」**で次のように説明されています。

> たとえば、100msec毎とした場合、1列のデータで最大11,000行、2列のデータで最大6,000行をログ出力できます。

100msec間隔でのログ出力が可能であり、３列のデータであれば、4,000行程度のログ出力が可能なようです。

そこで、今回、確認プログラムを作成し、実際の性能（書き込み速度とデータ容量）を確認しました。今後、加速度センサーのx,y,zを記録しようと思いますので、列(columns)を３列としました。

# 拡張ブロック編

[拡張機能 `datalogger`](https://microbit.org/get-started/user-guide/data-logging/) のブロックで確認プログラムを作成し、計測します。

## 方法

列(columns)を"a", "b", "c"の3列（3項目）とし、それぞれの値は、固定値 `1234`, `5678`, `9012` を繰り返し出力しました。

|#|項目|内容|備考|
|---|---|---|---|
|1|シリアル通信出力|なし||
|2|タイムスタンプ出力|あり|ミリ秒単位|
|3|列(columns)|"a", "b", "c"|||
|4|値|a:1234, b:5678, c:9012|固定値|

使用したソースコード(JavaScript)は、次の通りです。

```
datalogger.onLogFull(function () {
    isFull = 1
    basic.showIcon(IconNames.No)
})
input.onButtonPressed(Button.AB, function () {
    datalogger.deleteLog(datalogger.DeleteType.Full)
    isFull = 0
    basic.showIcon(IconNames.Heart)
    control.reset()
})
let isFull = 0
isFull = 0
datalogger.mirrorToSerial(false)
datalogger.includeTimestamp(FlashLogTimeStampFormat.Milliseconds)
datalogger.setColumns(["a", "b", "c"])
basic.forever(function () {
    if (0 == isFull) {
        datalogger.logData([
        datalogger.createCV("a", 1234),
        datalogger.createCV("b", 5678),
        datalogger.createCV("c", 9012)
        ])
    }
})
```

## 結果

`MY_DATA.HTM`をブラウザで開き、データをCSV形式ファイルとしてダウンロードして、集計しました。

|#|項目|内容（値）|備考|
|---|---|---:|---|
|1|平均書き込み間隔|34.2 ms|29 行/秒|
|2|最小書き込み間隔|26.0 ms||
|3|最大書き込み間隔|88.0 ms||
|4|標準書き込み間隔|32.0 ms|最も頻度が大きいもの|
|5|書き込み行数|5684 行|ヘッダー行を除く|
|6|CSV形式ファイルサイズ|120 KB|122,880 バイト|
|7|記録可能時間|3分14秒||


# C/C++編

`uBit.log` ([MicrobitLog](https://github.com/lancaster-university/codal-microbit-v2/blob/master/inc/MicroBitLog.h))を直接呼び出すようにC/C++言語で確認プログラムを作成し、計測します。

## 方法

列(columns)を"a", "b", "c"の3列（3項目）とし、それぞれの値は、固定値 `1234`, `5678`, `9012` を繰り返し出力しました(エラー処理なし)。

|#|項目|内容|備考|
|---|---|---|---|
|1|シリアル通信出力|なし||
|2|タイムスタンプ出力|あり|ミリ秒単位|
|3|列(columns)|"a", "b", "c"|||
|4|値|a:1234, b:5678, c:9012|固定値|

使用したソースコード(抜粋)は、次の通りです。

```custom.cpp

    //%
    void startLoggingTest() {
        customlib::initLogger();
        // start
        customlib::beginRow();
        customlib::logString("Start Logging Test.");
        customlib::endRow();
        // header
        customlib::beginRow();
        customlib::logHeader("a");
        customlib::logHeader("b");
        customlib::logHeader("c");
        customlib::endRow();
        for (;;) {
            // data
            customlib::beginRow();
            customlib::logData("a", "1234");
            customlib::logData("b", "5678");
            customlib::logData("c", "9012");
            customlib::endRow();
        }
    }
```

``` customlib.cpp
#include "pxt.h"
#include "customlib.h"

#if MICROBIT_CODAL
#include "MicroBitLog.h"
#endif

namespace customlib {

/**
* Initialize the log.
**/
void initLogger() {
#if MICROBIT_CODAL
    uBit.log.setSerialMirroring(false);
    uBit.log.setTimeStamp(codal::TimeStampFormat::Milliseconds);
#endif
}

/**
* Creates a new row in the log, ready to be populated by logData()
**/
void beginRow() {
#if MICROBIT_CODAL
    uBit.log.beginRow();
#endif
}

/**
* Populates the current row with the given key/value pair.
**/
void logData(const char *key, const char *value) {
#if MICROBIT_CODAL
    if (NULL == key || NULL == value)
        return;
    uBit.log.logData(key, value);
#endif
}

/**
* Populates the current row with the given key as header.
**/
void logHeader(const char *key) {
    logData(key, "");
}

/**
* Inject the given row into the log as text, ignoring key/value pairs.
**/
void logString(const char *value) {
#if MICROBIT_CODAL
    if (NULL == value)
        return;
    uBit.log.logString(value);
#endif
}

/**
* Complete a row in the log, and pushes to persistent storage.
**/
void endRow() {
#if MICROBIT_CODAL
    uBit.log.endRow();
#endif
}

}
```

## 結果

`MY_DATA.HTM`をブラウザで開き、データをCSV形式ファイルとしてダウンロードして、集計しました。

|#|項目|内容（値）|備考|
|---|---|---:|---|
|1|平均書き込み間隔|10.2 ms|97 行/秒|
|2|最小書き込み間隔|8.0 ms||
|3|最大書き込み間隔|68.0 ms||
|4|標準書き込み間隔|8.0 ms|最も頻度が大きいもの|
|5|書き込み行数|5844 行|ヘッダー行を除く|
|6|CSV形式ファイルサイズ|120 KB|122,880 バイト|
|7|記録可能時間|59秒||

# まとめ

micro:bit V2 で拡張機能として追加された データ ロガーについて、その性能を3列の場合で、確認しました。

1. 10ms～35ms間隔でログ出力が可能です。
1. 書き込み可能な行数は、5684行～5844行です。

データ取得時間を含めると、実際のデータロガーにおいては、C/C++言語を用いてuBit.logを直接操作すれば、20ms間隔で2分間程度の記録が可能でしょう。

100ms以上の間隔であれば、ブロックプログラミングでも、十分にデータロガーとして機能します。