yutaponのブログ

javascript界隈の興味あるネタを備忘録的に残しておく場所

Arduinode使ってNode.jsからフルカラーLEDを制御してみる

Arduinoの教本に必ず載っているフルカラーLEDの制御。
それをNode.js経由でやってみます。

ArduinoとNode.jsの間にはArduinodeというライブラリを使いました。
mironal/arduinode · GitHub
作者さまに感謝です。

Arduinoの回路を組んでLEDを点灯させる

おおまかに言うと、

  • フルカラーLED x1(端子が4つあるやつ)
  • 抵抗 x3
  • ジャンパーケーブル x4
  • ブレッドボード

が必要です。

Amazonで購入したArduinoエントリーキットにはアノードコモンの
フルカラーLEDが付属しており、抵抗も510Ωを3つ使えば回路が組めました。
でも今回は秋月電子で買ったフルカラーLEDを試します。

このOST A5131 A-R/PG/BというフルカラーLEDはカソードコモンで、
教本通りに配線しても点灯せず苦労しました。
それでLEDに付属したデータシートから抵抗値がおかしいということがわかり、
赤330Ω、緑100Ω、青100Ωにしたところ正常に点きました。
(本来は赤300Ω、緑133Ω、青75Ωが適正らしいです。)

以下は動作確認のためのArduinoスケッチです。
ランダムな色でだんだん明るくなっていき、だんだん暗くなるという動作をします。

#define FADE_TIME 10

int led_pins[] = { 9, 10, 11 };

void setup() {
  int i;
  
  randomSeed(analogRead(0));
  
  for (i = 0; i < 3; i++) {
    pinMode(led_pins[i], OUTPUT);
  }
}

void loop() {
  int i, j;
  
  for (j = 0; j < 3; j++) {
    led_pins[j] = random(9, 12);
  }
  
  for (j = 0; j < 3; j++) {
    for (i = 0; i < 256; i++) {
      analogWrite(led_pins[j], i);
      delay(FADE_TIME);
    }
  }
  
  for (j = 0; j < 3; j++) {
    for (i = 255; i > -1; i--) {
      analogWrite(led_pins[j], i);
      delay(FADE_TIME);
    }
  }
}

回路が組めたのでNode.jsから制御させます。

Arduinodeを使ってLEDを制御する

ArduinodeはArduinoとNode.jsの間でデータのやりとりができるような
APIを提供しているライブラリです。
ArduinoにArduinode側からの命令を受け取れるように専用のスケッチを書き込んでおきます。
あとはCでスケッチを書かず、JavaScriptでスケッチを書くだけになります。
Arduinoでできることをフルに発揮出来るわけではないですが、
ちょっとしたことをやるなら大変便利なライブラリです。

まずはArduinodeをインストールしてスケッチを書き込みます。

$ cd path/to/workspace
$ npm install arduinode
...
$ cd node_modules/arduinode/sketch/arduinode
$ // このディレクトリに arduinode.ino がある

arduinode.ino をArduino IDEで開いてArduinoに書き込みましょう。

これで準備は整ったのでJSでコーディングを始めます。

Arduinodeで用意されているAPIはこちら。
arduinode/doc/API.md at master · mironal/arduinode · GitHub


それで書いてみたのがこちら。
(※追記:underscoreっていうutilityライブラリを使ってるので動かすときは
 $ npm install underscore が必要です。)

var _ = require('underscore');
var Arduinode = require('arduinode').Arduinode;

// How to find the serial port?
// ls /dev | grep usb
var portName = '/dev/tty.usbmodem641';

function Led(r, g, b) {
    var portR = 9;   // PWMが使えるデジタルポートをそれぞれ指定する
    var portG = 10;
    var portB = 11;

    return {
        r : r || 0,
        g : g || 0,
        b : b || 0,

        setRGB : function setRGB(_r, _g, _b) {
            this.r = _r;
            this.g = _g;
            this.b = _b;
        },

        bright : function bright() {
            var self = this;

            this._bright('red');

            // TODO: 適当にずらす実装から正しくする
            setTimeout(function () {
                self._bright('green');
            }, 50);
            setTimeout(function () {
                self._bright('blue');
            }, 77);
        },

        _bright : function _bright(type) {
            switch (type) {
            case 'red':
                arduinode.analogWrite(portR, this.r, function (err, res) {
                    console.log('[r]', arguments);
                });
                break;
            case 'green':
                arduinode.analogWrite(portG, this.g, function (err, res) {
                    console.log('[g]', arguments);
                });
                break;
            case 'blue':
                arduinode.analogWrite(portB, this.b, function (err, res) {
                    console.log('[b]', arguments);
                });
                break;
            }
        }
    };
}

var arduinode = new Arduinode(portName, function(err, result){

    if(err){
        return console.log(err);
    }
    console.log('open');

    var interval = 100;
    var led = new Led();

    var timerId = setInterval(function () {
        var r = _.random(0, 255);
        var g = _.random(0, 255);
        var b = _.random(0, 255);

        led.setRGB(r, g, b);    // 色セット
        led.bright();           // 光らせる
    }, interval);

    // TODO: close処理を書く
});

これを実行するとLEDがランダムに光り出します。

使ってみて気づいた点としては、
Arduinodeを使ってArduino側に何か命令しているときに、
レスポンスか返ってこないまま次の命令を出すとエラーになるってこと。

それで適当にsetTimeout()してAPI叩くタイミングをずらしてます。
とりあえず動くやつをつくるということで、
ここは後々asyncとか使ってちゃんとしておきます。

おわりに

とりあえずNode.jsからArduinoを制御することができました。
それとLEDのプログラミングは奥深いってのがわかりました。
(それぞれの色を発光させるのに必要な電圧が違うってこととか。)

任意の色を光らせることができるってのは応用範囲が広いので、
何かと組み合わせていく予定。