低価格なArduino互換機などを使って、サーバーのステータスを電光掲示板やLEDで表したいとか、逆にArduinoの光センサや温度センサの値をサーバーで処理したいってことはよくあるんじゃないかと思います。
その際に、毎回用意するのがUSBを利用したシリアル通信で文字列を送受信する実装です。よく使うのでテンプレートを用意しておきました。
コードは、以上のリポジトリに置いてあります。
git cloneして、npm install。 serialport をそのまま使っています。
Node.js のコードは、
'use strict';
// シリアルポートに定期的に書き込んではデータを受け取る
// パーストークンは \n
// 1秒おき送信
const SerialPort = require('serialport');
const port = new SerialPort('/dev/cu.usbmodem14141', {
parser: SerialPort.parsers.readline('\n'),
baudrate: 9600
});
port.on('open', function () {
console.log('Serial open.');
setInterval(write, 1000, 'OK\n');
});
port.on('data', function (data) {
console.log('Data: ' + data);
});
function write(data) {
console.log('Write: ' + data);
port.write(new Buffer(data), function(err, results) {
if(err) {
console.log('Err: ' + err);
console.log('Results: ' + results);
}
});
}
こんな感じ。writeメソッドを1000ミリ秒ごとに定期実行してます。ここでは、パーストークンを\nにして、1秒おきに送受信。レートやシリアルポートのパスはArduino IDEとか見つつ適宜書き換えて下さい。
Arduinoのコードは、
#define LED 13
int recieveByte = 0;
String bufferStr = "";
String okStr = "OK";
void setup() {
pinMode(LED, OUTPUT);
Serial.begin(9600);
}
// シリアルポートに定期的に書き込んではデータを受け取る
// パーストークンは \n
// OK を受け取ったら 13 LED点灯、それ以外を受け取ったら削除
// 1秒おきループ
void loop() {
bufferStr = "";
while (Serial.available() > 0) {
recieveByte = Serial.read();
if (recieveByte == (int)'\n') break;
bufferStr.concat((char)recieveByte);
}
// 受け取ったデータがあるなら送りかえしてスイッチ操作
if (bufferStr.length() > 0) {
Serial.print("I received: ");
Serial.println(bufferStr);
if (okStr.compareTo(bufferStr) == 0) {
digitalWrite(LED, HIGH);
} else {
digitalWrite(LED, LOW);
}
}
delay(1000);
}
こんな感じでとりあえず13ピンのLEDの反応だけ書いて、受け取ったものを\nでパースしてそのまま返す感じ。それを1秒おきループで実装。これをコンパイルして送信。
これで、
~/w/arduino_serial_js $ node index.js
Serial open.
Write: OK
Data: I received: OK
Write: OK
Data: I received: OK
Write: OK
こんな感じにArudinoとNode.jsを動かしているマシンでシリアル通信して、文字列をやり取りするようにできます。LEDも送っている文字列がOKならば光ります。これをひな形にいろいろおもしろいもの作っていきましょう。