たくさんの自由帳
Androidのお話
たくさんの自由帳
投稿日 : | 0 日前
文字数(だいたい) : 2868
この記事の赤外線パターン解説編?
多分使えます。
https://nec-ir-pattern-hex.netlify.app/
ソースコード(Kotlin/JS製Webアプリ
):https://github.com/takusan23/IRPatternHex
スタートはこれ
[8925, 4540, 514, 626, 514, 1730, 514, 626, 514, 626, 514, 626, 514, 626, 514, 626, 514, 1730, 514, 1730, 514, 626, 514, 1730, 514, 1730, 514, 626, 514, 1730, 514, 1730, 514, 626, 514, 626, 514, 1730, 514, 1730, 514, 1730, 514, 1730, 514, 1730, 514, 626, 514, 1730, 514, 1730, 514, 626, 514, 626, 514, 626, 514, 626, 514, 626, 514, 1730, 514, 626, 514]
そしてゴールはこれです。
0x41b67d82
調べていると赤外線のパターンではなく、データは 0x~ です!
みたいなのを見かけたので調査。
合っているかは知りません。
参考にしました:
http://shrkn65.nobody.jp/remocon/nec.html
http://elm-chan.org/docs/ir_format.html
https://qiita.com/katsumin/items/517cd9fbe66e26d72fa7
https://god-support.blogspot.com/2020/08/nec.html
いくつかあるフォーマット(NEC / 家製協(AEHA) / SONY)の中から今回はNECフォーマットの解説を。
赤外線LEDを8.925ミリ秒
ONにして、4.540ミリ秒
OFFにして、5.14ミリ秒
ONにする...って意味です。
[8925, 4540, 514, 626, 514, 1730, 514, 626, 514, 626, 514, 626, 514, 626, 514, 626, 514, 1730, 514, 1730, 514, 626, 514, 1730, 514, 1730, 514, 626, 514, 1730, 514, 1730, 514, 626, 514, 626, 514, 1730, 514, 1730, 514, 1730, 514, 1730, 514, 1730, 514, 626, 514, 1730, 514, 1730, 514, 626, 514, 626, 514, 626, 514, 626, 514, 626, 514, 1730, 514, 626, 514]
NECフォーマット
の場合はおおよそ562
が使われています。リモコンによってばらつきがあると思う。
ので、Tの1倍
って書いてあった場合は、T*1 = 562
、Tの3倍
って書いてあった場合はT*3 = 1686
ってことです
+---------------------------------------------------------------------------------------------------
| リーダー部 2bit | データ部 32bit | トレーラー部 1bit |
+---------------------------------------------------------------------------------------------------
上記のアスキーアートのようになってます。良くわからんと思いますのでもう少し解説続けます。
最初のON、OFFのデータがリーダー部となっております。
NECフォーマットの場合おおよそ、ONは9ミリ秒(Tの16倍)
、OFFは4.5ミリ秒(Tの9倍)
に近い値になるみたいです。
実際のデータ(省略版)を見てもNECフォーマットっぽいです。(NECのシーリングライトなのでそれはそう)
[
8925, 4540, // ここが 9000 , 4500 ぐらいならNECフォーマット
514, 626,
514,
]
3番目からデータになっています。ここで見てほしいのは右と左のペア(下のコードでは隣同士に整形しておいた)です。
実際のデータを見るとなんか近い値と明らかに2、3倍になってる数値が見えてくると思います。
[
8925, 4540, // リーダー部 NECフォーマットと判明
514, 626, // 近い数値だな...
514, 1730, // 3倍ぐらいになってる!?
514, 626, // 近い数値だな...
514
]
NECフォーマットの仕様では、
ONが Tの1倍 -> Tの1倍
の順番になってて、データは0
OFFが Tの1倍 -> Tの3倍
の順番になっていて、データは1
になっているみたいです。?
実際のデータにコメントとして書き足すと
[
8925, 4540, // リーダー部
514, 626, // ON データ0
514, 1730, // OFF データ1
514, 626, // ON データ0
514
]
って感じになっています。514
->626
で正確に1倍にはなっていないのですが多分データ0で合ってます。
この0
と1
がNECフォーマットでは32個続きます(32bit
)
16bit
で区切ります。
区切って、前の16bit
がカスタマーコード、後ろの16bit
がデータです。
0100000110110110 0110010110011010
後ろの16bit
は、さらに8bit
に分けることが出来ます。
01100101 10011010
前の8bit
がデータ、後ろの8bit
は前の8bit
の反転になっていて、正しいデータか検証出来るようにしているそうです。(0なら1、1なら0)
01100101 // 前の8bit
10011010 // 後ろの8bit。前の8bitと比べて0と1が反転している。
よくわからん。取得したデータの最後のTの1倍
の値がそうだと思う。
取得したデータの中から、まずリーダー部(最初の2個)とトレーラー部(最後の1個)を消します。
解説用に短くしています。
[8925, 4540, 514, 626, 514, 1730, 514, 626, 514]
こんな感じ?
[514, 626, 514, 1730, 514, 626]
次に、[1,2]
、[3,4]
...のようにまとめていきます
[[514, 626], [514, 1730], [514, 626]]
その後、まとめた数値を比較して、最初の値を2倍してももう一方が大きい場合は1
、そうでない場合は0
を入れていきます
仕様ではTの3倍
です。がばらつきがあるのでしゃーない。
[
[514, 626], // 2倍以上ではない => 0
[514, 1730], // 2倍以上 => 1
[514, 626] // 2倍以上ではない => 0
]
こんな風に
[0, 1, 0]
そしたらくっつけて完成です。お好みで16進数に変換してもいいと思う。
let bin = "010";
この場合は、16進数(もしくは2進数)の赤外線のデータがどこのフォーマットのものなのかがわかっている必要があります。
16進数のデータにはリーダー部が含まれていないため分かりません。
今回はNECフォーマット
だとして、T
は562
という設定で行きます。
まず、配列を用意して、リーダー部を追加しておきます。
[8992, 5058]
そしたら、16進数の場合は2進数に戻します。
戻したら、データ1
が[Tの1倍
,Tの3倍
]、0
が[Tの1倍
,Tの1倍
]であることがNECフォーマットの仕様に書いてあるので、そのとおり作ります。
let bin = "010";
[
8992, 5058,
562, 562, // 0
562, 1686, // 1
562, 562 // 0
]
最後にストップビットとして配列の最後にTの1倍
を入れれば終わり。
[8992, 5058, 562, 562, 562, 1686, 562, 562, 562]
fun main() {
val pattern = listOf(
8925, 4540, 514, 626, 514, 1730, 514, 626, 514, 626, 514, 626, 514, 626, 514, 626, 514, 1730, 514, 1730, 514, 626, 514, 1730, 514, 1730, 514, 626, 514, 1730, 514, 1730, 514, 626, 514, 626, 514, 1730, 514, 1730, 514, 1730, 514, 1730, 514, 1730, 514, 626, 514, 1730, 514, 1730, 514, 626, 514, 626, 514, 626, 514, 626, 514, 626, 514, 1730, 514, 626, 514
)
// グループ化
val onOffGroupList = patternToOnOffPairList(pattern)
println("赤外線パターン ---")
println(onOffGroupList)
// データ部2進数変換
val bin = patternToBinCode(pattern)
println("データ部 2進数 ---")
println(bin)
// データ部16進数変換
val hex = binStringToHexString(bin)
println("データ部 16進数 ---")
println(hex)
}
/**
* [8955, 4510]を[Pair(8955, 4510)]にしていく関数。戻す際はflatMapを使ってください。
* */
fun patternToOnOffPairList(patternList: List<Int>) =
patternList
.toMutableList()
.mapIndexed { index, _ ->
if ((index + 1) % 2 != 0) {
Pair(patternList[index], patternList.getOrNull(index + 1) ?: 0)
} else null
}
.filterNotNull()
/**
* [patternList]のデータ部を2進数にして返す。
*
* ONとOFFが1:3の比率(だいたい)の場合は1、違う場合は0になる
*
* 32bit(32文字)になるはず
*
* リーダー部(9000,4500)(だいたいONが9000、OFFが4500)の次からがデータ部なので
*
* 例
*
* (607, 520) =(ON607、OFF520) なら 0
* (607, 1703) =(ON607、OFF1703)なら 1
*
* 変換例
* 010000 ...
*
* @param patternList ON/OFFパターン配列
* */
fun patternToBinCode(patternList: List<Int>) =
patternToOnOffPairList(patternList)
.drop(1) // リーダー部を消す
.dropLast(1) // ストップビット部も消す
.map { (on, off) -> if (off > on * 2) "1" else "0" } // ONの2倍以上で T*3 ってことで
.joinToString(separator = "") { it }
/**
* 2進数からパターン生成。先頭にトレーラーつけて、最後にストップビットを入れる
*
* @param t 変調。NECなら 562 前後?
* @param binCode 2進数
* */
fun binCodeToPattern(t: Int, binCode: String) =
listOf(t * 16, t * 9) + binCode.toList().flatMap { if (it == '1') listOf(t * 1, t * 3) else listOf(t * 1, t * 1) } + listOf(t * 1) // 1なら[T*1,T*3]、0なら[T*1,T*1]を配列に足していく
/**
* 2進数の文字列を16進数の文字列に変換する
*
* "1010"を"A"に変換する
*
* @param binString 変換前2進数の文字列
* */
fun binStringToHexString(binString: String) = "0x" + binString.toInt(2).toString(16)
出力例です。
赤外線パターン ---
[(8925, 4540), (514, 626), (514, 1730), (514, 626), (514, 626), (514, 626), (514, 626), (514, 626), (514, 1730), (514, 1730), (514, 626), (514, 1730), (514, 1730), (514, 626), (514, 1730), (514, 1730), (514, 626), (514, 626), (514, 1730), (514, 1730), (514, 1730), (514, 1730), (514, 1730), (514, 626), (514, 1730), (514, 1730), (514, 626), (514, 626), (514, 626), (514, 626), (514, 626), (514, 1730), (514, 626), (514, 0)]
データ部 2進数 ---
01000001101101100111110110000010
データ部 16進数 ---
0x41b67d82
長くなるのでGitHubに置いておきますが、データ部とかも見れる完全版も置いておきます。