2021年07月29日 更新

BLEでリアルタイムグラフ表示

どうも、クラゲです。
今回は、BLEデバイスからNotifyで読み込んだデータをリアルタイムにグラフ表示する方法を紹介します。横方向を時間軸として、次々とデータが流れるため、センサー値をリアルタイムでモニターするなどに最適です。

Smoothie Chartsというライブラリを活用しています。
グラフライブラリはc3.jsやChart.jsが有名ですが、Smoothie Chartsのようにオシロスコープ表示のような感じで描くことはできないと思います。

【 必要なもの 】

Scan と同様

【 micro:bitの準備 】

Scan と同様

micro:bitが手元にない人は、HTML側のUUIDと受信データフォーマットを変更すれば、他のBLEデバイスでも対応可能です

【 デモページとソースコード 】

WEB上で試せるデモページはこちら
BlueJelly Sample : Graph

ローカル環境で試したい方はこちらのGitHubからダウンロードし、advance_graph.htmlを開いて実行してください。

micro:bitを傾けることで、リアルタイムに角度(-179°〜180°)をグラフに描画します

【 プログラム解説(HTML) 】

ベースは Notify です。
グラフ追加部分を見てゆきましょう。

Smoothie Chartを使うために、以下のサイトからsmoothie.jsをダウンロードしてHTMLファイルと同じ階層に置いて下さい。

http://smoothiecharts.org/smoothie.js
右クリックでダウンロードしてください

smoothie.jsを呼び出します

<script type="text/javascript" src="./smoothie.js"></script>

Smoothie Chartが描画するためのCANVASを準備します。大きさは自由に決めてOKです

<canvas id="chart" width="500" height="320"></canvas>

【 プログラム解説(JavaScript) 】

Global変数宣言時に、TimeSeriesのインスタンス生成を行います
ble_dataという変数名は別名に変えても良いです。

var ble_data = new TimeSeries();

createTimelineという関数を作ります。3つの重要な要素が入っています。

  • new SmoothieChart
    グラフの箱の部分(背景や軸)を作ります。 SmoothieChartのインスタンスを生成してchartという名前にしています。

  • chart.addTimeSeries
    グラフそのものを追加します。 最初に作ったble_dataをグラフの箱であるchartに適用しています。

  • chart.streamTo
    グラフを実際のHTMLに描画します。 HTMLで設定したCANVASに描画を結びつけています。

//-------------------------------------------------
//smoothie.js
//-------------------------------------------------
function createTimeline() {
    var chart = new SmoothieChart({
        millisPerPixel: 20,
        grid: {
            fillStyle: '#ff8319',
            strokeStyle: '#ffffff',
            millisPerLine: 800
        },
        maxValue: 1024,
        minValue: 0
    });
    chart.addTimeSeries(ble_data, {
        strokeStyle: 'rgba(255, 255, 255, 1)',
        fillStyle: 'rgba(255, 255, 255, 0.2)',
        lineWidth: 4
    });
    chart.streamTo(document.getElementById("chart"), 500);
}

上記の中身の詳細設定について説明します。

  • new SmoothieChart
    millisPerPixel は横軸の単位です。今回は20ms/Pixelとしています。 CANVASのサイズが500Pixelなので、横軸は10秒間を示すことになります。値を小さくするとグラフの流れが早くなり、大きくするとグラフの流れがゆっくりとなります。
    gridの fillStyle は背景色、strokeStyleは軸と補助線の色、millisPerLineは補助線をどのくらいの間隔で描画するかの設定です。今回は1Lineあたり800msという意味になります。グラフ全体は10秒なので、10000/800 = 12.5LINEが画面に存在することになります。
    maxValueは縦軸の最大値、minValueは縦軸の最小値です。この設定を省略した場合は、データに応じて動的に最大・最小が変化します。アニメーションするため、見た目は面白いのですが、絶対的な値の感覚がつかみにくいため、クラゲは固定値を設定しています。

  • chart.addTimeSeries
    strokeStyleはグラフの色です。RGBのカラーに加えアルファ値(不透明度)を指定しています。
    fillStyleはグラフの下側領域の背景色です。同様にRGBAで指定します。
    アルファ値は0〜1.0で小さいほど透明になります。
    lineWidthはグラフの太さです。

  • chart.streamTo
    最後の引数の500という数値は、描画のディレイ(遅延)です。0にすると最新のデータがグラフの右端でプロットされるようになりますが、次のデータが決まっていないため、右端での動きがカクカクになります。これを回避するためにディレイを設けます。逆に大きすぎるとリアルタイムではなくなるため注意が必要です。

windowロード時に先ほどの関数createTimelineを呼ぶようにします。

//smoothie.js
createTimeline();

READ時に、取得したデータをグラフへ追加します。
1番目の引数は時間です。

//グラフへ反映
ble_data.append(new Date().getTime(), value);

これで、いい感じのグラフが描画できるようになりました!

以上、BLEでリアルタイムグラフ表示でした。