Node.js でラズパイのGPIO入力を取得します。

今回も Raspberry pi 3B+でなんかしようシリーズです。
今まで shellNode.js で L チカをする中で出力を操作してきましたが、
今回は入力情報を取得してみます。

目次

一回だけ入力をとってみよう

今回は gpio21 番ピンの入力を取得してみます。
回路は以下のようになります。

(相変わらず画像だとわかりにくいなぁ。)
結線だけ示すと以下のようになります。

[1番ピン(3.3V)]->[トグルスイッチ]-->[抵抗(1kΩ)]->[39番ピン(GND)]
                           |->[40番ピン(GPIO21番)]
                                 

gpioread.js として以下を保存します。

gpioread.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let fs = require("fs");
let path = require("path");

//使用するgpioピンナンバー
let pinnum = 21;
//使用する仮想ファイルのパスを定義
let pathstr = "/sys/class/gpio/";
let gpio21 = path.join(pathstr, "gpio" + pinnum);

//gpio使用の準備
fs.writeFileSync(path.join(pathstr, "export"), pinnum);
fs.writeFileSync(path.join(gpio21, "direction"), "in");

let state = fs.readFileSync(path.join(gpio21, "value"), "utf8");
console.log(state);

fs.writeFileSync(path.join(pathstr, "unexport"), pinnum);

sudo node gpioread.jsで実行すると
/sys/class/gpio/gpio21/valueを読み取りして、表示します。
表示の内容は、0 か 1 です。

今度は gpio21 を継続してチェックしてみます。

gpio の入力を監視してみよう

監視といっても、何度も対象の GPIO にアクセスして値の変化を認識するだけです。
gpioread-loop.js として以下を保存します。

gpioread-loop.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
let fs = require("fs");
let path = require("path");

//使用するgpioピンナンバー
let pinnum = 21;
//使用する仮想ファイルのパスを定義
let pathstr = "/sys/class/gpio/";
let gpio21 = path.join(pathstr, "gpio" + pinnum);
//gpio21のステータス
let state = "";
//gpio21のステータスが切り替わった回数をカウント
let count = 0;
//変数stateの初期化状況(プログラム起動時のgpio21の状態を初期値とした設定が済めばtrue)
let init = false;

//gpio使用の準備
fs.writeFileSync(path.join(pathstr, "export"), pinnum);
fs.writeFileSync(path.join(gpio21, "direction"), "in");

while (true) {
let buf = fs.readFileSync(path.join(gpio21, "value"), "utf8");
if (!init) {
//stateの初期化
state = buf;
init = true;
continue;
}
if (state != buf) {
state = buf;
if (state == 1) {
console.log(`${gpio21}がONになりました`);
} else {
console.log(`${gpio21}がOFFになりました`);
}
count++;
}
if (count > 3) {
break;
}
}

fs.writeFileSync(path.join(pathstr, "unexport"), pinnum);

sudo node gpioread-loop.jsで実行してスイッチを切り替えると以下のように表示されます。

1
2
3
4
/sys/class/gpio/gpio21がONになりました
/sys/class/gpio/gpio21がOFFになりました
/sys/class/gpio/gpio21がONになりました
/sys/class/gpio/gpio21がOFFになりました

gpio の状況を監視できるようになりました。
しかし、せっかく Node.js を使用しているので、非同期関数で実装してみたいところです。

何回も入力をとってみよう(非同期関数)

今度は非同期関数を使用して gpio の情報を取ってみたいと思います。
gpioread-async.js として以下を保存します。

gpioread-async.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
let fs = require("fs");
let path = require("path");

//使用するgpioピンナンバー
let pinnum = 21;
//使用する仮想ファイルのパスを定義
let pathstr = "/sys/class/gpio/";
let gpio21 = path.join(pathstr, "gpio" + pinnum);
//gpio21のステータス
let state = "";
//gpio21のステータスが切り替わった回数をカウント
let count = 0;
//変数stateの初期化状況(プログラム起動時のgpio21の状態を初期値とした設定が済めばtrue)
let init = false;

//gpio使用の準備
fs.writeFileSync(path.join(pathstr, "export"), pinnum);
fs.writeFileSync(path.join(gpio21, "direction"), "in");

//gpio読み込み関数を定義
let gpioread = async () => {
return new Promise((resolve, reject) => {
fs.readFile(path.join(gpio21, "value"), "utf8", function (err, text) {
if (err) {
//エラーの場合は0を返しておく
reject("0");
} else {
resolve(text);
}
});
});
};

//読み込み実行
(async () => {
while (true) {
//gpioの読み込み実行
let buf = await gpioread();
if (!init) {
//stateの初期化
state = buf;
init = true;
continue;
}
if (state != buf) {
state = buf;
if (state == 1) {
console.log(`${gpio21}がONになりました`);
} else {
console.log(`${gpio21}がOFFになりました`);
}
count++;
}
if (count > 5) {
break;
}
}
fs.writeFileSync(path.join(pathstr, "unexport"), pinnum);
})();

sudo node gpioread-async.jsで実行します。

今までは、同期実行されるfs.readFileSyncを使用してきましたが、
今回は非同期な関数のfs.readFileを使用してみました。
非同期関数を使用しても GPIO の取得ができました。

これまでの記事で入出力の操作に関してつかめました。
Node.js をコアにしたアプリにしてみたいところです。

ではでは。