見出し画像

【obniz】IRModule の送受信は半二重!

obniz の IRModule は標準のライブラリを使って送受信すると、半二重の状態になります。これは IRModule の発光部と受光部が剥き出しになっていて、自分が発する赤外線を自身が受信してしまうことと、受信時のライブラリにロジックアナライザーを使用していることによります。

延々と送信を繰り返す 

失敗談と解決策です。
見出しの写真にある IRModule を手に入れたので、送受信のテストをしようと思って、下記スクリプトを書いて実行してみました。
リモコンからの赤外線信号を IRModule で受信して記録し、4秒後に IRModule から記録したデータを送信するもので、受信、送信を繰り返し行うものです。


<script>
//  失敗例
$("#bploading").text("RUNNING...");
      (async function(){
        var obniz, irmodule, ir_rcv_col;
  
        obniz = new Obniz('XXXX-XXXX');
        await obniz.connectWait();
        irmodule = obniz.wired("IRModule",{"vcc":0, "send":1, "recv":2, "gnd":3});
        irmodule.duration = 800;
        irmodule.start();
         while(1){ 
          ir_rcv_col = (await new Promise(resolve=>{ irmodule.ondetect = resolve; })); 
          console.log('rcvd');
          console.log(ir_rcv_col);
          await obniz.wait(4000);  
          ir_send = ir_rcv_col;
          if ( ir_rcv_col.length != 0 ){
            console.log('send');
            console.log( ir_send );
            irmodule.send( ir_send );
          }
        }
})();
</script>

期待していた動作としては、リモコンを操作して発した赤外線を IRModule で受信し、4秒後にエコーバックの形で IRModule から送信、その後、待機して次のリモコン操作を待つと言ったものです。
ところが、上記スクリプトだと、一度リモコンの信号を受信し、4秒後の送信を行うと、その後は受信待機とはならず、4秒おきに延々と送信を繰り返す状態になってしまいました。
いろいろ調べたのですが、そのときは判らず、obniz のコミュニティフォーラムで質問したところ、
「自分の信号を受信しているのでは?」とコメントいただき、「あぁ、そうか!」となった訳です。

IRModule の構造とライブラリの仕様

私が使用した IRModule は見出しの写真にあるもので、
詳細は https://obniz.com/ja/sdk/parts/IRModule/README.md です。
写真にあるように、一つの基板の片面に剥き出しの赤外線 LED と、
その LED のすぐ隣に赤外線センサーが取り付けてあります。
この構造だと、LED の発する赤外線をセンサーはダイレクトに受け取ってしまいます。
一方、センサーからの受信データはロジックアナライザーを使って監視しています。一度、受信のライブラリを起動すると、ロジックアナライザーはトリガーを検出し、データを取り込みます。そして、すぐに待機して次のトリガーを待ちます。
ですのでライブラリが起動されている状態では、自分が赤外線を発した場合でも、赤外線は受信され、obniz へ取り込まれてしまいます。

解決方法

このからくりが解ってしまえば、解決方法は簡単でした。
方法は2つ
(1)受信したエコーを捨て読みする。
(2)自身が赤外線を発するときはロジックアナライザーを止める。

以下は上記2つの解決策を講じたスクリプトです。

(1)受信したエコーを捨て読みする。

<script>
       $("#bploading").text("RUNNING...");
       (async function(){
         var obniz, irmodule, ir_rcv_col;
   
         obniz = new Obniz('XXXX-XXXX');
         await obniz.connectWait();
         irmodule = obniz.wired("IRModule",{"vcc":0, "send":1, "recv":2, "gnd":3});
         irmodule.duration = 800;
         irmodule.start();
         while(1){ 
           ir_rcv_col = (await new Promise(resolve=>{ irmodule.ondetect = resolve; })); 
           console.log('rcvd');
           console.log(ir_rcv_col);
           await obniz.wait(4000);
           ir_send = ir_rcv_col;
           if ( ir_rcv_col.length != 0 ){
             console.log('send');
             console.log( ir_send );
             irmodule.send( ir_send );
           }
           // 自分が送信しているときに受信したデータを捨て読みする
           ir_rcv_col = (await new Promise(resolve=>{ irmodule.ondetect = resolve; }));
         }
       })();
   
   </script>


(2)自身が赤外線を発するときはロジックアナライザーを止める。
ただし、この場合、受信のたびにライブラリを起動する必要が有ります。
(ライブラリを起動→ここでは irmodule.start();)

<script>
       $("#bploading").text("RUNNING...");
       (async function(){
         var obniz, irmodule, ir_rcv_col;
   
         obniz = new Obniz('XXXX-XXXX');
         await obniz.connectWait();
         irmodule = obniz.wired("IRModule",{"vcc":0, "send":1, "recv":2, "gnd":3});
         while(1){ 
           irmodule.duration = 800;
           irmodule.start();
           ir_rcv_col = (await new Promise(resolve=>{ irmodule.ondetect = resolve; })); 
           console.log('rcvd');
           console.log(ir_rcv_col);
           await obniz.wait(4000);
	    
           // 赤外線センサーを止める
           irmodule.sensor.obniz.logicAnalyzer.end();
           ir_send = ir_rcv_col;
           if ( ir_rcv_col.length != 0 ){
             console.log('send');
             console.log( ir_send );
             irmodule.send( ir_send );
           }
         }
       })();
   
   </script>

以上です。
それにしても動かない原因がエコーだったとは、ぜんぜん気が付かなかった・・・ orz
obniz に IRModule を突き刺して受信と送信を両方機能させるスクリプトを組む場合は、IRModule のハードウェアの構造とライブラリの仕様上、半二重の状態になることを知っておいてください。


この記事が気に入ったらサポートをしてみませんか?