はじめに
Wio Nodeの学生むけの実習教材を作っていて、心拍センサーは非対応と書いてあるんだけれども、Generic Digital InputとWebSocket使えばいけるんじゃないのかな?と思って試してみました。
Wio Nodeと心拍センサーの接続
Grove Systemなので特に難しいことはないです。3番ピン(コネクタ側から見て左側)につないでいます。
アプリ側の設定
Generic Digital Input を選びます。
WebSocketのAPIが作られます。
プログラミング
Htmlに心拍数を表示するJSをバニラで書いてみます。
WebSocketのAPIは、心拍1回をトリガに、メッセージでイベントを4つ飛ばしてきます。接続しているのが3番ピンだとすると、心拍1回でON/OFFが連続的に同時に起こるので、
- {"msg": {"input_changed": "3"}}
- {"msg": {"input_rise": "3"}}
- {"msg": {"input_changed": "3"}}
- {"msg": {"input_fall": "3"}}
が送られてくることになります。
なので、input_riseかinput_fallを1回の心拍シグナルと見なして、心拍数を計算するプログラムにします。
"use strict";
// ミリ秒を取得する
const getMilis = function() {
return new Date().getTime();
}
// 心拍数を計算する(心拍合計/経過秒*60を小数点切り捨て)
const getHeartRate = function() {
let milis = getMilis() - initTime;
let rate = (beat / (milis / 1000.0)) * 60.0;
console.log(rate);
document.getElementById('rate').innerHTML = Math.floor(rate);
};
// 起動時のタイムスタンプ
const initTime = getMilis();
// 心拍合計
var beat = 0;
// 繰り返し処理
var interval = null;
// キー値
const key = '****';
// データをもらうためのWeb接続先
const ws = new WebSocket('wss://us.wio.seeed.io/v1/node/event');
window.onload = function() {
// Webに接続するための処理
ws.onopen = function() {
ws.send(key);
document.getElementById('wait').style.display = 'none';
};
// Webからデータを取得できたときの処理
// ピン番号を明確にしたければ、最初のifの条件式をjson.msg.input_rise === 'ピン番号' に。
ws.onmessage = function(evt) {
var json = JSON.parse(evt.data);
if (json.msg.input_rise) {
beat = beat + 1;
if (!interval) {
interval = setInterval(getHeartRate, 5000);
}
}
};
}
<body>
<p id="wait"><strong>じゅんびちゅう...</strong></p>
<p>心拍数:<span id="rate">?</span></p>
</body>
動作
この記事を書いている間に、心拍センサーをつけっぱなしにしてみました。
それっぽい値が出ています。(FitBitと比較して、誤差1〜2ぐらいでした)
なお、小数点を切り捨てにしています。
理由は、参考にしたUPMのソースコードがそうなっていたからなんですが、いいんですかね?
医療機器とか医療システムの中の人がいらっしゃいましたら、ぜひ教えてください。
おわりに
一見、Wio Nodeに対応していないGroveセンサーでも、Generic Digital Input, Generic Analog Inputを使って、対応させることができそうです。(全部はどうかわかりませんが)
参考までに、ソースコードを gistにおいておきました。キー(アクセストークン)は各自のものに変えてください。