【FF14】 リアルで侍をプレイする刀コントローラを作る(無線デバイス制御編その2 Node.js)

  • このエントリーをはてなブックマークに追加
ガジェット, 小細工

(0)準備編
(1)キー入力デバイス編
(2)無線デバイス制御編その1 HTTPClient

今回はラズパイ(Raspberry Pi 3)で刀からのセンサデータを受信するサーバを作ります。
ラズパイの役割は、刀(加速度センサ+ESP32)が送信するモーションの指令値を受信し、PCへキー入力を行なうArduinoに伝達することです。
ArduinoとラズパイはGPIOピンで接続するため、無線信号の受信処理とGPIO制御が同時に行なえるNode.jsを使ってサーバプログラムを作っていきます。

Node.jsはサーバとして簡単にプログラムを記述でき、またGPIOの制御が容易です。ラズパイ推奨OSのRaspbian v4.4にはNode.jsがプリインストールされていました。
今回必要なのはESP32からPOSTされたデータを判定してGPIO出力するプログラムです。
GPIOの制御方法はこちらのサイト(ics.media – Raspberry PiとNode.jsでLチカ(LEDをチカチカ)させてみよう!)を参考にしました。
“/sys/class/gpio”にある各ピンに対応したファイルに文字列を書き込んでGPIOピンの入出力を制御します。GPIOの24番ピンをHighにしたい場合は、以下のようなJavaScriptコードを実行します。

var fs = require('fs');

//GPIO24を有効化 
fs.writeFileSync('/sys/class/gpio/export', 24); 

//GPIO24を出力ピンに設定 
fs.writeFileSync('/sys/class/gpio/gpio24/direction', 'out'); 

//GPIO24をHighに設定 
fs.writeFileSync('/sys/class/gpio/gpio24/value', 1);

24番ピンをLowにする際には10行目を”fs.writeFileSync(‘/sys/class/gpio/gpio24/value’, 0);”とします。
またプログラム終了時には”fs.writeFileSync(‘/sys/class/gpio/unexport’, 24);”を記述してピンを開放しましょう。
もしプログラム実行時にすでに該当ピンがexportされている場合はエラーとなり、その際はターミナル上でコマンド”echo 24 > /sys/class/gpio/unexport“を実行することで手動でピンを(この例では24番ピン)リリースすることができます。
これでGPIOをNode.js上で制御する準備ができました。

続いてPOSTを受け付けるHTTPサーバを作ります。
GPIO処理を組み込んだプログラムがこちらになります。「0」というデータがPOSTされた場合にはGPIO24番ピンをHighに、「1」というデータがPOSTされた場合にはGPIO24番ピンをLowにするプログラムです。

var sys = require('sys'),
url = require('url'),
http = require('http'),
qs = require('querystring'),
fs = require('fs');

fs.writeFileSync('/sys/class/gpio/export', 24);
fs.writeFileSync('/sys/class/gpio/gpio24/direction', 'out');

http.createServer(function (request, response) {
 if(request.method == 'POST') {
var data = '';
request.on('data', function (chunk) {
data += chunk;
});
 request.on('end', function() {
console.log(data);
if(data == '0') {
console.log("bingo!");
fs.writeFileSync('/sys/class/gpio/gpio24/value', 1);
}
if(data == '1') {
console.log("off");
fs.writeFileSync('/sys/class/gpio/gpio24/value', 0);
}
});
}
}).listen(8080, '192.168.###.###');

このプログラムに合わせて、前回のESP32側のPOSTプログラムを作り直します(こちらのプログラムは外部ライブラリを使用しないバージョンです)。
ESP32のIO4ピンを入力として、スイッチが押されるたびに「0」と「1」を交互にPOSTするプログラムです。

#include "WiFi.h"

// WiFi credentials.
const char* WIFI_SSID = "###YOUR_SSID###";
const char* WIFI_PASS = "###YOUR_PASSWORD###";
// Internet domain to request from:
const char *sendServer = "192.168.###.###";
const int hostPort = 8080;
int flg = 0;

void setup() {

// Initilize hardware:
pinMode(4, INPUT);
Serial.begin(9600);

// Giving it a little time because the serial monitor doesn't
// immediately attach. Want the firmware that's running to
// appear on each upload.
delay(2000);
Serial.println();
Serial.println("Running Firmware.");

// Connect to the WiFi network (see function below loop)
connectToWiFi(WIFI_SSID, WIFI_PASS);
Serial.println("I'm ready.\n");
}

void loop() {
if (digitalRead(4) == 1) {
while( digitalRead(4) == 1) {
delay(100);
}
send();
if(flg) flg=0;
else flg++;
}
}

void send() {
WiFiClient client;
Serial.print("connecting to ");
Serial.println(sendServer);

 if(client.connect(sendServer, 8080)) {
String postMethod;
postMethod.concat("POST /");
postMethod.concat(".post HTTP/1.1\n");

postMethod.concat("Host: ");
postMethod.concat(sendServer);
postMethod.concat("\n");
postMethod.concat("Content-Type: application/x-www-form-urlencoded");
postMethod.concat("\n");

postMethod.concat("Content-Length: ");
postMethod.concat(1); //length of send data
postMethod.concat("\n\n");
postMethod.concat(flg);
postMethod.concat("\n\n");

client.print(postMethod);
Serial.print(" ");
Serial.println(flg);
}
}

void connectToWiFi(const char * ssid, const char * pwd) {
// https://www.losant.com/blog/getting-started-with-esp32-and-platformio
// Connect to Wifi.
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);

// Set WiFi to station mode and disconnect from an AP if it was previously connected
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(100);

 WiFi.begin(ssid, pwd);
 Serial.println("Connecting...");

 while (WiFi.status() != WL_CONNECTED) {
// Check to see if connecting failed.
// This is due to incorrect credentials
if (WiFi.status() == WL_CONNECT_FAILED) {
Serial.println("Failed to connect to WIFI. Please verify credentials: ");
Serial.println();
Serial.print("SSID: ");
Serial.println(ssid);
Serial.print("Password: ");
Serial.println(pwd);
Serial.println();
}
Serial.println("...");
delay(3000);
}

 Serial.println("");
 Serial.println("WiFi connected");
 Serial.println("IP address: ");
 Serial.println(WiFi.localIP());

 Serial.println("connected");
}

実際に動作させるとこんな感じになります。

JavaScriptで物が動くってすごい!
送信側のスイッチ押下から受信側のLED点灯までほぼラグがなく、連続で押しても受信側で入力を受け付けてくれています。

これで、[ESP32(スイッチボタン)] ⇒[Raspberry Pi(画面に映ってる黒画面)]の通信が確認できました。
前回までの記事でRaspberry PiからPS4にキーボード入力する方法を実装できているので、これで刀入力システムの準備がすべて整いました。
残りは刀の動きを取得するセンサの実装となります。

次回は侍のアクションの動作(モーション)解析と加速度の対応を検討します。

>> モーションセンサ編に続く


記載されている会社名・製品名・システム名などは、各社の商標、または登録商標です。

Copyright (C) 2010 – 2017 SQUARE ENIX CO., LTD. All Rights Reserved.

  • このエントリーをはてなブックマークに追加

コメントを残す


CAPTCHA