LIRC の赤外線データについて拙くまとめる

## About
Raspberry Pi3 で赤外線LED をつかってリモコンを制御する記事は調べると色々あります。

Amazon Echo や Google Home などと連携しているものもあるが、
その根本の赤外線LED → 受光器の仕組みは変わりません。

その赤外線についてしらべたのでメモ的にまとめます。

*※ネットで調べただけのシロウトなので間違いなど指摘頂けると助かります。*

回路については赤外線LED へ流す電流が弱いと光が弱くなり、
受光器側との距離が短くなったり届かなかったりする。
そのため、どうやって電流を多く流すのか、
（電源を別にするとかラズパイ 5V から可能な範囲で電流をひっぱるかとか）
fritzing で回路設計しては試行錯誤してみたが、
だいたい先人の示した道のとおりでした。


## Detail
### LIRC のデータ
ラズパイ、赤外線LED で検索するとたいてい LIRC がでてくる。
インストールや使い方は多く紹介されているのだけれども、
そのなかででてくる送信データがなんなのかがよくわからない。
`irrecord` や `mode2` で学習、表示されるデータですね。

こういうやつ↓
（SHARP AQUOS 2013年くらい？の電源ONOFFボタン、以下は正規化したデータです）

```
3200 1600 400 400 400 1200 400 400
400 1200 400 400 400 1200 400 400
400 1200 400 400 400 1200 400 400
400 1200 400 1200 400 400 400 1200
400 400 400 1200 400 1200 400 1200
400 1200 400 400 400 400 400 400
400 1200 400 400 400 1200 400 400
400 400 400 1200 400 400 400 400
400 400 400 400 400 1200 400 1200
400 400 400 1200 400 400 400 400
400 400 400 1200 400 400 400 400
400 400 400 1200 400 400 400 1200
400 1200 400 9000
```

これがどういうデータでなんでテレビがついたり消えたりするのだろうと疑問でした。

### データがなにか？
まず上記データがなにかでいうと、
PPM の pulse、space の対で、それぞれのマイクロ（μ）秒単位での時間。

`3200 1600 400 400` とあるが、
これは `3200 μ秒のパルス`、 `1600 μ秒のスペース`、 `400 μ秒のパルス`、 `400 μ秒のスペース` となる。

LIRC は奇数個にしないとエラーになるが、上記データでの `9000` を `gap` で定義することになり、
最後のパルスのあとに `gap` の値分のスペースが送信される（送信というか LOW）。

### PPM とは？
> PPMとはパルス位相変調信号です。なんか難しいことばですが、要は赤外線の点灯時間と消灯時間の長さの組み合わせによってビット値を表現すると言う物です。

この PPM の点灯と消灯をマイコン（ラズパイ）では、 PWM で変調し赤外線LED の電力を制御して受光器側で PPM として受け取ることができるようようです。
パルス幅とパルス位置。

### PWM とは？
> PWM(Pulse Width Modulation)とは、半導体を使った電力を制御する方式の１つです。オンとオフの繰り返しスイッチングを行い、出力される電力を制御します。
> 
> 一定電圧の入力から、パルス列のオンとオフの一定周期を作り、オンの時間幅を変化させる電力制御方式を ＰＷＭ と呼びます。早い周期でスイッチングを行うことで、オンのパルス幅に比例した任意の電圧が得られます。これは、半導体がオンとオフ状態が最も損失が少ない(中間状態は損失多い)ことを利用した電力制御方式です。

[PWMとは | 東芝 半導体＆ストレージ製品](https://toshiba.semicon-storage.com/jp/design-support/e-learning/brushless_motor/chap3/1274512.html)

パルスは HIGH の時間、スペースは LOW の時間です。
なのでまずここでのざっくりとした理解として、
`3200 1600 400 400` は、
`3200 μ秒の HIGH`、 `1600 μ秒の LOW`、 `400 μ秒の HIGH`、 `400 μ秒の LOW` となります。

※実際にはキャリア周波数にのせるのでこのとおりではないのですがそれについては後述します。ここでの理解は上記で大丈夫です。

### テレビリモコン（家電協）の赤外線フォーマット
テレビリモコンの赤外線フォーマットは公開されているわけではなさそうです。
先人が解析してくれた結果を使う、自分で解析するなどが必要です。
わたしは解析することまではできないので、秋月電子さんの [これ](http://akizukidenshi.com/download/k4174_manual.pdf) を参考にして、
解析結果ありきで AQUOS の電源ONOFF についてみていきます。

SHARP AQUOS は家電協フォーマットであり、
電源 ONOFF は `0x55,0x5A,0xF1,0x48,0x68,0x8B` と表記してくれています。

さらに [1. 家製協フォーマットの信号データ合成 — 赤外線リモコンの信号定義データの合成 1.2 ドキュメント](http://shrkn65.nobody.jp/remocon/aeha.html) より、
家電協フォーマットは、 `リーダー部 ＋ データ部 ＋ トレーラー部` となります。

#### リーダー部
`T = 0.4ms` とすると、リーダー部は次から `HIGH 3.2 ms、LOW 1.6ms` となります。 

> ON(8T)→OFF(4T)、Tは0.35〜0.5msと規定されている。典型的には中央値0.425msを使用する。

秋月電子さんの[これ](http://akizukidenshi.com/download/k4174_format.pdf)では、家電協フォーマットは `HIGH 3.2ms、LOW 1.6ms` となっています。
引用では `T=0.425ms として、ON(3.4ms)→OFF（1.7ms）` としています。
このへんの T の値からくる差はありますが、どちらであっても `ON(8T)→OFF(4T)` となっており、T が範囲内であればよいみたいです。（アバウトですね。。。）
計算が楽でわかりやすいので `T=0.4ms` にあわせます。

#### データ部
> 3バイト以上・任意バイト数の送信データ。各バイトはLSB first。
> データ「0」は ON(1T)→OFF(1T)
> データ「1」は ON(1T)→OFF(3T)
> なお、データの内容は
> 
> 1〜2バイト目がカスタムコード (ベンダー/機器の識別)
> 3バイト目以降がデータコード (コマンド等)

**データ「0」**は `0.4ms HIGH → 0.4ms LOW`、
**データ「1」**は `0.4ms HIGH → 1.2ms LOW`、
となります。

LSB first とありますが、元の仕様として決められているコードがイマイチわからず、
秋月電子さんのものは LSB first にしてくれた状態？でしょうか…。
`0x55,0x5A,0xF1,0x48,0x68,0x8B` を2進数にすると

```
(LSB?)0101 0101 0101 1010 1111 0001 0100 1000 0110 1000 1000 1011(MSB?)
```

となります。
上記のデータにあてはめて考えていくと、

```
「0」 0.4ms HIGH → 0.4ms LOW
「1」 0.4ms HIGH → 1.2ms LOW
「0」 0.4ms HIGH → 0.4ms LOW
「1」 0.4ms HIGH → 1.2ms LOW

「0」 0.4ms HIGH → 0.4ms LOW
「1」 0.4ms HIGH → 1.2ms LOW
「0」 0.4ms HIGH → 0.4ms LOW
「1」 0.4ms HIGH → 1.2ms LOW

「0」 0.4ms HIGH → 0.4ms LOW
「1」 0.4ms HIGH → 1.2ms LOW
「0」 0.4ms HIGH → 0.4ms LOW
「1」 0.4ms HIGH → 1.2ms LOW

「1」 0.4ms HIGH → 1.2ms LOW
「0」 0.4ms HIGH → 0.4ms LOW
「1」 0.4ms HIGH → 1.2ms LOW
「0」 0.4ms HIGH → 0.4ms LOW
・
・
・
```

となります。
ms を μs にすると・・・

```
「0」 400μs HIGH →  400μs LOW
「1」 400μs HIGH → 1200μs LOW
「0」 400μs HIGH →  400μs LOW
「1」 400μs HIGH → 1200μs LOW
```

これを pulse,space で書き出すと

```
400 400 400 1200 400 400 400 1200
```

なんかみたことある値になってきました。
これが LIRC のデータとして扱っているものになります。

#### トレーラー部
> ON(1T)→OFF(nn)
> nnは8ms以上と規定されている。Panasonic製デジタルチューナー付属のリモコンの場合は約75ms。

とあるので、いったんかりで次のようにしておきます。

```
400 1200 400 9000
```

#### まとめると
まずリーダー部の `3200 1600` があり、
次にデータ部が `400 400...` からはじまり、
トレーラー部の `400 1200 400 9000` でおわります。

```
3200 1600 400 400 400 1200 400 400
400 1200 400 400 400 1200 400 400
400 1200 400 400 400 1200 400 400
400 1200 400 1200 400 400 400 1200
400 400 400 1200 400 1200 400 1200
400 1200 400 400 400 400 400 400
400 1200 400 400 400 1200 400 400
400 400 400 1200 400 400 400 400
400 400 400 400 400 1200 400 1200
400 400 400 1200 400 400 400 400
400 400 400 1200 400 400 400 400
400 400 400 1200 400 400 400 1200
400 1200 400 9000
```

このようなデータとなりました。
実際に `irrecord` で学習したデータとつきあわせてみると、
実際のデータは `3425 1583 412 408...` のように少しずつ違いはありますがおおよそ同じ値となりました。

LIRC を使うのであればここでおわりです。

### PWM とキャリア周波数（補足）
LIRC や WiringPi のように、 PWM を独自で実装するときにおそらく必要になることですが、
赤外線はキャリア周波数にのせて送信されます。
[FAQ 1007798 : 赤外線リモコンの信号はどうなっているのですか? | Renesas Customer Hub](https://ja-support.renesas.com/knowledgeBase/17796063)

> onの期間はその全ての期間連続して赤外線を出しているわけではありません。
> 一定の周波数 (キャリア周波数) で赤外線を出している期間と出していない期間を繰り返しています。
> このキャリア周波数は 38KHzが標準です。
> また、そのデューティ比は 1/3となります。
> このように設定されているのは、できるだけ消費電力を抑えるためです。

上記までのデータをことばそのままの意味で受け取れば、
3200 μ秒の HIGH、 1600 μ秒の LOW なのですが、
引用より 38kHz のキャリアにのせるので実際には違っています。

38kHz でデューティー比 1:3 （リモコンの仕様でそうきまっているらしい）
（パルス幅が 1/3 ということ、パルス幅 1/4 と信号なし 3/4 ではないことに注意）、
周期 = 1 / 周波数、
周期 = 1 / 38000 = 0.000026316 秒、
0.000026316 秒＝26μs、
これが PWM の周期です。
この 26 μ秒で HIGH と LOW を表現します。

**HIGH** は、 `(26/3)*1=8.666666667≒9μs の HIGH`、 `26-9=17μs の LOW` で表現され、
**LOW** は `26μ秒の LOW` で表現されます。

たとえば、 3200 μs のパルス＝HIGH は、
`3200 / 26 = 123.076923077≒123` で 123回の `HIGH（9μs HIGH、１６μs LOW）` で表現されます。
1600 μs のスペース＝LOW は、
`1600 / 26 = 61.538461538≒61` で 61回の `LOW(26μs)` で表現されます。


### おまけ１
SHARP AQUOS のテレビの電源オンオフ、
付属の純正リモコンで一度テレビをつけてから、マイコンからオンオフするとうまくいきます。
それなのに、オフにしてしばらく放置してて、マイコンからオンオフするとうまくいきません。

これはいかに、と思って `mode2` でみてみると送信コードはやっぱりあっていました。
違っていたのは、そのコードをマイコンは一回だけ送信していたが、
リモコンは２回？か３回くらい送信していました。
なので `irsend SEND_ONCE "tv" "power" && irsend SEND_ONCE "tv" "power"` とするとつきました。
なんか一回だけのはノイズかもって判断で２回連続でこないとテレビつかないような制御があるんかもですね。

### おまけ2
SONY のテレビは電源オンオフがマイコンからできなかった。
SONY フォーマットが家電協とは違うといっても原理的にはそんな間違ってはないと思えるようになり、
ネチネチ見てたら `mode2` でやったらこっちは 4回同じコードがとんでた。
なのでいかりの `irsend SEND_ONCE "sonytv" "power" && irsend SEND_ONCE "sonytv" "power"` でついた。
あ、 `SEND_ONCE` って回数指定できます？もしかして…。
と思いつつ。


## Reference
- [FUTABA HOME](http://www.256byte.com/remocon.htm)
- [FUTABA HOME + BLOG - リモコン解析企画　第１弾](http://www.256byte.com/2006/10/post_2.html)
- [赤外線リモコンの通信フォーマット](http://elm-chan.org/docs/ir_format.html)
- [赤外線リモコン信号｜東工大おやぢ](https://ameblo.jp/aoijf2/entry-11261684880.html)
- [k4174 manual](http://akizukidenshi.com/download/k4174_manual.pdf)
- [k4174 format](http://akizukidenshi.com/download/k4174_format.pdf)
- [赤外線リモコンの信号定義データの合成 — 赤外線リモコンの信号定義データの合成 1.3.1 ドキュメント](http://shrkn65.nobody.jp/remocon/)
- [赤外線リモコン受信・送信～LIRCはあきらめましょう | Raspberry Pi 研究室 | Feijoa.jp](http://www.feijoa.jp/laboratory/raspberrypi/infrared/)


黒豆で、wireshark で QUIC のぞいて、バイナリコピペでそのまま動かなくて試行錯誤した日々は遠くなりました。
おわり。