2014年09月24日

小型赤外線(IR)リモコン irMagician ファースト・インプレッション

「赤外線の魔術師」こと irMagician (学習型赤外線リモコン・デバイス)をご存知ですか? 今日はその特長と Raspberry Pi を使った赤外線リモコンの学習・再生方法をご紹介しますよ。

01 irMagician

irMagician の特長・購入方法


irMagician は大宮技研 合同会社(http://www.omiya-giken.com/)の販売する学習型赤外線リモコン・ボードです。

赤外線(IR)学習リモコンには商用製品から Arduino を使った自作まで多くの選択肢がありますが今日ご紹介する irMagician には次のような特長があります。

  • 1チップマイコン(PIC18F2550)を採用し低価格(完成品で 3,980 円、パーツのみ 1,980 円)と小型化を実現
  • PIC チップ内蔵の CCP モジュール(Caputure/Compare 機能)を利用した高精度なパルス幅(HIGH/LOW 時間間隔)の計測が可能
  • IR 信号を純粋な HIGH/LOW の組み合わせとして扱うため特殊なフォーマットにも対応可能
  • IR 信号のバッファとして最大で 640 バイトのメモリ空間を利用可能。 これによりエアコンのような大きな赤外線データも再現可能。
  • USB 接続ながらそのインタフェースには CDC-ACM クラスを採用しているのでシリアル・デバイスとして利用可能。

まずは大きさを見てもらいましょうか。 実は僕ビット・トレード・ワン社が販売する USB 接続 赤外線リモコンキットも持っているんですがそれよりも一回りは小さなサイズ。
(ちなみにビット・トレード・ワンの赤外線キットはフリスクのケースをモールドに出来るという素晴らしい形状をしております)

02 irMagician サイズ比較


最も気になる学習機能ですが、(比較的)大容量のバッファ(640 bytes)とハードウェア支援(Caputure/Compare)を使い受信信号を純粋な HIGH/LOW と時間の組みわせとして学習するのでリモコン・フォーマットには依存しない仕組みになっています(赤外線リモコンのデータ形式には家電協、NEC、SONY、三菱など幾つかのメジャーなフォーマットと何れにも該当しない独自形式を採用している小規模ベンダーが混在しており、かつ、エアコンという家電は常に全ての設定値を送受信するのでデータ長が大きくなります。 これらの複雑な日本の IR 環境が学習リモコンによっては正しく学習出来る・出来ないの差が出る原因になっています)。

個人的に嬉しかったのはシリアル・デバイスとして扱えるところ。 メジャーな OS(Windows、Mac、Linux)・言語であれば、その殆ど全てでアプリケーションを作って遊ぶことが出来ますからね。

より詳しい説明はこちら(irMagician Japanese)をどうぞ。

え、すごく欲しくなってきた? irMagician の購入方法で一番簡単なのは大宮技研さんウェブサイトからオンライン(http://www.omiya-giken.com/?page_id=959)で注文する方法。 在庫があれば 2,3日で届きます(メール便)。

秋葉原の IT プラザ(http://www.itplaza.co.jp/)さんでも店頭販売してますよ(写真左が完成キット、右が組立キット)。

irMagician IT shop


あともう1つ irMagician には適当なモールド(外装)が無いのでフレキシブル USB ケーブルも購入しておくのがオススメ。

irMagician USB cable


Raspberry Pi と組み合わせるとこんな感じになります。

irMagician and Raspberry Pi


Raspberry Pi で irMagician を楽しむ方法


さて Raspberry Pi (+ Raspbian OS)で irMagician をセットアップしてみましょうか。

Raspbian を使う場合、そのままではシリアル・インタフェースをコンソール用として自動で割り当ててしまうのでカーネル・パラメーターを編集して事前に解除しておく必要があります。

適当なエディタで /boot/cmdline.txt を開き、

pi@raspberrypi ~ $ sudo vi /boot/cmdline.txt


コンソール用として ttyAMA0 を設定している箇所(console=ttyAMA0,115200 kgdboc=ttyAMA0,115200)を削除しましょう。

#dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait


もう一箇所、/etc/inittab を編集して Pi serial line として ttyAMA0 を設定している行をコメントアウトします。

#Spawn a getty on Raspberry Pi serial line
#T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100


これで一度再起動すればおしまい。 起動後に irMagician を USB 接続すると /dev/ttyACM0 というデバイス・ファイルが見えるはずです。

pi@raspberrypi ~ $ ls /dev/ttyACM*
/dev/ttyACM0


僕は Python を使って irMagician へアクセスするので pyserial ライブラリをインストールしておきます。

pi@raspberrypi ~ $ sudo apt-get install python-pip
pi@raspberrypi ~ $ sudo pip install pyserial


irMagician では学習することをキャプチャ、学習したデータを送信することをプレイと呼び、サンプル・コードがホームページ上(http://www.omiya-giken.com/?page_id=1231)で公開されているんですが、キャプチャ、プレイ、メモリ上にある受信データのセーブ(JSON 形式のファイルに保存)と個々にコードが別れていてちょっと使い辛い。

大宮技研さんのコードを参考にさせて頂きつつ、irm.py という1つのユーティリティにまとめるとこうなります。

# -*- coding: utf-8 -*-

import sys
import serial
import time
import json
import argparse
import os

here = os.path.abspath(os.path.dirname(__file__))
ir_serial = serial.Serial("/dev/ttyACM0", 9600, timeout = 1)
#ir_serial = serial.Serial("/dev/tty.usbmodem01231", 9600, timeout = 1)

def captureIR(path):
  print "Capturing IR..."
  ir_serial.write("c\r\n")
  time.sleep(3.0)
  msg = ir_serial.readline()
  print msg
  if path and not 'Time Out' in msg:
    saveIR(path)

def playIR(path):
  if path and os.path.isfile(path):
    print ("Playing IR with %s ..." % path)
    f = open(path)
    data = json.load(f) 
    f.close()
    recNumber = len(data['data'])
    rawX = data['data']

    ir_serial.write("n,%d\r\n" % recNumber)
    ir_serial.readline()

    postScale = data['postscale']
    ir_serial.write("k,%d\r\n" % postScale)
    #time.sleep(1.0)
    msg = ir_serial.readline()
    #print msg
    
    for n in range(recNumber):
        bank = n / 64
        pos = n % 64
        if (pos == 0):
          ir_serial.write("b,%d\r\n" % bank)
    
        ir_serial.write("w,%d,%d\n\r" % (pos, rawX[n]))
    
    ir_serial.write("p\r\n")
    msg = ir_serial.readline()
    print msg
    #ir_serial.close() 
  else:
    print "Playing IR..."
    ir_serial.write("p\r\n")
    time.sleep(1.0)
    msg = ir_serial.readline()
    print msg

def saveIR(path):
  print ("Saving IR data to %s ..." % path)
  rawX = []
  ir_serial.write("I,1\r\n")
  time.sleep(1.0)
  recNumberStr = ir_serial.readline()
  recNumber = int(recNumberStr, 16)
  
  ir_serial.write("I,6\r\n")
  time.sleep(1.0)
  postScaleStr = ir_serial.readline()
  postScale = int(postScaleStr, 10)
  
  #for n in range(640):
  for n in range(recNumber):
      bank = n / 64
      pos = n % 64
      if (pos == 0):
          ir_serial.write("b,%d\r\n" % bank)
  
      ir_serial.write("d,%d\n\r" % pos)
      xStr = ir_serial.read(3) 
      xData = int(xStr, 16)
      rawX.append(xData)
  
  data = {'format':'raw', 'freq':38, 'data':rawX, 'postscale':postScale}

  f = open(path, 'w')
  json.dump(data, f)
  f.close()
  print "Done !"

if __name__ == "__main__":
  # parse options
  parser = argparse.ArgumentParser(description='irMagician CLI utility.')
  parser.add_argument('-c', '--capture', action="store_true", dest="cap", help="capture IR data", default=False)
  parser.add_argument('-p', '--play', action="store_true", dest="play", help="play IR data", default=False)
  parser.add_argument('-s', '--save', action="store_true", dest="save", help="save IR data", default=False)
  parser.add_argument('-f', '--file', action="store", dest="file", help="IR data file (json)", default=False)
  
  args = parser.parse_args()

  if args.play:
    playIR(args.file)

  if args.save and args.file:
    saveIR(args.file)
  
  if args.cap:
    captureIR(args.file)

  # release resources 
  ir_serial.close()


こいつを Raspberry Pi にコピーして -c オプション(キャプチャ・モード)付きで起動(環境によっては sudo も必要)すると・・・

pi@raspberrypi ~ $ python irm.py -c
Capturing IR...
... Time Out !

お、グリーン色の LED が点灯。 うまく動いているみたい。

irMagician LED capture mode


もう一度キャプチャ・モード(- c)で起動、実際にリモコンから赤外線を照射してみます。

irMagician capture remocon


するとターミナル(端末)上に表示されるメッセージにも変化が。

pi@raspberrypi ~ $ python irm.py -c
Capturing IR...
... 80


うまくキャプチャ出来たでしょうか? 今度は -p オプション(プレイ)付きでキャプチャした赤外線パルスを機器に向けて発射してみましょう。

pi@raspberrypi ~ $ python irm.py -p
Playing IR...
... Done !


僕が試したリモコン・コンセント OCR-05 は無事動きましたよ!

irMagician and OCR-05


残念ながら赤外線フォーマットに依存するビット・トレード・ワン製リモコン・キットは学習失敗・・・。

僕が試せた限りで両者の比較・検証結果は以下の通り。

学習対象デバイス irMagician
(大宮技研)
USB接続 赤外線リモコンキット
(Bit Trade One)
液晶テレビ
(東芝 REGZA 37Z1S)
OK OK
エアコン
(HITACHI RAM-A28CS)
OK x
リモコン・コンセント
(オーム電機 OCR-05)
OK x

動くことが確認出来たらチップ上にバッファされただけの IR データを次のコマンドでファイルに保存しておきましょう。

pi@raspberrypi ~ $ python irm.py -s -f OCR05-ON.json
Saving IR data to OCR05-ON.json ...
Done !


ちなみに JSON ファイルの中身はこんな構造になっております。
(エアコン、シーリングライト、扇風機など動作確認済みの機器については大宮技研さんのページで JSON ファイルが公開されています)

{"postscale": 100,
"freq": 38,
"data": [29, 1, 249, 39, 39, 13, 12, 13, 12, 13, 28, 13, 28, 13, 28, 13, 28, 13, 12, 13, 12, 13, 161, 39, 39, 13,
 12, 13, 12, 13, 28, 13, 28, 13, 28, 13, 28, 13, 12, 13, 12, 13, 159, 39, 39, 13, 12, 13, 12, 13, 28, 13, 28, 13,
 28, 13, 28, 13, 12, 13, 12, 13, 159, 39, 39, 13, 12, 13, 12, 13, 28, 13, 28, 13, 28, 13, 28, 13, 12, 13, 12, 13],
 "format": "raw"}


このファイルを使えばマイコン上の赤外線データ・バッファがリセットされてしまった後でもプレイが出来るという理由です。

pi@raspberrypi ~ $ python irm.py -p -f OCR05-ON.json
Playing IR with OCR05-ON.json ...
... Done !

使い方が分からなくなったら help をどうぞ。

pi@raspberrypi ~ $ python irm.py --help
usage: irm.py [-h] [-c] [-p] [-s] [-f FILE]

irMagician CLI utility.

optional arguments:
  -h, --help            show this help message and exit
  -c, --capture         capture IR data
  -p, --play            play IR data
  -s, --save            save IR data
  -f FILE, --file FILE  IR data file (json)

次回は宅内にある赤外線制御機器を屋内・屋外から制御するホーム・オートメーション環境を作ります(多分)。



Posted by netbuffalo at 01:48│Comments(6)TrackBack(0) 家電 | Raspberry Pi


この記事へのトラックバックURL

この記事へのコメント
はじめまして!
記事拝見させていただきました
irMagicianにすごく興味あります

irMagicianを使ってみて
赤外線の飛ぶ距離と幅?についての使用感
をぜひ教えていただけないでしょうか?

ビット・トレード・ワン製リモコン・キットを使っているのですが
赤外線の出力幅?が狭くそれぞれの機器にLEDを向けないと
リモコンできなくって困っています
irMagicianを使うことで解決できるなら
購入を考えています

よろしくお願いします
Posted by 樽 at 2015年01月29日 12:59
樽さん、ご質問ありがとうございます。

<赤外線の飛距離>
僕はさほど広くない8畳ほどの居間で使っており家電との距離が限られるのですが、2-3mで問題は感じません(それ以上の距離は試していないのでコメントできず申し訳ないです)

<赤外線の幅(指向性)>
これも同じ居間という条件であり樽さんのご質問に明確には答えられないのですが、指向性は強くない(幅が狭いということはない)と思います。距離は比較的近いのですがボードに対してほぼ真横にある家電(TV)と目の前2mほど先にある家電(エアコン)両方の制御に成功しています。

<その他>
僕の家ではビット・トレード・ワン社ボードではエアコンが動かず双方の比較はできなかったのですが、並べて見る限り赤外線送出部のクリスタル部品に物理的な違いが見えますので性能差はあると思います。
Posted by netbuffalo at 2015年01月29日 17:10
こんばんは!

ご回答ありがとうございます(感謝)

飛距離が2~3m・・・十分です(^^
真横でもリモコンできているなら、irMagicianだけで
私の部屋にある全部の家電をリモコンできるかもしれない~

情報ありがとうございます

ちなみに私の方では
ビット・トレード・ワン社ボードは
Raspberry Piと接続していて最初はエアコンはNGでした
信号の長さが問題では?と思い、プログラムソースを
ちょっとだけ変更して、信号の記憶量を増やしたら
制御できるようになりましたよ
Posted by 樽 at 2015年01月30日 19:23
樽さん、こちらこそ情報ありがとうございます。
BTOさんのボードはファームを色々と更新しただけで、ソースの変更はしていませんでした。
時間ができたらチャレンジしてみます(バッファ・サイズかな)!
Posted by netbuffalo at 2015年01月30日 19:50
もう一箇所、/etc/inittab を編集して Pi serial line として ttyAMA0 を設定している行をコメントアウトします。
の後、再起動しても立ち上がりません(再起動しません)。
起動の途中で停止します。
なぜでしょうか。
Posted by kijik at 2015年11月06日 12:27
kijikさん、僕の手元(今は Raspberry Pi 2を使っています)で試しましたが、inittab編集後に Raspberry Pi(Raspbian)が起動しないという現象は起きませんでした。
(念の為、irMagician を USB ポートに指したまま、抜いた状態の両方で試しましたが起動しました)
起動しないのは何か別の理由なのかな?という気がするのですが、具体的な原因は思い付きません。
念の為、僕が今日手元で試した Raspberry Pi の inittab ファイルをメールでお送りしますね。
Posted by netbuffalo at 2015年11月07日 16:47

コメントする

名前
 
  絵文字