Johnny-fiveからnode-serialportに

ArduinoをJavaScriptで動かす「Johnny-five」。

魅力的ではあるものの、対応している電子部品に限りがあり、開発が行き詰ってしまいます。

Arduinoの開発言語はライブラリが充実しているC++を使った方が良さそうです。

でもNode.jsは使いたい

IoT実現のため、Arduinoの制御にJavaScriptを使うことは断念しましたが、ブラウザとの連携はNode.jsサーバーを使って、JavaScriptで行いたいです。

そうなるとArduinoとNode.jsサーバー間のデータ送受信で、Johnny-fiveに代わる仕組みが必要になります。

シリアル通信で何かしらの文字列を送受信できれば良いのですが・・・

node-serialportを使う

シリアル通信ができるNode.jsライブラリがありました!

ArduinoとNode.jsサーバー間で、文字列の送受信を行います。

例えば「LED=H」という文字列をNode.jsからArduinoにシリアル通信で送ると、Arduinoに接続されたLEDが光るというような想定です。

ちょこちょこハマる

結果的にはできましたが、ハマりどころが多かったです。

シリアル通信もあまり理解していないところから始めたので、簡単なところでつまずいています。

参考になるか分かりませんが、コードを掲載していきます。

開発環境は、この系統の情報が意外と少ない(?)、Windows 10です。

ディレクトリ構成

Cドライブ直下に「node-arduino」というディレクトリを作り、ここで開発を行います。

「node-serialport」インストール

すでにNode.jsとExpress、soket.ioはインストールされているとします。

Expressなどと同じ手順だと思いますが、コマンドプロントで

と入力すれば、インストールされます。

Node.jsプログラムの制作

続いてNode.jsサーバーのapp.jsを書きます。

以前書いたものに、飯谷健太さん、sifueさん、_shimizuさんの記事を参考に手を加えています。

var TCP_PORT = 3000,
 DIRECTORY = 'htdocs',
 SERIAL_PORT = 'COM20',
 BAUD_RATE = 57600,
 express = require('express'),
 app = express(),
 http = require('http').Server(app),
 io = require('socket.io')(http),
 serialPort = require('SerialPort'),
 serial = new serialPort(SERIAL_PORT,{
  parser: serialPort.parsers.readline('\n'),
  baudrate: BAUD_RATE
 });

var init = function () {
 app.use(express.static(DIRECTORY));
 http.listen(TCP_PORT, function(){
  console.log(getIP() + ':' + TCP_PORT + ' でサーバーを起動');
 });
 serial.on('open',function(){
  console.log('シリアルポート ' + SERIAL_PORT + ' と接続');
 });
 setIo();
},

//ローカルIPアドレス取得
getIP = function(){
 var os = require('os'),
 ip,
 interfaces = os.networkInterfaces();

 var getIPv4 = function(){
  interfaces[dev].forEach(function(details){
   if (details.family === 'IPv4' && details.address.indexOf('192.') > -1){
    ip = details.address;
   }
  });
 };

 for (var dev in interfaces) {
  getIPv4(dev);
 }
 return ip;
},

//ソケットIO設定
setIo = function(){
 serial.on('data',function(data){
  io.emit('recvmsg',data.toString());
 });

 io.on('connection',function(socket){
  socket.on('led',function(msg){
   serial.write(new Buffer(msg),function(err,results){
    if(err) {
     console.log('Err: ' + err);
     console.log('Results: ' + results);
    }
   });
  });
 });
};

init();

ハマりどころとしては・・・

4行目 シリアルポートの指定

Macのサンプルコードだと「/dev/tty.usbmodemfd121」というような、Windowsユーザーの見慣れぬ文字列となっています。

Windowsの場合は、Arduinoと接続しているCOM番号を、コントロールパネルのデバイスマネージャーや、Arduino IDEで調べて指定します。

ただ、接続し直すとCOM番号が変わることがあるので、どうにかしたい・・・

11行目 改行パース

シリアル通信でデータで「AAA」と文字列を送ると、「A\nA\nA\n」というような改行が入る仕様(?)につまづきました。

文字列は1文字ずつしか送れず、必ず改行が入るようです。

送信したバラバラの文字列を、Arduino上で組み立てるコードも、この後掲載します。

18行目 IPアドレス表示

Wi-Fi接続の際、IPアドレスが変わっていることがあるので、コマンドプロントに出力することにしました。

実際の処理は、26行目以降のgetIP();です。

49行目 デバッグ用の受信コード

Node.jsでシリアルポートを使っていると、Arduinoのシリアルモニタは使えません。

Arduinoのデバッグをする際は、確認したい値をブラウザに表示させます。
(コマンドプロントに表示でもよいのですが)

LED操作画面のindex.html

続いてNode.jsと連携するindex.htmlの制作です。

LED点灯ボタンがあるだけです。

index.htmlファイルに、HTML、CSS、JavaScriptをまとめて記述しています。

<!doctype html
<html>
<head>
<meta charset="utf-8">
<title>Node.jsでシリアル通信</title>
<script src="/socket.io/socket.io.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<style>
 body {
  padding-top: 500px;
  background: #000;
  text-align: center;
 }
 button {
  padding: 20px 40px;
  border-bottom: #999 solid 20px;
  border-radius: 15px;
  background: #EEE;
  font-size: 100px;
 }
  button.on {
  margin-top: 15px;
  border-bottom: #095E13 solid 5px;
  background: #3C9053;
  color: #FFF;
 }
</style>
</head>
<body>
<button id="ledBtn">LED点灯</button>
<script type="text/javascript">
 var SWITCH_CLASS = "on",
 socket = io(),
 $ledBtn = $("#ledBtn"),
 ledSwitch = 0;

 var init = function(){
  setBrowser();
  setMicom();
 }

 //ブラウザ設定
 var setBrowser = function(){
  $ledBtn.on("click", function(){
   if(ledSwitch === 0){
    ledSwitch = 1; //true
    $(this).addClass(SWITCH_CLASS);
   }else{
    ledSwitch = 0; //false
    $(this).removeClass(SWITCH_CLASS);
   }
   socket.emit('led', 'l=' + ledSwitch);
  });
 },

 //マイコン設定
 setMicom = function(){
  socket.on("buttonSwitch", function(buttonSwitch){
   if(buttonSwitch === true){
    ledSwitch = 1;
    $ledBtn.addClass(SWITCH_CLASS);
   }else{
    ledSwitch = 0;
    $ledBtn.removeClass(SWITCH_CLASS);
   }
  });
  socket.on('recvmsg',function(data){
   $ledBtn.text(data);
  });
 };

 init();

</script>
</body>
</html>

52行目 Arduinoに送る文字列

「LED点灯」ボタンを押したら、Node.jsを経由して、Arduinoにシリアル通信で文字列を送ります。

点灯の時は’l=1’、消灯の時は’l=0’としています。

 

また、逆にArduinoからNode.jsを経由して、文字列を受け取れるか確認するため、下記コードを一時的に追加していました。

Arduinoからシリアル送信した文字を、LED点灯ボタンに表示させます。

前途したように、デバッグ用に使いました。

Arduinoのシリアル送受信プログラム

まだ終わりません。Arduinoにプログラムを書き込みます。

#define LED_PIN 13
int recieveByte = 0;
String instruction = "";

void setup(){
 Serial.begin(57600);
 pinMode(LED_PIN,OUTPUT);
}
 
void loop(){
 instruction = "";

 while (Serial.available() > 0){
  recieveByte = Serial.read();
  if(recieveByte == (int)'\n') break;
  instruction.concat((char)recieveByte);
  delay(1);//必要
 }

 if(instruction.length() > 0){
  if(instruction == "l=1"){
   digitalWrite(LED_PIN,HIGH);
  }else if(instruction == "l=0"){
   digitalWrite(LED_PIN,LOW);
  }
 }
}

17行目: 処理に余裕を持たせる

シリアルポートから1文字ずつ送られてきたデータを、Arduino上で組み立てていますが、17行目にdelay(1)を入れないと、繰り返し処理が正しく動作しませんでした。

1m秒遅らせたら、シリアルで送られてきたデータを正常に受信できました。

回路は単純なLED接続

説明不要かもしれないくらい単純な、13番PINでのLED接続です。

最後に動作確認

コマンドプロントでサーバーを立ち上げます。

サーバー立ち上げに成功すると、「192.168.XXX.XXX:3000 でサーバーを起動」とコマンドプロントに表示されます。

そのアドレスを、同じWi-Fiに接続された端末のブラウザで表示させます。

ブラウザでページを読み込むと、LED点灯ボタンが表示されます。

クリックすると・・・

ボタンも緑色になり、Arduinoに接続された緑色のLEDが光ります。

うまく動作しました。

Johnny-fiveからnode-serialportに移行成功です。

 

Johnny-fiveほど手軽ではないですが、応用は利くでしょう。

ESP-WROOM-32にもう一度賭けてみる

以前、Wi-Fiに全く接続できず断念した「ESP-WROOM-32」を、もう一度購入して試しました。

今度は秋月ではなく、Amazonで売られてている少し高めの「ESP32 DevKitC V2」を試します。

結果・・・運よく簡単にWi-Fi接続できました。

ブレッドボードも適したものを

前回はブレッドボードに挿すところから困ったので、「ESP32 DevKitC」と相性のいい、「サンハヤト SAD-101 ニューブレッドボード」も用意しました。

作りが良く、38本のピンがスルッ!と入ります。

これは驚きました。

安いブレッドボードだと、なかなかピンが入らず、曲がってしまったりするのですが、サンハヤト製のものは違います。

穴の1つ1つが、滑らかなすり鉢状になっています。

あまりに良くて、安いブレッドボードが使えなくなってしまうかもしれません。

スマホでLEDをON/OFF

本題のWi-Fi接続テストを行います。

Arduino IDEのメニューから、
ファイル >スケッチ例  >(ESP32 Devの)Wifi > SampleWiFiServer
を選択します。

ssidとpasswordに、自分のWi-Fi情報を入力した後、ボードに書き込みます。

ESP32の5番ピンには、LEDと抵抗器を接続しておきます。

 

Arduino IDEのシリアルモニタを開くとIPアドレスが「192.168.XXX. XXX」と表示されるので、そのアドレスをスマホに打ち込みます。(PCでも良いです)

アドレスの最後に「/H」をつける・・・http://192.168.XXX. XXX/H というように入力すればLEDが点灯。

最後に「/L」を付けると消灯です。

ブラウザに表示されるリンクで、LEDのON/OFFを制御できます。

ESP32のパフォーマンスに期待

ESP32利用を諦めていましたが、もう一度賭けてみて良かったです。

Wi-FI接続以外にも、高速なCPUと大量のピンの数が、このボードの魅力です。

まだまだハマりそうですが試行錯誤していきます。

ボッチャ IoT定規2号

少し前ですが、ボール間の距離を測るコンパス型定規の試作2号を作りました。

距離データをWi-Fiで飛ばせるのは、IoT定規1号と変わりません。
配線を整理して、使いやすく改善しています。

ただ、「レーザー距離測定指示板」を作ったので、あまり必要性を感じなくなりました。

距離データ蓄積で成長を確認

ボッチャの試合で、何cm何mmかという距離データは必要ありません。
相手よりボールが近いか、遠いか分かれば良いからです。

しかし、ボッチャの練習に打ち込んでいると、自分の投球がどれくらいの精度なのかデータで蓄積し、成長を見てみたいと感じるようになりました。

データ蓄積の仕組みも開発中です。

ボッチャ レーザー距離測定実践

本日、ボッチャ教室で主審をやらせて頂きました。

そして、目測で分からない場面に、先日開発したレーザー測定指示板を投入してみました。

照準がずれていた

主審をやりつつ、心に余裕がない中で、レーザー測定は焦ります。

しかも悲しいことに、試作品が雑すぎてボール間の距離を正しく測れませんでした。

照準のレーザーポインタが、持ち運び中に曲がっていたようです。

マスキングテープで固定は、さすがに雑すぎでした。

手が震える

また個人的な問題なのですが、測定中に手が震え、照準が思うように合いませんでした。
床に固定できるような補助器具を指示板につけたほうが良さそうです。

私の場合、メジャーでもコンパスでも手が震えるので・・・そもそもこの手の震えを解決したいところです。

 

とりあえず、実際レーザー測定指示板を使ってみると、改善の余地だらけでした。

私くらい手の震えがひどい人でも使えるレベルにしなければ・・・。

いい勉強となりました。

ボッチャ 親子対等

ボッチャは親子で対等にプレーできる。

これは、他のスポーツでは味わえない、ボッチャ特有のすばらしさだと感じます。

体格差が(ほぼ)関係ない

だいたい小学生以上の子供になると制球が定まり、大人とあまり変わらない実力があります。

野球にしろ、サッカーにしろ、筋力がものをいうので、子供が大人に勝つのは難しいです。さすがに子供と真剣勝負とはいきません。

しかし、ボッチャは真剣勝負で、大人が子供に負けます。

子供にとって、大人に勝てるという体験は、成長意欲の刺激になるのではないかと、考えています。(本当にそうか調査必要)

親子でのチーム戦も対等

もちろんチーム戦で、親子で協力して戦うことも楽しいです。

対等な仲間として、戦略を立てられます。

 

障がい者、高齢者向けにスポットが当てられやすいボッチャですが、親子参加競技として向いているのではないでしょうか?

 

 

レーザービームの可視化

レーザーポインタが欲しくて購入しました。

せっかくなので、子供にレーザービームを見せたいと思います。

赤い点じゃん

Quarton社の「VLM-650-03 LPA」という2,000円くらいのレーザーモジュールを購入しました。

レーザーと聞いて、子供が楽しみにしていたのですが、実際レーザーを出してみても、壁に赤い点が映るだけです。

「赤い点じゃん」と、がっかりした模様。

レーザービームを撃つ特撮かアニメを見て、期待していたのだと思います。

煙に光を通せばレーザービームを見れる

では、レーザービームを見せましょう。

煙に通せばよいので、家にあった蚊取り線香を焚いて光を通します。

ビー(レーザー発射)

「うわ!すごい!」

冒頭の写真のように、赤いレーザービームが見えました。

レーザーの扱いに注意!

子供がレーザーを直視したり、人に向けないように注意が必要です。

保管、扱いには気を使います。

 

Arduinoの配線を載せるまでもないかもしれませんが、一応下記のように5VとGrandで接続しています。

電池に直接つないでも良いです。

 

扱いに注意すれば、楽しめる電子部品だと思います。

イベント総合EXPOでもボッチャ

イベント総合EXPOに行ってきました。

余談ですが、幕張メッセで開催なのに、間違ってビッグサイトに行ってしまい、その後、京葉線と武蔵野線を乗り間違えたのか、埼玉に行ってしまい・・・愚かなことに、なかなかたどり着けなかったです。

その上、夜にボッチャ教室の予定が入っていたため、ほとんど展示会に滞在できませんでした。

 

・・・しかし、それでも収穫はありました。

ボッチャをやっていた!?

30小間くらいの膨大なスペースを確保している西尾レントオール社が、ボッチャをやっていました。

ボッチャを普及のために活動しているのかと思いきや、どうやらそれよりも、床のレンタルを普及させたいようでした。

 

鉄球を使うペタンクと違い、床が傷まない室内用競技のボッチャで、レンタルの床が必要なのかな?と、思いましたが、野外用の床があるそうです。

仮説スポーツ床材「Power Game」

 

ボッチャのボールの転がりは、ゲームの楽しさに影響する大切な要素ですし、平らな床材は、野外イベントで活躍すると思います。

ラズベリーパイは甘くない

ラズベリーパイを買いました。

パイが入っていそうですが、中身はコンピュータです。

電子工作でArduinoと並び、有名なのが「Raspberry Pi」。

Arduinoに比べ、複雑な処理に向いているようです。

やりたいことが増えてきたので、Raspberry Piも試してみます。

Lチカに1日かかる

Raspberry PiはOSのインストールから始まるのですが・・・

JavaScript(Node.js)でLEDをチカチカさせるのに1日かかってしまいました。

Pythonで開発が無難か

調べた感触として、Raspberry Piのプログラミングは、Pythonを使うのが無難と感じました。

Raspberry Piの「Pi」は、Pythonから来ているらしいです。

 

おいしそうな袋に入っていたラズベリーパイですが、結構、学習コストがかかり、甘くはないようです。