JavaScript
Node.js
IoT
Edison

ミニ四駆でIoTをやってみた

More than 1 year has passed since last update.


自己紹介


名前

加納 聖大

会社

NCデザイン&コンサルティング株式会社

やってること



  • Webアプリ

  • インフラ構築、運用



趣味



  • PCゲーム

  • 自宅サーバー

  • いろんな技術で遊んでみること



Twitter: @karuru6225



自己紹介


名前

十川 亮平

会社

NCデザイン&コンサルティング株式会社

やってること



  • AppPotというバックエンドサービスのプロダクトマネージャ

  • 今回のデモではサーバーサイドを担当しています



Twitter: @rsogo

Twitter: @app_pot



NCDCの紹介

ncdc.png



伊勢丹百貨店さま「MyIsetan、My三越」

isetan.png



その他事例

15665605_10154284654272810_9210138522031466545_n.jpg 15665698_10154284654367810_7436219989809742873_n.jpg


写真 2015-10-19 21 52 26.jpg



AppPotとは

apppot1.png



AppPotのアーキテクチャ

apppot2.png



IoTやAIの事例


某建設会社さま

建設機器のデータを自動でクラウドにアップ。

管理書類を自動でつくる。改ざんや、入力ミスの防止。

研究テーマとして、施工の結果がOKなのかNGなのかをDeep Learningで判定しようとしている。


IoTや機械学習で会社のルールや業務を変える


  • 曖昧になっていたものが見えるようになる。


    • これまでより多くの品質検査NGがでるようになるかも知れない・・・。現場のマネージャは結構悩んでいる

    • 一方、今まで分からなかったので過剰に余裕を持っていたものを最適化





これらの案件から言えること1


業務フロー(UXと言っても良い)に着目して、業務フローを改善するパターン


  • これまで人が入力していた業務を、Thingが勝手に連携してくれる

  • 人が考えてやっていた業務を、MLが勝手にやってくれる



これらの案件から言えること2


これまではできなかったことを物量とCPUパワーでなんとかして実現する


  • GE Predix

    機器のさまざまな情報を収集。故障実績と、その時、機器から収集していたデータを元に学習して、故障を予知。
    Cloud-based Platform-as-a-Service (PaaS) | Predix.io 2016-12-22 14-45-18.png



ミニ四駆デモの構成

展示会_2016秋_ミニ四駆展示A3パネル_Fix.pdf(1ページ) 2016-12-22 08-44-46.png



サーバー側をもっと詳しく(AppPot IoT)

IoT.png

いろんなIaaSや、オンプレミスで動作するようなミドルウェア選定をしています。


  • ActiveMQ: MQTTを受信する

  • Javaプログラム: 端末認証、端末の記録

  • Kafka: メッセージをトピックとしてPublish

  • Fluentd:


    • Kafka Consumer: Kafkaからのメッセージ取得

    • fluent-plugin-mysql



  • MySQL: 今回は。実際はなんでもいい。



はじまり

飲みながら話をしたときのアイデア


  • (ミニ四駆の)バッテリー残量を見る


    • 電圧測ればいける?




  • F1の実況中継みたいな、加速度計があったらかっこいい?


    • 加速度計



  • ラップ数、ラップタイム


    • ジャイロで一周したことを測る?

    • コースに黒いテープを貼り付けて、そこを通過したら一周とする?

    • フォトリフレクタの電圧をバッテリ残量のための電圧計で測ればいいか。



  • モーターの温度とか測りたい


    • 温度計





マイコンボードの選定

目的は、弊社製品の AppPot IoT のアピールだったので、以下のような条件を満たすマイコンが必要だった。


  • インターネットに繋げられ、データの送信ができる

  • センサーの情報取得できる

  • ミニ四駆に載せられる

  • (できれば)Node.jsでI2C通信でセンサーデータを取得できる


    • Web系エンジニアで、過去に既にやったことが有った。

      写真 2016-12-21 13 57 23.jpeg





マイコンボードの比較

ボード名
インターネット
ミニ四駆に載る?
Node.js

Arduino
1


×

Raspberry Pi


IntelEdison


写真 2016-12-21 14 33 33.jpg



部品購入 (10/7)


  • Intel Edison Breakout Board Kit

  • MPU-6050搭載 三軸加速度三軸ジャイロセンサモジュール

  • ADS1015搭載 12BitADC 4CH 可変ゲインアンプ付き

  • LiPo 燃料ゲージ

  • QRE1113 フォトリフレクタ・モジュール

  • TMP007 非接触温度センサ

  • リチウムイオン電池900mAh




センサーからのデータ取得

各種センサーとの通信はI2C通信で行い、

得られたデータを色々処理すると、各種センサーのデータが得られる。

2016-12-21 22-33-01.png

各種センサーは固有のアドレスを持っており、読み書きに先立って、対象のアドレスをi2c通信経路に送出する。



動かしてみる

早速各種ハンダ付けし、回路をブレッドボードで組み立て

Raspberry Piの方のコードを改造し動かしてみる

写真 2016-10-08 17 22 19.jpg 写真 2016-10-11 9 05 34.jpg

・・・が、Intel EdisonではNode.jsのI2Cライブラリが動かない

→ どうやらEdisonでは、mraaというライブラリで、各種通信を行うらしい。



mraaをインストー・・・

ビルドでコケてできない。


いろいろ調べた所、Edisonに入っている

ファームウェア(Linuxディストリ:Edison Yocto)の

バージョンが古いせいだった。

→ Yoctoを最新版に



ファームウェアのアップデート

J3にUSB MicroBを接続(シリアル接続)

J16にもUSB MicroBを接続(充電&その他接続)
iot-devkit-prof-dev-image-edison-20160606.zip をダウンロード&解凍


MacのTerminal

$ sudo brew install dfu-util coreutils gnu-getopt

$ cd iot-devkit-prof-dev-image-edison-20160606
$ sudo cu -s 115200 -l /dev/cu.usbserial-A502OQ0D
$ sudo ./flashall.sh

写真 2016-10-08 15 36 41.jpg



Bluetoothテザリングの設定


  • 展示会場で使うことを踏まえ、Wifiでなく、Bluetoothデザリングをする

Bluetoothのペアリング


Edisonにログインした後

$ systemctl start connman

$ systemctl enable connman
$ rfkill unblock bluetooth
$ bluetoothctl
[bluetooth]# scan on
[bluetooth]# discoverable on
[bluetooth]# devices
[bluetooth]# pair AB:CD:EF:01:23:45
[bluetooth]# exit

接続&自動接続の設定

$ connmanctl

[connmanctl]# services
[connmanctl]# connect bluetooth_5fed432cba10_abcdef012345
[connmanctl]# config bluetooth_5fed432cba10_abcdef012345 autoconnect yes
[connmanctl]# exit
$ reboot


全体の構成



ここからのミニ四駆に乗せるまでの流れ

Node.jsのインストール

while(うまく動くまで) {

 ・ ブレッドボードで回路を試作,修正

 ・ JavaScriptのコード作成

}

走行テスト



ブレッドボードで試作

基本的には、どの機器も電源と、I2C通信用の2つの回路を繋げるだけ。

写真 2016-10-12 7 33 07.jpg



JavaScript

せっかくなので、babel & webpack & gulpを使ったナウでヤングな環境で作る


babel.png webpack.png gulp.png


webpack.config.js

const webpack = require('webpack');

const env = process.env.NODE_ENV;

const webpackConfig = {
entry: {
index: './src/index.js'
},
output: {
filename: '[name].js',
libraryTarget: 'umd'
},
resolve: {
extensions: ['', '.js']
},
plugins: [],
target: 'node',
externals: [
/^(?!^\.\/)/,
/config\.js/
],
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
'presets':['es2015']
}
},
{ // ここ重要。mraaのバイナリを読むために必要
test: /\.node$/,
loader: 'node-loader'
}
]
},
node: {
fs: 'empty'
}
};

if(env == 'production'){
webpackConfig['plugins'].push(
new webpack.optimize.UglifyJsPlugin({
compress: { warnings: false }
})
);
}else{
webpackConfig['devtool'] = '#source-map';
}

module.exports = webpackConfig;



gulpfile.js

const gulp = require('gulp');

const plumber = require('gulp-plumber');
const watch = require('gulp-watch');
const del = require('del');
const webpack = require('webpack-stream');
const webpackConfig = require('./webpack.config.js');

const distDir = './dist/';

gulp.task('clean-js', ()=>{
return del([
distDir + '**/*'
]);
});

gulp.task('copy-js', ['clean-js'], ()=>{
return gulp.src([
'./src/config.js'
])
.pipe(plumber())
.pipe(gulp.dest(distDir))
});

gulp.task('compile', ['copy-js'], ()=>{
return gulp.src([
'./src/**/*.js'
])
.pipe(plumber())
.pipe(webpack(webpackConfig))
.pipe(gulp.dest(distDir));
});

gulp.task('build', ['compile']);

gulp.task('watch', ['build'], ()=>{
watch([
'./src/**/*.js'
], ()=>{
gulp.start('compile');
});
});



C言語やArduionのコードは落ちているが、JavaScriptのコードなんてどこ探しても全然ない!

→ 各センサーのデータシート(加速度計)や、C言語、Arduinoのサンプルコードを見つつ実装していく。



センサーデータの読み書き

各種センサーはレジスタを持っていて、設定や測定結果が格納されている。

大まかには以下のような手順でセンサーデータを得る

1. 設定のレジスタに設定を書き込む

2. 測定結果のレジスタから生データを取り出す

3. データシートの記述に従い、生データを加工して測定データを算出する



JavaScriptのデータ型

ローレベルなデータを扱うとやはりデータの型が必要になってくる

Bufferを使う。

    const raw = this._i2c.readBytes(0x3b, 14);

return {
ax: new Buffer([raw[0], raw[1]] ).readInt16BE(0) * this._accelMagni + this._e.ax,
ay: new Buffer([raw[2], raw[3]] ).readInt16BE(0) * this._accelMagni + this._e.ay,
az: new Buffer([raw[4], raw[5]] ).readInt16BE(0) * this._accelMagni + this._e.az,
gx: new Buffer([raw[8], raw[9]] ).readInt16BE(0) * this._gyroMagni + this._e.gx,
gy: new Buffer([raw[10], raw[11]]).readInt16BE(0) * this._gyroMagni + this._e.gy,
gz: new Buffer([raw[12], raw[13]]).readInt16BE(0) * this._gyroMagni + this._e.gz
};



実装

ここまでである程度動作するコード、回路が完成したので、

ブレッドボードの回路を参考にユニバーサル基板に色々はんだ付け

写真 2016-10-20 0 21 22.jpg 写真 2016-10-19 20 37 57.jpg



走行テスト (10/21 12:0016:31 〜 18:30)

実際にコースで走らせ、パーツの配置を直したり、回路を修正したり、コードを直したり・・・

IMG_20161021_164056.jpg IMG_20161021_181321.jpg



何かが悪い?

走行テスト動かしてみる

→ うまく動いたり動かなかったり・・・

いくら見直してもコードも合ってそうだし、センサーはこわれてないと思う?

回路も最低限のもので検証し、合ってるはず・・・



EdisonのIO

EdisonのI2C通信を含む、外部接続は、1.8V基準になっており、

外部機器は3.3vで動作させている

→ 電圧が合ってない

EdisonのI2C通信の設定を変更し、対応。



プルプルプル

プルアップ

プルダウン



I2C通信再び


  • I2C通信では、通信経路をプルアップすることが規格で定められている(電圧は決まってない)。

  • Edison側、センサー側両方でプルアップがされていた。

→ Edisonの設定は、デフォルトpullupで、pullup、pulldown、nopullの設定が可能。

→ I2Cのポートの設定を pullup -> nopullへ


i2cのnopull設定

echo "nopull" > /sys/kernel/debug/gpio_debug/gpio27/current_pullmode # i2c-6 scl

echo "nopull" > /sys/kernel/debug/gpio_debug/gpio28/current_pullmode # i2c-6 sda

2016-12-22 08-39-17.png



まさか?の故障

どこかがショートしたのか、Edisonが起動しなくなる。

写真 2016-10-20 0 21 22.jpg 写真 2016-12-22 13 59 40.jpg



2代目回路

電池の電圧を測るセンサーと、加速度計が同時に動作させられなかったので、

フォトリフレクタの結果を取得するために コンパレーター を導入。



フォトリフレクタ?

ラップ数やラップタイムを取得するために購入したセンサー

センサーから赤外線が出ており、反射光の強さに応じて、出力される電圧が変化する。

写真 2016-12-22 16 12 12.jpg



コンパレーター?

2つの電圧を比較して、一方の方が大きかったら、電源電圧。小さかったら0vを出力する素子。

2016-12-22 14-31-57.png



コンパレーター

2代目では、片方に半固定抵抗2の出力を入力し、もう片方にフォトリフレクタの出力を入力。

2016-12-22 14-49-34.png 写真 2016-12-22 14 53 37.jpg



フォトリフレクタのデータを取得

コンパレーターからはデジタルな出力が得られるので、それをGPIOに入力。

(反射光が一定以上になったら、0になる)

GPIOの結果をmraaで取得し、ラップのカウントを送信。

GPIOの変化から、一周したと判断したら、その時刻を送信。



2代目回路の設計。

1代目はブレッドボードの試作を目で見て、行き当たりばったりで配線をしていた。

Excel方眼紙を作成し、適当な配線図を設計。

2016-12-22 14-17-19.png



2回目走行テスト (10/24 18:30 〜 23:00)

2代目回路も無事完成し、走行テストをしつつ、半固定抵抗の抵抗値や、コード中の各種パラメーターを調整。

写真 2016-12-22 14 38 51.jpg 写真 2016-12-22 15 05 40.jpg

ようやく通して動いた!



展示会場でテスト (10/25 15:00 〜 )

幕張メッセで展示会前日テスト。

IMG_20161025_194211.jpg

バッテリーのコネクタが緩む、などの問題も発生したが、なんとか展示にこぎつけた。



コードの説明

コードはgithubのリポジトリで公開しています。



MQTTとは

MQTTとは、小さなメッセージを非同期でやりとりするための所謂メッセージ・キューの仕組みの一つ。

軽量なプロトコルでさまざまな機器で対応できるのが特徴。


MQTTブローカーの比較

mqtt-broker.png



Fluentdを使って任意の分析基盤にデータ連携

機器から取得した生データから、ビジネス的に意味のある値を得る必要がある。

RedShiftやHadoopのようなBigData系の分析基盤に流し込んでもいいし、

機械学習系の基盤に流し込むこともできる。


例えば・・・

荷物を収集する車から積載量や位置情報を収集する。

分析基盤で、積載量がある一定の条件を超えたら、位置情報や荷物の量から時間や料金が最適になるトラックを呼んで、持っていってもらう。



サーバー側をもっと詳しく(バックエンドサービスAppPot)

AppPot.png


  • JavaScript SDK

  • ユーザー認証

  • Databaseのテーブル作成とデータアクセス

PushやFile APIなどさまざまな機能がありますが、今回使っているのはこれだけ。



まとめ。


  • Web系エンジニアでも、なんとかIoTっぽいことができる(ハード含めて)

  • IoTのPoCするときでも、自分たちでなんとか作れる!

  • ミニ四駆IoTくらいのものなら、2週間半(実業務をしながら)で、作れる!



3代目

依頼を受け、3代目の回路を設計&製作中。

Eagleというソフトウェアを使用し、回路設計。

2016-12-22 15-20-10.png 2016-12-22 15-20-29.png

P板.com にプリント基板を発注中。



購入品目リスト


スイッチサイエンス


  • Intel Edison Breakout Board Kit

  • MPU-6050搭載 三軸加速度三軸ジャイロセンサモジュール

  • ADS1015搭載 12BitADC 4CH 可変ゲインアンプ付き

  • LiPo 燃料ゲージ

  • QRE1113 フォトリフレクタ・モジュール

  • TMP007 非接触温度センサ

  • リチウムイオン電池900mAh


秋月電子通商


  • 2回路入コンパレータ NJM2903D (5個入)1パック

  • 半固定ボリューム 3362P 10kΩ

  • ロープロファイルピンヘッダ 2×14(28P) 9.54mm

  • ロープロファイルピンソケット (低メス) 2×14 (28P) 5.0mm





  1. Arduino YÚN miniというものならネットもNode.jsもOKだったらしい 



  2. 抵抗値を調節して、電源電圧〜0Vの間の任意の電圧を出力できるもの