Raspberry Pi でスイッチを使ったLED点灯をしてみた。(Node.js)

今回は、Node.js をインストールした Raspberry Pi を使って、
LED点灯の制御を行ってみました。

概要

スイッチが押されている間だけLEDが点灯するプログラムを作成する。

参考文献

WEB
  1. 第9回「ラズベリーパイで電子工作!Lチカ…の前にLピカ!」
  2. Raspberry PiとNode.jsでLチカ(LEDをチカチカ)させてみよう!
  3. ラズベリーパイのGPIOを、Node.jsで操作してLED光らせてみた!
  4. タクトスイッチを使ってLEDを点灯してみる
  5. Raspberry Pi タクトスイッチの入力を扱う その1
書籍
  1. Raspberry Piで学ぶ電子工作 超小型コンピュータで電子回路を制御する

環境

回路の作成

以下の図の通りに配線を繋ぎます。 f:id:ashiris:20170109205400p:plain 回路の解説は割愛させて頂きます。
参考文献のWEB 5.書籍 1.で詳しい解説が掲載されていますので、
詳細を知りたい方はそちらを参照ください。

プログラム作成

ソースコード
var fs = require('fs');

var GPIO_DIR = '/sys/class/gpio';
var GPIO_PIN_DIR = GPIO_DIR + '/gpio';
var PIN_LIST = [];

//使用したGPIOポートの開放
var cleanUp = function() {
    for (var i=0; i < PIN_LIST.length; i++) {
                fs.writeFileSync(GPIO_DIR + '/unexport', PIN_LIST[i]);
        }
};

//使用するGPIOポートの準備設定
var setUp = function(pin, io) {
        try {
                fs.writeFileSync(GPIO_DIR + '/export', pin);
                PIN_LIST.push(pin);
                fs.writeFileSync(GPIO_PIN_DIR + pin + '/direction', io);
        } catch (e) {
                console.log(e);
                cleanUp();
        }
};

//GPIOの入力状態を取得
var getInput = function(pin) {
        try {
                var cntxt = fs.readFileSync(GPIO_PIN_DIR + pin + '/value');
                return cntxt.toString().split('\n')[0];
        } catch (e) {
                console.log(e);
                cleanUp();
        }
};

//GPIOの出力状態を設定
var setOutput = function(pin, value) {
        try {
                fs.writeFileSync(GPIO_PIN_DIR + pin + '/value', value);
        } catch (e) {
                console.log(e);
                cleanUp();
        }
};

try {
        //GPIO 7を入力に設定する。
        setUp(7, 'in');
        //GPIO 8を出力に設定する。
        setUp(8, 'out');

        //0.01毎にGPIO 7の入力状態を確認し、
        //電流が流れている(スイッチが押されている)場合
        //LEDを点灯させる。
        var moniter = setInterval(function() {
                var value = getInput(7);
                if (value == '1') {
                        //スイッチが押された状態
                        setOutput(8, '1');
                } else {
                        //スイッチが離された状態
                        setOutput(8, '0');
                }
        }, 10);
} catch (e) {
        console.log(e);
        cleanUp();
}

process.on('SIGINT', function() {
        cleanUp();
        process.exit(0);
});

process.on('end', function() {
        cleanUp();
        process.exit(0);
});
コード解説

GPIOの操作について、基本的な内容を簡潔に書くと以下のとおりです。

  • /sys/class/gpio/export にGPIOの番号を書き込むと、その番号のGPIOが使用可能になる。
  • /sys/class/gpio/unexport にGPIOの番号を書き込むと、その番号のGPIOが使用不可能になる。
  • /sys/class/gpio/gpioX/direction (XはGPIO番号)に、
    • 「in」と書き込むと入力としてGPIOが機能する。
    • 「out」と書き込むと出力としてGPIOが機能する。
  • /sys/class/gpio/gpioX/value (XはGPIO番号)の内容が、
    • 「0」である場合は電流が流れていない。(正確には電位が低い)
    • 「1」である場合は電流が流れている。(正確には電位が高い)

Node.js では、ファイルの読み書きは「fs」モジュールを扱う。
読み込みは「readFileSync(ファイル名)」関数を使用し、
書き込みは「writeFileSync(ファイル名, 書き込み内容)」関数を使用する。

注意点は、GPIOの使用後は必ず使用したGPIOを使用不可能状態に戻すことです。
開放したままそのGPIOを使用可能に設定しようとすると、エラーが発生してしまいます。

LED点灯の主要部分は、setInterval内の記述です。
スイッチが押された状態ではGPIO 7の電位が高くなるので、
0.01秒間隔でGPIO 7の状態を確認し電位が高ければ、
GPIO 8から電流が流れるようにしています。
スイッチを離された状態は、その逆に設定すれば良いだけです。

後書き

スイッチの状態を判断する処理をsetIntervalではなく、
できれば Node.js っぽくイベントを拾って行いたかったのですがうまくいきませんでした。
「fs.watch」関数でファイル変更イベントが拾えませんでした。

いろいろ調べていたら「Node.jsでRaspberryPiのGPIOを良しなにする方法」という記事を見つけました。
どうやら方法はあるみたいです。
時間ができたらそちらを学習してみようかな。