クリスマスも近いので、睡眠計測&遠隔起床装置を作った
最近寒いですね。いよいよクリスマスが近づいてきました。
こんな日は、IoT開発に限ります。
はじめに
この記事は、大学の授業に提出する最終レポートを兼ねています。そのため、記事としては少し違和感を覚える箇所があるかもしれません。
加えて、今年の東京電機大学アドベントカレンダー 23日目の記事でもあります。
目的
本記事は、課題の条件に沿って作成したシステムを提示し、その制作過程を伝えることを目的とする。はじめにシステムの概要を説明し、次にM5StackCore2を用いた計測装置および計測結果を可視化する手法を述べ、最後に結果と感想を述べる。
課題条件の要約は以下:
- M5StackまたはArduinoに1つ以上のセンサを加えて、センサデータを取得すること。
- アクチュエータを、取得したセンサ値の変化に応じて制御させること。LED、振動、LCD(液晶)、サーボモータなど1つ以上。動作写真を掲載すること。
- 取得したセンサデータをグラフで表示し、考察せよ。
システム概要
本システムは、睡眠中に使用するシナリオを想定して制作した。計測装置で睡眠中の体の動きや呼気をセンシングし、取得した値をWeb上で観察することができる。加えて、Web上のボタンを押すことで、アクチュエータである振動モータを動かし、計測装置を付けた人間を起こすことができる。このシステムは特段、なんらかの課題を解決するものではない。
システム構成としては、エッジ側から、M5StackCore2(以下、M5Stack)とTVOC/eCO2(以下、CO2センサ)、Node-RED、cables.glで構成されている。M5StackとNode-RED間はMQTTで、Node-REDとcables.gl間はWebSocketで通信を行っている。
また、M5Stackのプログラミングには、UIFlowを用いた。
システム構成図
アプリケーションは以下で試すことができるが、手元のM5Stackの電源が入っていないと動かないので、ほとんどの場合作動しない。
cables.glのパッチそのものは、以下で公開されている。
UIFlow、Node-RED、cables.glそれぞれのソースコードは、以下のリポジトリにまとめてある。
システム詳細
具体的なデータフローを述べる。データの流れは行きと帰りの2系統ある。
- M5Stackに接続されたCO2センサと内蔵のIMUで取得したセンサデータが、JSON形式としてMQTTでNode-REDに送信される。MQTTブローカーはNode-RED上のAedesMQTTbrokerノードを使用している。Node-REDに送られたデータはCSV形式でファイルに記録され、WebSocketでCables.glに送信される。WebSocketサーバはNode-REDサーバが兼ねている。cables.glは受け取ったデータを元に、WebGLを描画する。
- cables.gl上のボタンが押されると、メッセージを含んだJSONがWebSocketで送出される。Node-REDはそれを受け取り、MQTTの送信をトリガーする。M5StackはMQTTを受信すると、画面の表示を変更し、振動モータを作動させる。
使用サービス一覧
- UIFlow
- Node-RED
- cables.gl
センサ・アクチュエータ一覧
- TVOC/eCO2センサ
- 6軸IMU (M5Stack)
- ディスプレイ (M5Stack)
- 振動モータ (M5Stack)
使用プロトコル一覧
- MQTT
- WebSocket
動作の様子
計測装置
通常の状態
アプリケーション側でボタンが押された後の状態
Cables.glで作成したアプリケーションの様子
M5Stackのセンサデータにリアルタイムで反応する
ソースコード
ソースコードは上記GitHubリポジトリにある。ビジュアルプログラミング環境については、以下に参考のキャプチャを貼る。
UIFlow
Node-RED
cables.gl
取得されるデータの例と可視化
Node-REDのCSVノードを用いてセンサデータをCSVファイルに変換し、matplotlibとpandasでグラフにした。
以下のグラフは、実際の睡眠を計測したものではない。実際の睡眠を計測するにはM5Stackのバッテリーが持たないという問題があり、外付けのバッテリーを用意する必要がある。しかし、今回は時間の問題からそこまでできなかった。
時刻とIMUのグラフ
import matplotlib.pyplot as plt
import pandas as pd
df = pd.read_csv(io.BytesIO(uploaded['data.csv']))
plt.plot(pd.to_datetime(df['time']), df['pitch'])
plt.plot(pd.to_datetime(df['time']), df['roll'])
時刻を横軸に、IMUのピッチとロールを縦軸にとったグラフの例
実際の睡眠のグラフではないが、ピッチ角とロール角の関係が見て取れる。
時刻とCO2量のグラフ
import matplotlib.pyplot as plt
import pandas as pd
df = pd.read_csv(io.BytesIO(uploaded['data.csv']))
plt.plot(pd.to_datetime(df['time']), df['co2'])
時刻を横軸に、CO2量を縦軸にとったグラフの例
19時ごろにグラフが大きく伸びている。この時間はキッチンで料理をしていたタイミングと一致しており、空気中のTVOC増加に反応したものと考えられる。
まとめ
冒頭の課題条件に照らして、システム構成をまとめる:
- M5StackCore2を用いた。内蔵IMUと、TVOC/eCO2センサを使用した。
- センサの値に応じて、画面の表示を変更した。追加機能として、振動モーターを動かした。
- 取得したセンサデータをmatplotlib・pandasを用いることで可視化した。
上記に加えて、Node-REDでのプログラミングや、cables.glでのアプリケーション制作に挑戦した。
感想
いつもながら、作っていて非常に楽しかった。楽しい気持ちもありつつ、課題のたびに新しい技術に挑戦しているのもあり、たくさん苦労した。MQTTもWebSocketもNode-REDも初めて触ったので、これらを組み合わせるのに時間を要した。
今回は、多くのセンサを触る機会がなかったので、たくさんのセンサを試す機会を別に持ちたい。
さて、本記事ではここまで強調していないが、このシステムがノーコードだという点に触れておきたい。コーディングは散々やっているし、新しいものを触りたいし、という気持ちでこのような構成になったが、「意外としっかり作れるな」という感想だった。
UIFlowは思った通りのことができなくてもどかしく感じる場面もあったが、一方、普通に書くと大変な、M5のディスプレイのUI実装が楽な点(これは本当にすごい)や通信機能を簡単に作れる点など、明らかな強みも感じた。クラウドとの連携もサポートされているようで侮れない。
Node-REDは痒い所に手が届く機能が数多く提供されていて、カスタムノードも合わせれば幅広い処理を素早く実装できた。データ構造をデストラクトする方法など、少々慣れが必要なところもあるが、総じてその実力が高いことを実感した。IoTプラットフォームとして使われるのもうなずける。
cables.glは、TouchDesignerやMax、vvvvを思わせる直感的かつ完成度の高い操作性が魅力的に感じた。ブラウザで操作できるオーサリングツールというだけでも価値が高いうえ、GitHubやNetlifyに簡単にエクスポートして公開できるという点で、唯一無二だと思う。何より見た目がイケている。今後の発展に期待したい。
Discussion