ちなみに、Edison Intelに乗せる前にArduinoで超音波距離センサモジュールHC-SR04を使って人がある範囲を通過したらカウントするというデバイスを作ってみたの続き。
Edison用のOSの選択肢は幾つかあるが、Webサーバーが最低限動けば良いので、nodejsが標準搭載されているYoctoを使うことにする。セットアップはIntel Edison How toも参考になる。
前提
- Edisonのセットアップが済んでいること (参考ページ)(時間合わせ)
- Yocotのセットアップが完了していること (参考ページ)
- Wifiの設定が終わっていること (参考ページ)
- Intel® XDK IoT Editionの準備が終わっていること (参考ページ)(使わなくても良いが、一応)
準備
nodejsがデフォルトで準備されているのでそれを使うことにする。libmraa
も使うことになるのでopkg
を使ってまずはパッケージのアップデートを行う。Update libraries on Edisonに従ってやってみる。
Edisonの設定
- configure_edisonで行う
$ configure_edison --help
Wifiの確認
$ ifconfig
ifconfig | grep -A1 wlan0
wlan0 Link encap:Ethernet HWaddr 78:4b:87:a7:86:eb
inet addr:192.168.10.17 Bcast:192.168.10.255 Mask:255.255.255.0
192.168.10.17にブラウザーで接続してみる。うまくいかない場合、以下をしてみると良いらしい。こんな感じで表示された。
パッケージのアップデート
# as a root
$ echo "src intel-iotdk http://iotdk.intel.com/repos/1.1/intelgalactic" > /etc/opkg/intel-iotdk.conf
$ opkg update
$ opkg upgrade
XDKの準備
接続する予定のIPを追加
$ xdk-whitelist --add 192.168.10.14 # 同一ネットワーク内の自宅PCIP
うまく接続できない場合以下をやってみると良いらしい
$ systemctl enable xdk-daemon
$ systemctl restart xdk-daemon
XDKからアップしたプロジェクトはedisonの以下に格納される
$ ls /node_app_slot
直接サーバー上でごにょごにょしてもよい
mraaの準備
- MRAA Github Repository: https://github.com/intel-iot-devkit/mraa
$ echo "src mraa-upm http://iotdk.intel.com/repos/1.1/intelgalactic" > /etc/opkg/mraa-upm.conf
$ opkg update
$ opkg install libmraa0
johnny-five
入れなくても良いが試しに入れてみた
- johnny-five https://www.npmjs.com/package/johnny-five
- この辺りも参考になるのかな https://github.com/rwaldron/galileo-io/
インストール
$ npm install johnny-five
export NODE_PATHをして、NODE_PATHにjohnny-fiveのnode_moduleを追加しておく
$ echo $NODE_PATH
/usr/lib/node_modules/:/home/root/.node_app_slot/node_modules/johnny-five/node_modules/
LED Blinkテスト
var five = require("johnny-five");
var Edison = require("galileo-io");
var board = new five.Board({
io: new Edison()
});
board.on("ready", function() {
var led = new five.Led(13);
led.blink();
});
実行
$ node blink_test.js
正しくブリンクすればOK。
センサーのドキュメント
ドキュメントがあったので一応目を通してみた。10us(microseconds)TTLをシグナルピンに投げると、センサーが8回 40kHz Pulse投げてecho back受けるっぽい。当然ながらドキュメントに色々と情報あることを学んだ。
The timing diagram of HC-SR04 is shown. To start measurement, Trig of SR04 must receive a pulse of high (5V) for at least 10us, this will initiate the sensor will transmit out 8 cycle of ultrasonic burst at 40kHz and wait for the reflected ultrasonic burst. When the sensor detected ultrasonic from receiver, it will set the Echo pin to high (5V) and delay for a period (width) which proportion to distance. To obtain the distance, measure the width (Ton) of Echo pin.
Time = Width of Echo pulse, in uS (micro second)
Distance in centimeters = Time / 58
Distance in inches = Time / 148
Or you can utilize the speed of sound, which is 340m/s
hc_sr04 javascript版サンプルソース
microsecondsをインストールしておく
$ npm install microseconds
とりあえず自分の書いたArduino版ソースを参考にやっつけで書いてみた。最初pulseIn
をどう表現するか迷ったがなんとかいけたっぽい。ただ、センサーの情報が時々期待通り帰ってこなかったりする。
多分、物理的な問題があるのだろう。オーバーヘッドがあったりするのかな。専門じゃないからわからないけど、microsecondsモジュールのおかげでなんとか動いている感じ。
johnny-fiveでもやってみたが、イマイチうまく動かなかったのと、mraaの方がArduinoからのソースを書き換えるだけで済むのでmraaを使うことにした。
var m = require('mraa');
var μs = require('microseconds');
var echoPin = new m.Gpio(12);
var trigPin = new m.Gpio(11);
var LEDPin = new m.Gpio(13);
var defaultDistance = 0; // centimètre
var prevDistance = 0;
var counter = 0;
var adjustment = 3; // centimètre
var lock = false;
var maximumRange = 500; // Maximum range needed
var minimumRange = 3; // Minimum range needed
var unlockReadyCounter = 0;
var unlockReadyCounterAdjusment = 0;
var loopDelay = 60; // ms
var LOW = 0;
var HIGH = 0;
trigPin.dir(m.DIR_OUT);
echoPin.dir(m.DIR_IN);
LEDPin.dir(m.DIR_OUT);
LEDBlink(3);
// sleep microseconds
function usleep(us) {
start = μs.now();
while (true) {
if (μs.since(start) > us) {
return;
}
}
}
function lockCounter() {
LEDPin.write(LOW);
unlockReadyCounter = 0;
lock = true;
}
function unlockCounter() {
if (unlockReadyCounter > unlockReadyCounterAdjusment) {
LEDPin.write(HIGH);
unlockReadyCounter = 0;
lock = false;
} else {
unlockReadyCounter++;
}
}
function LEDBlink(c) {
for (var i = 0; i < c; i++) {
LEDPin.write(HIGH);
usleep(50000); // 50ms
LEDPin.write(LOW);
}
}
function init() {
lock = true;
defaultDistance = 0;
prevDistance = 0;
unlockReadyCounter = 0;
//counter = 0;
}
setInterval(function(){
var pulseOn, pulseOff;
var duration, distance;
trigPin.write(HIGH);
usleep(2);
trigPin.write(HIGH);
usleep(10);
trigPin.write(LOW);
while (echoPin.read() == 0) {
pulseOff = μs.now();
}
while (echoPin.read() == 1) {
pulseOn = μs.now();
}
duration = pulseOn - pulseOff;
distance = parseInt(duration / 58.2);
if (
!distance ||
(!defaultDistance && prevDistance > 0)
) {
init();
defaultDistance = distance;
console.log("defaultDistance: " + defaultDistance + "cm.");
LEDBlink(2);
} else if (
distance >= maximumRange ||
distance <= minimumRange ||
defaultDistance <= distance ||
defaultDistance > prevDistance
) { // lock condtion
lockCounter();
} else if (
(defaultDistance - adjustment) > distance
) { // unlock condtion
unlockCounter();
console.log("unlockReadyCounter: " + unlockReadyCounter + " count.");
console.log(" -> Distance: " + distance + "cm.");
}
if (lock == false) {
LEDBlink(1);
lockCounter();
counter++;
console.log("Counter: " + counter + ".");
console.log(" -> Distance: " + distance + "cm.");
}
if (distance && unlockReadyCounter == 0) {
prevDistance = distance;
}
}, loopDelay);
感想
後は、nodeのexpressを入れてリアルタイムでカウンターを見えるようにするとか、若干のコントロールする機能を入れるとかしたらよいのかな?以外と簡単にできた。
おもちゃレベルかもしれないが、こんなにサクサクできるなんて素敵。それと、簡単にインターネットにも繋がるし可能性が広がる。IoT!
趣味として楽しむにはいい感じかも。
今度は、慣れたPythonを使ってAWSにもつないでみようかな。で、PyCon JPのポスターセッションとかで何かやれたらいのかなぁ。もっとハードに詳しい人に教えてもらいたい。