LoginSignup
7
7

More than 5 years have passed since last update.

Edison+Arduino上で超音波距離センサモジュールHC-SR04をnodejsとmraaを使って動かしてみる

Last updated at Posted at 2015-02-24

こんな感じになる
IMG_0518.jpg

ちなみに、Edison Intelに乗せる前にArduinoで超音波距離センサモジュールHC-SR04を使って人がある範囲を通過したらカウントするというデバイスを作ってみたの続き。

Edison用のOSの選択肢は幾つかあるが、Webサーバーが最低限動けば良いので、nodejsが標準搭載されているYoctoを使うことにする。セットアップはIntel Edison How toも参考になる。

前提

準備

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にブラウザーで接続してみる。うまくいかない場合、以下をしてみると良いらしい。こんな感じで表示された。

Screen Shot 2015-02-22 at 4.09.44 PM.png

パッケージのアップデート

# 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の準備

$ echo "src mraa-upm http://iotdk.intel.com/repos/1.1/intelgalactic" > /etc/opkg/mraa-upm.conf
$ opkg update
$ opkg install libmraa0

johnny-five

入れなくても良いが試しに入れてみた

インストール

$ 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テスト

blink_test.js
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

Screen Shot 2015-02-23 at 12.01.38 AM.png

hc_sr04 javascript版サンプルソース

microsecondsをインストールしておく

$ npm install microseconds

とりあえず自分の書いたArduino版ソースを参考にやっつけで書いてみた。最初pulseInをどう表現するか迷ったがなんとかいけたっぽい。ただ、センサーの情報が時々期待通り帰ってこなかったりする。

多分、物理的な問題があるのだろう。オーバーヘッドがあったりするのかな。専門じゃないからわからないけど、microsecondsモジュールのおかげでなんとか動いている感じ。

johnny-fiveでもやってみたが、イマイチうまく動かなかったのと、mraaの方がArduinoからのソースを書き換えるだけで済むのでmraaを使うことにした。

hc_sr04.js
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のポスターセッションとかで何かやれたらいのかなぁ。もっとハードに詳しい人に教えてもらいたい。

7
7
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7