SlideShare a Scribd company logo
センサネットワークと組み込み技術 最終レポート
IoT デバイスセンサデータ分析
2020 年 1 月
Nihei Yuki
目次
1. 目的 .......................................................................................................................1
2. システム概要 .........................................................................................................1
3. センサの種類と型、アクチュエータの種類 ...........................................................2
• センサ ..................................................................................................................... 2
• アクチュエータ ....................................................................................................... 2
• 動作の様子 .............................................................................................................. 2
4. Arduino ソースコード............................................................................................3
5. Python 送信側コード .............................................................................................6
6. Node.js 受信側コード............................................................................................7
7. Python グラフ可視化コード...................................................................................8
8. 生成されるグラフの例 .........................................................................................10
9. 考察と今後の発展 ................................................................................................11
10. 苦労した点 .......................................................................................................11
11. 参考 URL..........................................................................................................12
1
1. 目的
本レポートは,Arduino を用いて得たセンサデータをクラウドに送信し,それらを
グラフ化することによりセンサデータを可視化するための手法および結果を述べるこ
とを目的とする.
2. システム概要
本システムは,図1に示すように,ローカル側とクラウド側で構成されている.ま
ずローカルでは Arduino を用いて取得したセンサデータを PC 等の端末で受信し
MQTT を用いて Cloud Pub/Sub に送信する 1)
.そしてクラウド上では受け取ったデ
ータを Cloud Functions 経由で Firestore に送信する 2),3)
.また,蓄積されたデータは
HTTP アクセスをトリガーとして閲覧することが可能となっている 4)
.
今回は Firebase Hosting と Vue.js を用いて以下の閲覧用サイトを作成した.
なお最新の画像および動作時の動画には以下の URL からアクセス可能である.
https://spherical-voice-251409.firebaseapp.com/
(2020 年 4 月までアクセス可能であることを保証します)
図1 システムの概要
2
3. センサの種類と型、アクチュエータの種類
今回は IoTAB シールドに含まれている部品を使用したため,Arduino と距離センサ
を接続したシールドのみで再現することが可能である.
• センサ
 温度センサ STS30 I2C 接続(アドレス: 0x4A)
 照度センサ BH1780 I2C 接続(アドレス: 0x29)
 加速度センサ MMA8452Q I2C 接続(アドレス: 0x1C)
 距離センサ HC-SR04 デジタル入力/出力: D12/D13
 可変抵抗器 3386K-EY5-103TR アナログ入力: A3
• アクチュエータ
 LCD AQM0802A-RN-GBW I2C 接続(アドレス: 0x7C)
 LED OSYG1608C1A デジタル出力: D3〜D8
• 動作の様子
Raspberry Pi は Wi-Fi でネットワークに接続できるため,モバイルバッテリーを
用いることにより完全な無線化が可能である.
図2 動作の様子
距離に応じて変化
温度と加速度
(x,y 軸)を表示
LED 変化の
大きさを変更
距離センサ
温度センサ
シリアル通信
3
4. Arduino ソースコード
//*******************************************
//* センサネットワークと組み込み技術 最終課題
//* 2020/1 17FI552 二瓶雄貴
//*******************************************
// I2C に必要
#include <Wire.h>
// 温度センサに必要
#include <STSSensor.h>
STSSensor sts30(Wire);
// 定数の定義
#define ACCaddr 0x1C // 加速度センサ
#define LightAddr 0x29 // 照度センサ
#define echoPin 12 // Echo ピン
#define trigPin 13 // Trigger ピン
#define volPin 3 // 可変抵抗ピン
// 変数の宣言と初期化
double Duration = 0; // 超音速を受信した間隔
int LEDLevel = 0; // LED で表せる距離の範囲
double Distance = 0; // 距離
double Temp = 0; // 温度
double TempOld = 0; // 過去の温度
int Light = 0; // 照度
int LightOld = 0; // 過去の照度
void setup() {
Wire.begin();
lcd_init();
// 加速度センサの初期化
Wire.beginTransmission(ACCaddr);
Wire.write(0x2A);
Wire.write(0x00);
Wire.endTransmission();
Wire.beginTransmission(ACCaddr);
Wire.write(0x2A);
Wire.write(0x01);
Wire.endTransmission();
Wire.beginTransmission(ACCaddr);
Wire.write(0x0E);
Wire.write(0x00); // Set range to +/- 2g
Wire.endTransmission();
delay(300);
4
// 温度センサの初期化
sts30.init(Wire);
// 照度センサの初期化
Wire.beginTransmission(LightAddr);
Wire.write(0x80);
Wire.write(0x03);
Wire.endTransmission();
Serial.begin(9600); // シリアル通信の初期化
pinMode(echoPin, INPUT); // Echo ピンを入力に設定
pinMode(trigPin, OUTPUT); // Trigger ピンを出力に設定
for(int i=3; i<9; i++)
pinMode(i,OUTPUT); // LED を出力に設定
}
void loop() {
// 加速度センサからの入力を受け取る
unsigned int accData[5];
Wire.requestFrom(ACCaddr, 5);
// staus, xAccl lsb, xAccl msb, yAccl lsb, yAccl msb
if(Wire.available() == 5)
for (int i=0; i<5; i++) accData[i]= Wire.read();
// 加速度を変数に格納する
int xAcc = accl(&accData[1]);
int yAcc = accl(&accData[3]);
//温度センサからの入力を受け取る
sts30.readSample();
Temp = sts30.getTemperature();
// 照度センサからの入力を受け取る
Light = i2c_readlux();
// 超音波を出力する
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds( 10 );
digitalWrite(trigPin, LOW);
// 超音速センサからの入力を受け取る
Duration = pulseIn(echoPin, HIGH);
LEDLevel = analogRead(volPin)/32+1;
// 距離によって LED を点灯させる
if (Duration > 0) {
Duration = Duration / 2; // 往復距離を半分にする
Distance = Duration * 340 * 100 / 1000000; // 音速を 340m/s に設定
5
if (Distance <= 450) { // 測定可能距離は 450cm まで
for(int i=0; i<6; i++)
digitalWrite(i+3, (int)(Distance/LEDLevel)>i?HIGH:LOW);
}
}
// 1 行目を生成
char tempbuf[6]; // 温度を格納する変数
// 小数はそのまま表示できないため一度文字列に変換
dtostrf(Temp, 5, 2, tempbuf); // %5.2f と同様の文字列を生成
// LCD 表示部
char pr[8]; // 1 行分を格納する変数
lcd_clear();
lcd_setCursor(0,0); // カーソルを 1 行目の先頭に
sprintf(pr,"%s[C]",tempbuf); // 温度を表す文字列
lcd_printStr(pr); // 1 行分を表示
lcd_setCursor(0,1); // カーソルを 2 行目の先頭に
sprintf(pr,"%4d%4d",xAcc/10,yAcc/10);// 加速度を表す文字列
lcd_printStr(pr); // 1 行分を表示
// データ送信部
if(abs(Temp - TempOld) > 0.5 || abs(Light - LightOld) > 5) {
// 温度変化が 0.5 度を超えたか照度変化が 5Lx を超えたら
writeSerial(Temp, Light); // センサデータを送信
TempOld = Temp; // 比較対象の温度を更新
LightOld = Light; // 比較対象の温度を更新
}
delay(300); // 1 秒待機
}
// センサデータを送信する関数
void writeSerial(double temp, int light) {
Serial.write("STARTn");
char buf[1];
String str;
str = (temp != -1 ? String(temp) : "") + "n";
str += (light != -1 ? String(light) : "") + "n";
str.toCharArray(buf, str.length() + 1);
Serial.write(buf);
Serial.write("ENDn");
}
// 加速度を変換する関数
int accl(int d[]) {
6
int val = ((d[0]*256+d[1]))/16;
if (val > 2047) val -= 4096;
return val;
}
// 照度を読み取る関数
uint16_t i2c_readlux() {
uint16_t val;
Wire.beginTransmission(LightAddr);
Wire.write(0x8D);
Wire.endTransmission();
Wire.beginTransmission(LightAddr);
Wire.requestFrom(LightAddr,2);
delay(150);
val = Wire.read();
Wire.endTransmission();
val <<=8;
Wire.beginTransmission(LightAddr);
Wire.write(0x8C);
Wire.endTransmission();
Wire.beginTransmission(LightAddr);
Wire.requestFrom(LightAddr,2);
delay(150);
val |= Wire.read();
Wire.endTransmission();
return val;
}
LCD の制御に必要なライブラリを https://github.com/JanStegenga/Arduino-STS-lib
からダウンロードしインストールする必要がある.
5. Python 送信側コード
実行するためには,pip を用いた pyserial と google-cloud-pubsub のインストールが
必要である.また,認証情報を格納した json ファイルへのパスを環境変数
GOOGLE_APPLICATION_CREDENTIALS に格納しておく必要がある.
# Arduino からセンサの値を受け取って Google Cloud Pub/Sub に MQTT で送信する
プログラム
# 2020/1 17FI552 二瓶雄貴
import serial
from google.cloud import pubsub_v1
# パブリッシャーの設定
publisher = pubsub_v1.PublisherClient()
# トピックの設定
7
project_id = 'spherical-voice-251409'
topic_name = 'iot-sensor-data'
topic_path = publisher.topic_path(project_id, topic_name)
if __name__ == "__main__":
# Arduino の接続ポートを書く
ser = serial.Serial("/dev/cu.usbmodem14201", 9600)
data = []
flag = False
while True:
message = ser.readline().decode("utf-8").replace("n", "")
if message == "START":
flag = True
elif message == "END":
flag = False
# データをバイト列にエンコードして送信
future = publisher.publish(topic_path,
",".join(data).encode("utf-8"))
# print(future.result())
data = []
else:
if flag:
print(message)
data.append(message)
6. Node.js 受信側コード
Cloud Functions 上の Node.js 8 以上でのみ動作するコードが含まれている.
index.js
/**
* Triggered from a message on a Cloud Pub/Sub topic.
*
* @param {!Object} data Message on a topic.
* @param {!Object} context Metadata for the event.
*/
const functions = require('firebase-functions')
// cloud function で firestore を使うのに必要な設定は以下の2行
const admin = require('firebase-admin')
admin.initializeApp(functions.config().firebase)
8
// データベースの参照を作成
var db = admin.firestore()
exports.subscribe = (data, context) => {
var message = Buffer.from(data.data, 'base64').toString();
// console.log("Message: ", message);
var docRef = db.collection('record');
docRef.add({
"timestamp": parseInt(Date.now()/1000),
"temp": message
});
};
package.json
{
"name": "iot2firestore",
"version": "1.0.0",
"dependencies": {
"@google-cloud/firestore": "^0.16.1",
"firebase-admin": "^6.0.0",
"firebase-functions": "^1.0.0"
}
}
7. Python グラフ可視化コード
Cloud Functions 以外での実行には認証情報が必要である.
main.py
from flask import make_response
import datetime
import operator
import matplotlib.pyplot as plt
from matplotlib import rcParams
from matplotlib.backends.backend_agg import FigureCanvasAgg
from google.cloud import firestore
from io import BytesIO
def make_graph(request):
# フォントの設定
9
rcParams['font.family'] = 'sans-serif'
rcParams['font.sans-serif'] = ['Noto Sans CJK JP', 'Hiragino
Sans', 'Hiragino Maru Gothic Pro', 'Yu Gothic']
# 最新 20 件のコレクション取得
db = firestore.Client()
query =
db.collection(u'record').order_by(u'timestamp',direction=firestore.Query.D
ESCENDING).limit(20)
results = query.stream()
# データを取得する
lists = {}
for result in results:
res = result.to_dict()
lists[datetime.datetime.fromtimestamp(res['timestamp'],
datetime.timezone(datetime.timedelta(hours=9)))] = (float(res['temp']) ,
int(res['light']))
# 時刻順に並び替える
lists = sorted(lists.items())
# グラフ生成
fig, ax = plt.subplots()
ax.set_title(u'センサデータ')
# リストからデータを抽出
x = list(map(operator.itemgetter(0), lists))
y = list(map(operator.itemgetter(1), lists))
# y 軸のデータを分割しプロット
y1 = list(map(operator.itemgetter(0), y))
ax.plot(x, y1, label='温度 [℃]', color='b', linewidth=2)
y2 = list(map(operator.itemgetter(1), y))
ax.plot(x, y2, label='輝度 [Lx]', color='r', linewidth=2)
# 凡例の位置を自動で変更
plt.legend(loc='best')
# 軸ラベルの設定
plt.xlabel('時刻')
# x 軸を回転させる
plt.xticks(rotation=70)
# 余白を調整
plt.subplots_adjust(left=0.07, right=0.97, bottom=0.21, top=0.93)
# グリッドを設定
plt.grid()
# グラフの画像を生成
10
canvas = FigureCanvasAgg(fig)
buf = BytesIO()
canvas.print_png(buf)
data = buf.getvalue()
# HTTP レスポンスを生成
response = make_response(data)
response.headers['Content-Type'] = 'image/png'
response.headers['Content-Length'] = len(data)
# キャッシュ設定 ブラウザごとに 5 分,CDN に 10 分
response.headers['Cache-Control'] = 'public, max-age=300, s-
maxage=600'
return response
requirements.txt
matplotlib
google-cloud-firestore
8. 生成されるグラフの例
7.で示したコードにより図3に示すようなグラフが生成される.今回はセンサを屋
内の窓際に設置した.日射により温度と輝度が変化している.
図3 センサデータを元に生成されたグラフ
11
9. 考察と今後の発展
今回製作したシステムにより,IoT 機器を用いて取得したセンサデータをクラウド
上にアップロードし管理することにより遠隔地の環境をリアルタイムに確認すること
が出来た.
今後,更なるユビキタスセンサーネットワーク技術や機械学習技術の発達により継
続的に複数地点の遠隔監視を行うことができ,一般家庭から収集したセンサデータ
をビックデータとして機械学習を用いて統計処理することにより様々な関連性を見出
すことができ,産業の発展やネットワーク機器の利便性向上に貢献することが期待で
きる.
10. 苦労した点
• IoTAB シールドのサンプルファイルを用いて温度センサの値を取得しようとした
が2つの問題があった.
 STS ライブラリが別途必要だったためインストールした.
 サンプルファイルには一向に新しいデータに更新されない問題があり,STS
ライブラリのページを参照すると sht.readSample();を都度実行する必要があ
るとの記述があった 5)
ため実行することにより解決した.
• Raspberry Pi における google-cloud-pubsub のセットアップ時に grpcio のビルドが
永遠に終わらない問題があったためビルド済みのバイナリをインストールした 6)
.
• Cloud Functions の Node.js のバージョンの違いにより関数の記述方法が変わって
おりエラーの特定に数時間を要した 7)
.
• Cloud Forestore の設定画面から取得したサービスアカウントの秘密鍵(JSON フ
ァイル)には type 属性などの必要な属性が含まれていなかったため動作せず,
Cloud Console の IAM 管理画面から秘密鍵をダウンロードする必要があった.
• ローカルでは Python を用い,Cloud Functions では Node.js を用いており,ローカ
ルとクラウド上での言語の違いやサービスアカウントの認証方法の違い(Cloud
Functions では認証情報を簡単に取得できる)があった.
• Python で作成したグラフを Firebase Hosting を用いて表示させるために Cloud
Functions を用いて生成したファイルを Cloud Storage に格納する方法を模索して
いたが,5時間ほどかけても解決できなかったために JavaScript を用いて実現する
こととした.
• その後二日間を要したが最終的には HTTP リクエストにより Python を用いたグ
ラフを生成させることに成功した 4),8)
.特にリスト型と辞書型,タプル型の変換に
苦労した.
12
11. 参考 URL
1) 「クイックスタート: Pub/Sub システム機能の構築」
https://cloud.google.com/pubsub/docs/quickstart-py-mac?hl=ja
2) 「Firebase を使って IoT データをリアルタイム可視化する」
https://camp.isaax.io/ja/examples/firebase-realtime-visualization
3) 「IoT Core から Cloud Functions 経由で Firestore にデータを追加する」
https://qiita.com/bathtimefish/items/1f4885c130d23eb63710
4) 「Google Cloud Functions の HTTP トリガーで matplotlib を使って生成した
画像を返す」
https://qiita.com/tanabee/items/2bfee85f9659be097750
5) 「GitHub - JanStegenga/Arduino-STS-lib」
https://github.com/JanStegenga/Arduino-STS-lib#integrating-it-into-your-sketch
6) 「Google Cloud IoT Core の環境構築ではまったところ(デバイス側)
」
http://chinoppy.hatenablog.com/entry/2019/01/06/190530
7) 「Cloud Functions の nodejs6 を nodejs8 に移行するとき、バックグラウンド関数
を使っているときは引数を修正する」
https://qiita.com/itatibs/items/5540c0ac94582ab4851e
8) 「Cloud Firestore のデータを Python で取得する」
https://qiita.com/yusukeito58/items/c77feaa25fbbe37e9953

More Related Content

Similar to IoTデバイス センサデータ分析システム

サーバ異常検知入門
サーバ異常検知入門サーバ異常検知入門
サーバ異常検知入門mangantempy
 
データセンターの電力量ログをGAEで
データセンターの電力量ログをGAEでデータセンターの電力量ログをGAEで
データセンターの電力量ログをGAEでhidemotoNakada
 
Bluetooth通信の 仕組みと活用法紹介
Bluetooth通信の仕組みと活用法紹介Bluetooth通信の仕組みと活用法紹介
Bluetooth通信の 仕組みと活用法紹介
Takehiko YOSHIDA
 
衛星芸術Pbl 2011 10_18
衛星芸術Pbl 2011 10_18衛星芸術Pbl 2011 10_18
衛星芸術Pbl 2011 10_18Koichiro Mori
 
200625material naruse
200625material naruse200625material naruse
200625material naruse
RCCSRENKEI
 
RouterBOARD with OpenFlow
RouterBOARD with OpenFlowRouterBOARD with OpenFlow
RouterBOARD with OpenFlow
Toshiki Tsuboi
 
DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519
DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519
DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519Yasuhiro Ishii
 
show コマンド結果をパースする方法あれこれ #npstudy
show コマンド結果をパースする方法あれこれ #npstudyshow コマンド結果をパースする方法あれこれ #npstudy
show コマンド結果をパースする方法あれこれ #npstudy
akira6592
 
[AI08] 深層学習フレームワーク Chainer × Microsoft で広がる応用
[AI08] 深層学習フレームワーク Chainer × Microsoft で広がる応用[AI08] 深層学習フレームワーク Chainer × Microsoft で広がる応用
[AI08] 深層学習フレームワーク Chainer × Microsoft で広がる応用
de:code 2017
 
AWS Black Belt Techシリーズ AWS CloudTrail & CloudWatch Logs
AWS Black Belt Techシリーズ AWS CloudTrail & CloudWatch LogsAWS Black Belt Techシリーズ AWS CloudTrail & CloudWatch Logs
AWS Black Belt Techシリーズ AWS CloudTrail & CloudWatch Logs
Amazon Web Services Japan
 
PF部2011年12月勉強会.androidsola
PF部2011年12月勉強会.androidsolaPF部2011年12月勉強会.androidsola
PF部2011年12月勉強会.androidsolaandroid sola
 
トレジャーデータ株式会社について(for all Data_Enthusiast!!)
トレジャーデータ株式会社について(for all Data_Enthusiast!!)トレジャーデータ株式会社について(for all Data_Enthusiast!!)
トレジャーデータ株式会社について(for all Data_Enthusiast!!)Takahiro Inoue
 
C++0x in programming competition
C++0x in programming competitionC++0x in programming competition
C++0x in programming competition
yak1ex
 
ものづくりプロジェクトII 一日でわかるArduino入門
ものづくりプロジェクトII 一日でわかるArduino入門ものづくりプロジェクトII 一日でわかるArduino入門
ものづくりプロジェクトII 一日でわかるArduino入門
Yoichi Yamazaki
 
JAWS DAYS 2018 | IoT時代におけるデバイスのファームウェアとクラウドのいい関係
JAWS DAYS 2018 | IoT時代におけるデバイスのファームウェアとクラウドのいい関係JAWS DAYS 2018 | IoT時代におけるデバイスのファームウェアとクラウドのいい関係
JAWS DAYS 2018 | IoT時代におけるデバイスのファームウェアとクラウドのいい関係
SORACOM,INC
 
PL/CUDA - Fusion of HPC Grade Power with In-Database Analytics
PL/CUDA - Fusion of HPC Grade Power with In-Database AnalyticsPL/CUDA - Fusion of HPC Grade Power with In-Database Analytics
PL/CUDA - Fusion of HPC Grade Power with In-Database Analytics
Kohei KaiGai
 
[db tech showcase Tokyo 2017] D15: ビッグデータ x 機械学習の高速分析をVerticaで実現!by ヒューレット・パッ...
[db tech showcase Tokyo 2017] D15: ビッグデータ x 機械学習の高速分析をVerticaで実現!by ヒューレット・パッ...[db tech showcase Tokyo 2017] D15: ビッグデータ x 機械学習の高速分析をVerticaで実現!by ヒューレット・パッ...
[db tech showcase Tokyo 2017] D15: ビッグデータ x 機械学習の高速分析をVerticaで実現!by ヒューレット・パッ...
Insight Technology, Inc.
 
NoSQL/SQLデュアルインターフェースを備えた IoT向けデータベースGridDB - 強化された時系列データ管理・検索機能について -
NoSQL/SQLデュアルインターフェースを備えた IoT向けデータベースGridDB - 強化された時系列データ管理・検索機能について -NoSQL/SQLデュアルインターフェースを備えた IoT向けデータベースGridDB - 強化された時系列データ管理・検索機能について -
NoSQL/SQLデュアルインターフェースを備えた IoT向けデータベースGridDB - 強化された時系列データ管理・検索機能について -
griddb
 
自作仮想化基盤 「n0stack」の紹介
自作仮想化基盤 「n0stack」の紹介自作仮想化基盤 「n0stack」の紹介
自作仮想化基盤 「n0stack」の紹介
Takeshi Take
 

Similar to IoTデバイス センサデータ分析システム (20)

サーバ異常検知入門
サーバ異常検知入門サーバ異常検知入門
サーバ異常検知入門
 
データセンターの電力量ログをGAEで
データセンターの電力量ログをGAEでデータセンターの電力量ログをGAEで
データセンターの電力量ログをGAEで
 
Bluetooth通信の 仕組みと活用法紹介
Bluetooth通信の仕組みと活用法紹介Bluetooth通信の仕組みと活用法紹介
Bluetooth通信の 仕組みと活用法紹介
 
衛星芸術Pbl 2011 10_18
衛星芸術Pbl 2011 10_18衛星芸術Pbl 2011 10_18
衛星芸術Pbl 2011 10_18
 
200625material naruse
200625material naruse200625material naruse
200625material naruse
 
RouterBOARD with OpenFlow
RouterBOARD with OpenFlowRouterBOARD with OpenFlow
RouterBOARD with OpenFlow
 
DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519
DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519
DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519
 
show コマンド結果をパースする方法あれこれ #npstudy
show コマンド結果をパースする方法あれこれ #npstudyshow コマンド結果をパースする方法あれこれ #npstudy
show コマンド結果をパースする方法あれこれ #npstudy
 
[AI08] 深層学習フレームワーク Chainer × Microsoft で広がる応用
[AI08] 深層学習フレームワーク Chainer × Microsoft で広がる応用[AI08] 深層学習フレームワーク Chainer × Microsoft で広がる応用
[AI08] 深層学習フレームワーク Chainer × Microsoft で広がる応用
 
AWS Black Belt Techシリーズ AWS CloudTrail & CloudWatch Logs
AWS Black Belt Techシリーズ AWS CloudTrail & CloudWatch LogsAWS Black Belt Techシリーズ AWS CloudTrail & CloudWatch Logs
AWS Black Belt Techシリーズ AWS CloudTrail & CloudWatch Logs
 
PF部2011年12月勉強会.androidsola
PF部2011年12月勉強会.androidsolaPF部2011年12月勉強会.androidsola
PF部2011年12月勉強会.androidsola
 
トレジャーデータ株式会社について(for all Data_Enthusiast!!)
トレジャーデータ株式会社について(for all Data_Enthusiast!!)トレジャーデータ株式会社について(for all Data_Enthusiast!!)
トレジャーデータ株式会社について(for all Data_Enthusiast!!)
 
C++0x in programming competition
C++0x in programming competitionC++0x in programming competition
C++0x in programming competition
 
ものづくりプロジェクトII 一日でわかるArduino入門
ものづくりプロジェクトII 一日でわかるArduino入門ものづくりプロジェクトII 一日でわかるArduino入門
ものづくりプロジェクトII 一日でわかるArduino入門
 
JAWS DAYS 2018 | IoT時代におけるデバイスのファームウェアとクラウドのいい関係
JAWS DAYS 2018 | IoT時代におけるデバイスのファームウェアとクラウドのいい関係JAWS DAYS 2018 | IoT時代におけるデバイスのファームウェアとクラウドのいい関係
JAWS DAYS 2018 | IoT時代におけるデバイスのファームウェアとクラウドのいい関係
 
PL/CUDA - Fusion of HPC Grade Power with In-Database Analytics
PL/CUDA - Fusion of HPC Grade Power with In-Database AnalyticsPL/CUDA - Fusion of HPC Grade Power with In-Database Analytics
PL/CUDA - Fusion of HPC Grade Power with In-Database Analytics
 
[db tech showcase Tokyo 2017] D15: ビッグデータ x 機械学習の高速分析をVerticaで実現!by ヒューレット・パッ...
[db tech showcase Tokyo 2017] D15: ビッグデータ x 機械学習の高速分析をVerticaで実現!by ヒューレット・パッ...[db tech showcase Tokyo 2017] D15: ビッグデータ x 機械学習の高速分析をVerticaで実現!by ヒューレット・パッ...
[db tech showcase Tokyo 2017] D15: ビッグデータ x 機械学習の高速分析をVerticaで実現!by ヒューレット・パッ...
 
godo m
godo mgodo m
godo m
 
NoSQL/SQLデュアルインターフェースを備えた IoT向けデータベースGridDB - 強化された時系列データ管理・検索機能について -
NoSQL/SQLデュアルインターフェースを備えた IoT向けデータベースGridDB - 強化された時系列データ管理・検索機能について -NoSQL/SQLデュアルインターフェースを備えた IoT向けデータベースGridDB - 強化された時系列データ管理・検索機能について -
NoSQL/SQLデュアルインターフェースを備えた IoT向けデータベースGridDB - 強化された時系列データ管理・検索機能について -
 
自作仮想化基盤 「n0stack」の紹介
自作仮想化基盤 「n0stack」の紹介自作仮想化基盤 「n0stack」の紹介
自作仮想化基盤 「n0stack」の紹介
 

More from Yuki Nihei

サーバ・VM+コンテナ管理Tips@オンライン合宿2020
サーバ・VM+コンテナ管理Tips@オンライン合宿2020サーバ・VM+コンテナ管理Tips@オンライン合宿2020
サーバ・VM+コンテナ管理Tips@オンライン合宿2020
Yuki Nihei
 
オフライン簡易天候予測装置の開発
オフライン簡易天候予測装置の開発オフライン簡易天候予測装置の開発
オフライン簡易天候予測装置の開発
Yuki Nihei
 
データベースプログラミング演習 最終課題
データベースプログラミング演習 最終課題データベースプログラミング演習 最終課題
データベースプログラミング演習 最終課題
Yuki Nihei
 
楽曲検索システム
楽曲検索システム楽曲検索システム
楽曲検索システム
Yuki Nihei
 
BookRecommender 発表資料
BookRecommender 発表資料BookRecommender 発表資料
BookRecommender 発表資料
Yuki Nihei
 
enPiT学生発表2019 電機大(抜粋)
enPiT学生発表2019 電機大(抜粋)enPiT学生発表2019 電機大(抜粋)
enPiT学生発表2019 電機大(抜粋)
Yuki Nihei
 

More from Yuki Nihei (6)

サーバ・VM+コンテナ管理Tips@オンライン合宿2020
サーバ・VM+コンテナ管理Tips@オンライン合宿2020サーバ・VM+コンテナ管理Tips@オンライン合宿2020
サーバ・VM+コンテナ管理Tips@オンライン合宿2020
 
オフライン簡易天候予測装置の開発
オフライン簡易天候予測装置の開発オフライン簡易天候予測装置の開発
オフライン簡易天候予測装置の開発
 
データベースプログラミング演習 最終課題
データベースプログラミング演習 最終課題データベースプログラミング演習 最終課題
データベースプログラミング演習 最終課題
 
楽曲検索システム
楽曲検索システム楽曲検索システム
楽曲検索システム
 
BookRecommender 発表資料
BookRecommender 発表資料BookRecommender 発表資料
BookRecommender 発表資料
 
enPiT学生発表2019 電機大(抜粋)
enPiT学生発表2019 電機大(抜粋)enPiT学生発表2019 電機大(抜粋)
enPiT学生発表2019 電機大(抜粋)
 

IoTデバイス センサデータ分析システム

  • 2. 目次 1. 目的 .......................................................................................................................1 2. システム概要 .........................................................................................................1 3. センサの種類と型、アクチュエータの種類 ...........................................................2 • センサ ..................................................................................................................... 2 • アクチュエータ ....................................................................................................... 2 • 動作の様子 .............................................................................................................. 2 4. Arduino ソースコード............................................................................................3 5. Python 送信側コード .............................................................................................6 6. Node.js 受信側コード............................................................................................7 7. Python グラフ可視化コード...................................................................................8 8. 生成されるグラフの例 .........................................................................................10 9. 考察と今後の発展 ................................................................................................11 10. 苦労した点 .......................................................................................................11 11. 参考 URL..........................................................................................................12
  • 3. 1 1. 目的 本レポートは,Arduino を用いて得たセンサデータをクラウドに送信し,それらを グラフ化することによりセンサデータを可視化するための手法および結果を述べるこ とを目的とする. 2. システム概要 本システムは,図1に示すように,ローカル側とクラウド側で構成されている.ま ずローカルでは Arduino を用いて取得したセンサデータを PC 等の端末で受信し MQTT を用いて Cloud Pub/Sub に送信する 1) .そしてクラウド上では受け取ったデ ータを Cloud Functions 経由で Firestore に送信する 2),3) .また,蓄積されたデータは HTTP アクセスをトリガーとして閲覧することが可能となっている 4) . 今回は Firebase Hosting と Vue.js を用いて以下の閲覧用サイトを作成した. なお最新の画像および動作時の動画には以下の URL からアクセス可能である. https://spherical-voice-251409.firebaseapp.com/ (2020 年 4 月までアクセス可能であることを保証します) 図1 システムの概要
  • 4. 2 3. センサの種類と型、アクチュエータの種類 今回は IoTAB シールドに含まれている部品を使用したため,Arduino と距離センサ を接続したシールドのみで再現することが可能である. • センサ  温度センサ STS30 I2C 接続(アドレス: 0x4A)  照度センサ BH1780 I2C 接続(アドレス: 0x29)  加速度センサ MMA8452Q I2C 接続(アドレス: 0x1C)  距離センサ HC-SR04 デジタル入力/出力: D12/D13  可変抵抗器 3386K-EY5-103TR アナログ入力: A3 • アクチュエータ  LCD AQM0802A-RN-GBW I2C 接続(アドレス: 0x7C)  LED OSYG1608C1A デジタル出力: D3〜D8 • 動作の様子 Raspberry Pi は Wi-Fi でネットワークに接続できるため,モバイルバッテリーを 用いることにより完全な無線化が可能である. 図2 動作の様子 距離に応じて変化 温度と加速度 (x,y 軸)を表示 LED 変化の 大きさを変更 距離センサ 温度センサ シリアル通信
  • 5. 3 4. Arduino ソースコード //******************************************* //* センサネットワークと組み込み技術 最終課題 //* 2020/1 17FI552 二瓶雄貴 //******************************************* // I2C に必要 #include <Wire.h> // 温度センサに必要 #include <STSSensor.h> STSSensor sts30(Wire); // 定数の定義 #define ACCaddr 0x1C // 加速度センサ #define LightAddr 0x29 // 照度センサ #define echoPin 12 // Echo ピン #define trigPin 13 // Trigger ピン #define volPin 3 // 可変抵抗ピン // 変数の宣言と初期化 double Duration = 0; // 超音速を受信した間隔 int LEDLevel = 0; // LED で表せる距離の範囲 double Distance = 0; // 距離 double Temp = 0; // 温度 double TempOld = 0; // 過去の温度 int Light = 0; // 照度 int LightOld = 0; // 過去の照度 void setup() { Wire.begin(); lcd_init(); // 加速度センサの初期化 Wire.beginTransmission(ACCaddr); Wire.write(0x2A); Wire.write(0x00); Wire.endTransmission(); Wire.beginTransmission(ACCaddr); Wire.write(0x2A); Wire.write(0x01); Wire.endTransmission(); Wire.beginTransmission(ACCaddr); Wire.write(0x0E); Wire.write(0x00); // Set range to +/- 2g Wire.endTransmission(); delay(300);
  • 6. 4 // 温度センサの初期化 sts30.init(Wire); // 照度センサの初期化 Wire.beginTransmission(LightAddr); Wire.write(0x80); Wire.write(0x03); Wire.endTransmission(); Serial.begin(9600); // シリアル通信の初期化 pinMode(echoPin, INPUT); // Echo ピンを入力に設定 pinMode(trigPin, OUTPUT); // Trigger ピンを出力に設定 for(int i=3; i<9; i++) pinMode(i,OUTPUT); // LED を出力に設定 } void loop() { // 加速度センサからの入力を受け取る unsigned int accData[5]; Wire.requestFrom(ACCaddr, 5); // staus, xAccl lsb, xAccl msb, yAccl lsb, yAccl msb if(Wire.available() == 5) for (int i=0; i<5; i++) accData[i]= Wire.read(); // 加速度を変数に格納する int xAcc = accl(&accData[1]); int yAcc = accl(&accData[3]); //温度センサからの入力を受け取る sts30.readSample(); Temp = sts30.getTemperature(); // 照度センサからの入力を受け取る Light = i2c_readlux(); // 超音波を出力する digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds( 10 ); digitalWrite(trigPin, LOW); // 超音速センサからの入力を受け取る Duration = pulseIn(echoPin, HIGH); LEDLevel = analogRead(volPin)/32+1; // 距離によって LED を点灯させる if (Duration > 0) { Duration = Duration / 2; // 往復距離を半分にする Distance = Duration * 340 * 100 / 1000000; // 音速を 340m/s に設定
  • 7. 5 if (Distance <= 450) { // 測定可能距離は 450cm まで for(int i=0; i<6; i++) digitalWrite(i+3, (int)(Distance/LEDLevel)>i?HIGH:LOW); } } // 1 行目を生成 char tempbuf[6]; // 温度を格納する変数 // 小数はそのまま表示できないため一度文字列に変換 dtostrf(Temp, 5, 2, tempbuf); // %5.2f と同様の文字列を生成 // LCD 表示部 char pr[8]; // 1 行分を格納する変数 lcd_clear(); lcd_setCursor(0,0); // カーソルを 1 行目の先頭に sprintf(pr,"%s[C]",tempbuf); // 温度を表す文字列 lcd_printStr(pr); // 1 行分を表示 lcd_setCursor(0,1); // カーソルを 2 行目の先頭に sprintf(pr,"%4d%4d",xAcc/10,yAcc/10);// 加速度を表す文字列 lcd_printStr(pr); // 1 行分を表示 // データ送信部 if(abs(Temp - TempOld) > 0.5 || abs(Light - LightOld) > 5) { // 温度変化が 0.5 度を超えたか照度変化が 5Lx を超えたら writeSerial(Temp, Light); // センサデータを送信 TempOld = Temp; // 比較対象の温度を更新 LightOld = Light; // 比較対象の温度を更新 } delay(300); // 1 秒待機 } // センサデータを送信する関数 void writeSerial(double temp, int light) { Serial.write("STARTn"); char buf[1]; String str; str = (temp != -1 ? String(temp) : "") + "n"; str += (light != -1 ? String(light) : "") + "n"; str.toCharArray(buf, str.length() + 1); Serial.write(buf); Serial.write("ENDn"); } // 加速度を変換する関数 int accl(int d[]) {
  • 8. 6 int val = ((d[0]*256+d[1]))/16; if (val > 2047) val -= 4096; return val; } // 照度を読み取る関数 uint16_t i2c_readlux() { uint16_t val; Wire.beginTransmission(LightAddr); Wire.write(0x8D); Wire.endTransmission(); Wire.beginTransmission(LightAddr); Wire.requestFrom(LightAddr,2); delay(150); val = Wire.read(); Wire.endTransmission(); val <<=8; Wire.beginTransmission(LightAddr); Wire.write(0x8C); Wire.endTransmission(); Wire.beginTransmission(LightAddr); Wire.requestFrom(LightAddr,2); delay(150); val |= Wire.read(); Wire.endTransmission(); return val; } LCD の制御に必要なライブラリを https://github.com/JanStegenga/Arduino-STS-lib からダウンロードしインストールする必要がある. 5. Python 送信側コード 実行するためには,pip を用いた pyserial と google-cloud-pubsub のインストールが 必要である.また,認証情報を格納した json ファイルへのパスを環境変数 GOOGLE_APPLICATION_CREDENTIALS に格納しておく必要がある. # Arduino からセンサの値を受け取って Google Cloud Pub/Sub に MQTT で送信する プログラム # 2020/1 17FI552 二瓶雄貴 import serial from google.cloud import pubsub_v1 # パブリッシャーの設定 publisher = pubsub_v1.PublisherClient() # トピックの設定
  • 9. 7 project_id = 'spherical-voice-251409' topic_name = 'iot-sensor-data' topic_path = publisher.topic_path(project_id, topic_name) if __name__ == "__main__": # Arduino の接続ポートを書く ser = serial.Serial("/dev/cu.usbmodem14201", 9600) data = [] flag = False while True: message = ser.readline().decode("utf-8").replace("n", "") if message == "START": flag = True elif message == "END": flag = False # データをバイト列にエンコードして送信 future = publisher.publish(topic_path, ",".join(data).encode("utf-8")) # print(future.result()) data = [] else: if flag: print(message) data.append(message) 6. Node.js 受信側コード Cloud Functions 上の Node.js 8 以上でのみ動作するコードが含まれている. index.js /** * Triggered from a message on a Cloud Pub/Sub topic. * * @param {!Object} data Message on a topic. * @param {!Object} context Metadata for the event. */ const functions = require('firebase-functions') // cloud function で firestore を使うのに必要な設定は以下の2行 const admin = require('firebase-admin') admin.initializeApp(functions.config().firebase)
  • 10. 8 // データベースの参照を作成 var db = admin.firestore() exports.subscribe = (data, context) => { var message = Buffer.from(data.data, 'base64').toString(); // console.log("Message: ", message); var docRef = db.collection('record'); docRef.add({ "timestamp": parseInt(Date.now()/1000), "temp": message }); }; package.json { "name": "iot2firestore", "version": "1.0.0", "dependencies": { "@google-cloud/firestore": "^0.16.1", "firebase-admin": "^6.0.0", "firebase-functions": "^1.0.0" } } 7. Python グラフ可視化コード Cloud Functions 以外での実行には認証情報が必要である. main.py from flask import make_response import datetime import operator import matplotlib.pyplot as plt from matplotlib import rcParams from matplotlib.backends.backend_agg import FigureCanvasAgg from google.cloud import firestore from io import BytesIO def make_graph(request): # フォントの設定
  • 11. 9 rcParams['font.family'] = 'sans-serif' rcParams['font.sans-serif'] = ['Noto Sans CJK JP', 'Hiragino Sans', 'Hiragino Maru Gothic Pro', 'Yu Gothic'] # 最新 20 件のコレクション取得 db = firestore.Client() query = db.collection(u'record').order_by(u'timestamp',direction=firestore.Query.D ESCENDING).limit(20) results = query.stream() # データを取得する lists = {} for result in results: res = result.to_dict() lists[datetime.datetime.fromtimestamp(res['timestamp'], datetime.timezone(datetime.timedelta(hours=9)))] = (float(res['temp']) , int(res['light'])) # 時刻順に並び替える lists = sorted(lists.items()) # グラフ生成 fig, ax = plt.subplots() ax.set_title(u'センサデータ') # リストからデータを抽出 x = list(map(operator.itemgetter(0), lists)) y = list(map(operator.itemgetter(1), lists)) # y 軸のデータを分割しプロット y1 = list(map(operator.itemgetter(0), y)) ax.plot(x, y1, label='温度 [℃]', color='b', linewidth=2) y2 = list(map(operator.itemgetter(1), y)) ax.plot(x, y2, label='輝度 [Lx]', color='r', linewidth=2) # 凡例の位置を自動で変更 plt.legend(loc='best') # 軸ラベルの設定 plt.xlabel('時刻') # x 軸を回転させる plt.xticks(rotation=70) # 余白を調整 plt.subplots_adjust(left=0.07, right=0.97, bottom=0.21, top=0.93) # グリッドを設定 plt.grid() # グラフの画像を生成
  • 12. 10 canvas = FigureCanvasAgg(fig) buf = BytesIO() canvas.print_png(buf) data = buf.getvalue() # HTTP レスポンスを生成 response = make_response(data) response.headers['Content-Type'] = 'image/png' response.headers['Content-Length'] = len(data) # キャッシュ設定 ブラウザごとに 5 分,CDN に 10 分 response.headers['Cache-Control'] = 'public, max-age=300, s- maxage=600' return response requirements.txt matplotlib google-cloud-firestore 8. 生成されるグラフの例 7.で示したコードにより図3に示すようなグラフが生成される.今回はセンサを屋 内の窓際に設置した.日射により温度と輝度が変化している. 図3 センサデータを元に生成されたグラフ
  • 13. 11 9. 考察と今後の発展 今回製作したシステムにより,IoT 機器を用いて取得したセンサデータをクラウド 上にアップロードし管理することにより遠隔地の環境をリアルタイムに確認すること が出来た. 今後,更なるユビキタスセンサーネットワーク技術や機械学習技術の発達により継 続的に複数地点の遠隔監視を行うことができ,一般家庭から収集したセンサデータ をビックデータとして機械学習を用いて統計処理することにより様々な関連性を見出 すことができ,産業の発展やネットワーク機器の利便性向上に貢献することが期待で きる. 10. 苦労した点 • IoTAB シールドのサンプルファイルを用いて温度センサの値を取得しようとした が2つの問題があった.  STS ライブラリが別途必要だったためインストールした.  サンプルファイルには一向に新しいデータに更新されない問題があり,STS ライブラリのページを参照すると sht.readSample();を都度実行する必要があ るとの記述があった 5) ため実行することにより解決した. • Raspberry Pi における google-cloud-pubsub のセットアップ時に grpcio のビルドが 永遠に終わらない問題があったためビルド済みのバイナリをインストールした 6) . • Cloud Functions の Node.js のバージョンの違いにより関数の記述方法が変わって おりエラーの特定に数時間を要した 7) . • Cloud Forestore の設定画面から取得したサービスアカウントの秘密鍵(JSON フ ァイル)には type 属性などの必要な属性が含まれていなかったため動作せず, Cloud Console の IAM 管理画面から秘密鍵をダウンロードする必要があった. • ローカルでは Python を用い,Cloud Functions では Node.js を用いており,ローカ ルとクラウド上での言語の違いやサービスアカウントの認証方法の違い(Cloud Functions では認証情報を簡単に取得できる)があった. • Python で作成したグラフを Firebase Hosting を用いて表示させるために Cloud Functions を用いて生成したファイルを Cloud Storage に格納する方法を模索して いたが,5時間ほどかけても解決できなかったために JavaScript を用いて実現する こととした. • その後二日間を要したが最終的には HTTP リクエストにより Python を用いたグ ラフを生成させることに成功した 4),8) .特にリスト型と辞書型,タプル型の変換に 苦労した.
  • 14. 12 11. 参考 URL 1) 「クイックスタート: Pub/Sub システム機能の構築」 https://cloud.google.com/pubsub/docs/quickstart-py-mac?hl=ja 2) 「Firebase を使って IoT データをリアルタイム可視化する」 https://camp.isaax.io/ja/examples/firebase-realtime-visualization 3) 「IoT Core から Cloud Functions 経由で Firestore にデータを追加する」 https://qiita.com/bathtimefish/items/1f4885c130d23eb63710 4) 「Google Cloud Functions の HTTP トリガーで matplotlib を使って生成した 画像を返す」 https://qiita.com/tanabee/items/2bfee85f9659be097750 5) 「GitHub - JanStegenga/Arduino-STS-lib」 https://github.com/JanStegenga/Arduino-STS-lib#integrating-it-into-your-sketch 6) 「Google Cloud IoT Core の環境構築ではまったところ(デバイス側) 」 http://chinoppy.hatenablog.com/entry/2019/01/06/190530 7) 「Cloud Functions の nodejs6 を nodejs8 に移行するとき、バックグラウンド関数 を使っているときは引数を修正する」 https://qiita.com/itatibs/items/5540c0ac94582ab4851e 8) 「Cloud Firestore のデータを Python で取得する」 https://qiita.com/yusukeito58/items/c77feaa25fbbe37e9953