6. リモコン信号の解析¶
黒豆や IRKit, KURO-RS, クロッサム2+ などのプログラマブルな学習リモコン (スマートリモコン) の信号データを、リモコン同士ツノつき合わせて学習させるのではなく、PC 上で理想的な波形に合成するためのノウハウです。
- 赤外線リモコンの信号定義データの合成 [表紙]
- 家製協フォーマットの信号データ合成
- NEC フォーマットの信号データ合成
- ソニーフォーマットの信号データ合成
- SHARP フォーマットの信号データ合成
- リモコン信号定義データの相互変換
- リモコン信号の解析 (このページ)
- メーカー純正リモコンのコード
このページでは、IRKit や KURO-RS を利用して簡便に機器付属のリモコン信号を解析するサンプルコードを紹介します。
6.1. リモコン信号の解析¶
汎用定義形式のデータから、リモコン信号のフォーマット (家製協/NEC/ソニー/SHARP) を判別し、デコードするための perl スクリプトです。アドホックな作りですが、そこそこの精度で解析できています。
- 入力は、1行に定義データ一つの形式のテキストファイル。読めない行は黙って捨てる。
- 出力は、各データを解析した結果が標準出力に書き出される。
使用例¶
IRKit で学習済みの定義データを解析する (irconvert は こちら を参照)
$ irconvert --in irkit 入力ファイル | iranalyze
黒豆でリモコン信号を次々に受信しながら解析する (broadlink_cli は こちら、irconvert は こちら を参照)
$ while (1)
> broadlink_cli --device "0x2737 192.168.xx.xx xxxxxx" --learn | irconvert --in mame | iranalyze
> end
サンプルコード¶
#! /usr/bin/perl
#
# Usage: iranalyze [infile ...]
while (<>) {
chop;
my (@run) = split (" ", $_);
my ($freq) = shift (@run);
my ($repeat) = shift (@run);
next if ($freq + 0 <= 0);
print &analyze (@run), "\n";
}
sub analyze {
my (@run) = @_;
my ($result) = "";
# -- ヘッダ部の「1」の長さでフォーマット判別
if ($run[0] <= 1200) { # SHARPフォーマット (ヘッダなし)
while (@run) {
my ($t_on) = shift (@run); my ($t_off) = shift (@run);
last if ($t_off > 3000);
$code .= ($t_off > 1000) ? "1" : "0";
}
my ($len) = length ($code);
goto unknown if ($len != 15);
my ($id, $cmd, $exp, $chk) = ($code =~ /(.{5})(.{8})(.)(.)/);
$result = sprintf ("sharp(%d): %d/%d/%d", $len, unpack ("SS", pack ("b16b16", $id, $cmd)), $exp);
} elsif ($run[0] <= 2600) { # ソニーフォーマット (仕様上は2400μsec)
shift (@run); shift (@run);
while (@run) {
my ($t_on) = shift (@run); my ($t_off) = shift (@run);
$code .= ($t_on > 900) ? "1" : "0";
last if ($t_off > 3000);
}
my ($len) = length ($code);
goto unknown if ($len != 12 && $len != 15 && $len != 20);
my ($cmd, $id) = ($code =~ /(.{7})(.*)/);
$result = sprintf ("sony(%d): %d/%d", $len, unpack ("SS", pack ("b16b16", $id, $cmd)));
} elsif ($run[0] <= 4800) { # 家製協フォーマット (仕様上は2800~4000μsec)
shift (@run); shift (@run);
while (@run) {
my ($t_on) = shift (@run); my ($t_off) = shift (@run);
last if ($t_off / $t_on > 10);
$code .= ($t_off / $t_on > 2) ? "1" : "0";
}
my ($len) = length ($code);
goto unknown if ($len % 8 != 0);
$result = sprintf ("aeha(%d): ", $len);
$result .= join (" ", unpack ("H2"x ($len / 8), pack ("b$len", $code)));
} elsif ($run[0] <= 15000) { # NECフォーマット (仕様上は9000μsec)
shift (@run); shift (@run);
while (@run) {
my ($t_on) = shift (@run); my ($t_off) = shift (@run);
last if ($t_off / $t_on > 5);
$code .= ($t_off / $t_on > 2) ? "1" : "0";
}
my ($len) = length ($code);
goto unknown if ($len != 32);
$result = sprintf ("nec(%d): ", $len);
$result .= join (" ", unpack ("H2"x 4, pack ("b32", $code)));
} else { # 未知フォーマット
unknown:
$result = "unknown";
}
return $result;
}