Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
27
Help us understand the problem. What is going on with this article?
@dokkozo

Arduinoで家にある赤外線リモコン全部解析

概要

家電を操作する"リモコン"は内蔵の赤外線LEDの光り方によって信号を家電に伝送しています. その信号を解析して, Arduinoのようなマイコンで赤外線LEDを同じように光らせれば, Arduinoから家電を操作できます. この記事はその第一歩, 家にある家電製品のリモコン信号をひたすら解析した方法と, 解析した結果を載せています.

本記事の想定する読者

  • リモコン信号を解析する方法を知りたい
  • リモコン信号を解析するコードが知りたい
  • 解析結果が知りたい

赤外線信号のフォーマット

  • 赤外線信号のフォーマットについては多くのウェブページに説明があり, その多くでこちらが参照されています. この記事以上にわかりやすく説明できないのでこれを見てください.
  • 英語記事ですが上記記事内でも引用されているこちらには受信側の仕組みも解説されています.
  • 簡単にまとめると,
    • 赤外線リモコンでは最初にLeaderと呼ばれる部分があり, それに続いて0/1の信号が1Byteずつエンコードされて送られる.
    • 変調単位T[us]という変数があって, 1を送る時はhighを1Tのあとlowを1T, 0を送る時はhighを1Tのあとlowを3Tのようにデコードされる
    • LeaderはHighとLowが既定の長さ送信されるパターンで, それぞれの長さはフォーマットによって異なる. たとえばhighを16T, lowを8Tなど

赤外線信号のデコード方法

材料

素子 型番 単価[円] リンク
赤外線リモコン受信モジュール OSRB38C9AA 50 秋月
Arduino Uno Arduino Uno Rev3 2,940 秋月

回路

赤外線リモコン受信モジュールをArduinoに直で繋ぐだけ. 受信モジュールの足は左から信号, GND, Vccです. 信号はGPIO2につないでいます

スケッチ

  • 赤外線リモコンを解析/送信するためのIRremoteと呼ばれるライブラリが存在しているためそれを使うのが定石ですが, ある一定の長さ以上の信号を解析できない制約があり, 以下に解析した家電の中ではエアコンの信号は解析できません.
  • ということで解析するためのプログラムを書きました. こちらのコードを改変して使いやすくしたものです.
#define maxLen 800 // 信号の最大長
#include <stdio.h>

// リモコン信号を読むためのコード
// 参考 https://gist.github.com/chaeplin/a3a4b4b6b887c663bfe8

// 受光モジュールはGPIO2に接続
// 受信内容はシリアルモニタで確認

volatile unsigned int irBuffer[maxLen]; // stores timings - volatile because changed by ISR
volatile unsigned int x = 0; // 入ってきた信号の長さ Pointer thru irBuffer - volatile because changed by ISR

void setup() {
  Serial.begin(115200);
  attachInterrupt(0, rxIR_Interrupt_Handler, CHANGE);
}

void loop() {
  delay(5000);
  if (x) { // same as if x >= 1
    detachInterrupt(0);
    for (int i = 1; i < x; i++) {
      irBuffer[i - 1] = irBuffer[i] - irBuffer[i - 1];
    }
    x--;

    // 9000usより長い信号があった場合は, その次からデコードする
    // たとえばエアコンのリモコンの場合, 13000usのインターバルをはさんで2回信号が送信されているが, 後半だけあればエアコンを操作できるようなので
    // 前半は表示しない. 
    int startpoint = 0;
    for (int i = 0; i < x; i++) {
      if(irBuffer[i]>9000){
        startpoint = i+1;
      }
    }

    if (x - startpoint < 30){ //短すぎる信号はノイズなのでカット
      attachInterrupt(0, rxIR_Interrupt_Handler, CHANGE);
      return;
    }

    //raw array
    Serial.print(F("Raw: ("));
    Serial.print((x-startpoint));
    Serial.print(F(")"));
    Serial.print(F("["));
    for (int i = startpoint; i < x; i++) {
      Serial.print(irBuffer[i]);
      Serial.print(F(", "));
    }
    Serial.println(F("]"));

    // hex array. 8T 4T { } T
    Serial.print(F("hex: ("));
    Serial.print((x - startpoint - 3)/2); // length of signal [bit]
    Serial.print(F(") {"));

    int cnt = 0; // digit
    int hexval = 0; // sum of 8digits C_0 C_1 ... C_7

    for (int i = startpoint + 2; i < x - 1; i++) {
      if ((i - startpoint)%2 == 1){
        if (irBuffer[i]> 900){ // T=450usならおよそ2Tを閾値としていることになる
          //Serial.print(1);
          hexval += 1 << cnt;
        }else{
          //Serial.print(0);
        }
        cnt++;
        if (cnt == 8){
          if(hexval < 16){ // padding
            Serial.print(0);
          }
          Serial.print(hexval, HEX);
          Serial.print(F(" "));
          cnt = 0;
          hexval = 0;
        }
      }
    }
    x = 0;
    Serial.println(F("}"));

    attachInterrupt(0, rxIR_Interrupt_Handler, CHANGE);
  }

}

void rxIR_Interrupt_Handler() {
  if (x > maxLen) return; //ignore if irBuffer is already full
  irBuffer[x++] = micros(); //just continually record the time-stamp of signal transitions
}

使い方

  • Arduino Unoにプログラムを書きこんでシリアルモニタを開き, 受信モジュールに向かってリモコンを押すと, デコードされたhex列が表示されます.
    • 前述の信号フォーマットを見るとわかるように, バイナリから16進数に直すときはC0, C1,...,C7の順, つまり1の位が一番左で2の位,4の位,...,128の位という順になります. なのでバイナリで01100011は16進数でC6です.
  • Rawを見ると, 信号のhigh/lowの生の長さが表示されています. ここから変調単位TとLeaderの長さを計算できます.
    • たとえばRawが7040, 3520, 440, 440, 440, 1320, 440, 1320,...ならT=440us, Leaderは16T, 8T, そのあとに信号の011が続いています

解析結果

まとめ

家電名 メーカー 型番 T [us] Leader_high[T] Leader_low[T] signal[Byte]
オイルヒーター Delonghi RHJ75V0915 554 16 8 4
扇風機 Toshiba F-ALX60 560 16 8 4
扇風機 Panasonic F-CS338 842 4 4 3
テレビ Sharp LC-22K7 420 8 4 6
シーリングライト Panasonic HK9493 435 8 4 5
エアコン Panasonic CS-228-CF 437 8 4 19
エアコン MITSUBISHI 不明 428 8 4 18
  • Panasonicのシーリングライトのみリモコンの型番です.

Delonghiヒーター

command hex
on/off 00fe00ff
+ 00fe04fb
- 00fe05fa
eco 00fe01fe

Toshiba Fan

command hex
on/off 4bb412ed
random 4bb415ea
wind 4bb409f6
ontimer 4bb40bf4
offtimer 4bb40af5

Panasonic Fan

command hex
on/off 3b487c
1/fゆらぎ 3b478c
首振り 7b4788
wind+ fb4780
wind- fb45a0
明るさ控えめ 7b45a8
温度センサ運転 7b4698
入りタイマ bb45a4
切りタイマ bb4784

Sharp TV

command hex
on/off aa5a8f1216d1
1 aa5a8f124e32
2 aa5a8f124f22
3 aa5a8f1250c2
4 aa5a8f1251d2
5 aa5a8f1252e2
6 aa5a8f1253f2
7 aa5a8f125482
8 aa5a8f125592
9 aa5a8f1256a2
0/10 aa5a8f1257b2
11 aa5a8f125842
12 aa5a8f125952
decide aa5a8f1252d1
digital aa5a8f128982
bs aa5a8f128ab2
cs aa5a8f128ba2
reclist aa5a8f12ad3f
chup aa5a8f1211a1
chdown aa5a8f121291
sndup aa5a8f1214f1
snddown aa5a8f1215e1
chinput aa5a8f121381
chlist aa5a8f1260f2
return aa5a8f12e401

Panasonic Ceiling Light

command channel1 channel2 channel3
on 2c52092d24 2c5209353c 2c52093d34
off 2c52092f26 2c5209373e 2c52093f36
full 2c52092c25 2c5209343d 2c52093c35
night 2c52092e27 2c5209363f 2c52093e37
high 2c52092a23 2c5209323b 2c52093a33
low 2c52092b22 2c5209333a 2c52093b32
warm 2c523991a8 2c523995ac 2c523999a0
cool 2c523990a9 2c523994ad 2c523998a1

Panasonic Airconditioner

  • 信号を解析したところ 8T, 4T, 8Byte, 1T, 10ms, 8T, 4T, 19Byte, 1Tのような信号が出ていたが, 前半の8T, 4T, 8Byte, 1T部分が無くてもエアコンは操作できるようなので前半は省略. 後半の8T, 4T, 19Byte, 1Tの19Byteの部分のみ記載
  • エアコンの信号はこれまでの家電のリモコンと異なり, ボタンを押した後リモコンに表示されているすべての情報を送付している

1Byteごと解説

  • 1-5B
    • 0220e00400
  • 6B
    • 電源on1/off0 入りタイマあり1/なし0 切りタイマあり1/なし0 冷房1100/暖房0100/ドライ0010
  • 7B 温度
    • 0 温度1位 2位 4位 8位 16位 32位 64位
  • 8B
    • 00000001 (80)
  • 9B
    • 風向1000/0100/1100/0010/1010/1111 風量1100/0010/1010/1110/0101
  • 10B
    • 00000000 (00)
  • 11B-13B 入り/切りタイマ時間, タイマなし(000660)
    • 入りタイマ
    • 00 + 8bit + 000000 11110000
    • 切りタイマ
    • 00010110 100000 + 8bit + 00
    • 8bit:時間 0~11
    • 反転4bit + 4bit
    • 1,2,4,8
    • 0: 1111 0000
    • 1: 0111 1000
  • 14B
    • 静か/パワフル/指定なし 00000100/10000000/00000000 + 内部クリーン00000010
  • 15B
    • 0 温度上限下限1/そうでなければ0 00000 小数点以下.5あり1/なし0
    • 温度上限下限を表しているのではなく, 単に音を2回鳴らすかどうかのフラグ
  • 16B
    • 00000001
  • 17B
    • 00000000
  • 18B
    • 01101000
  • 19B
    • checksum 1-18Biteの和
    • C0 C1 ... C7 の方法で和を取る

MITSUBISHI Airconditioner

  • Panasonicのエアコンと同様に信号の前半部分は省略
  • 1-5B
    • c4d3648000/23cb260100
  • 6B
    • 入り0x20/切り0x00
  • 7B
    • 冷房/除湿/暖房 18/10/08
  • 8B
    • 温度-16 (16-31/0x00-0x0F) 除湿の場合は0x08
  • 9B
    • 除湿 弱/標準/強 0x34/32/30 冷房/暖房の場合は0x36/0x30
  • 10B
    • 音 2回/1回/0回 +80/+40/+00 (上位2bit) 電源on/off時は00なら消音, それ以外なら既定の音が鳴る
    • 風速 自動/1/2/3 +00/01/02/03 (中位3bit)
    • 風向 自動/1/2/3/4/5/スイング +00/08/10/18/20/28/38 (下位3bit)
  • 11B

    • 0x00
  • 12B

    • 切りタイマー時間 0.5時間 = 0x03. 0.5h-12.0h 0x03-0x48. 別のタイマー使用時/タイマー未使用時は0x00
  • 13B

    • 入りタイマー時間 0.5時間 = 0x03. 0.5h-12.0h 0x03-0x48. 別のタイマー使用時/タイマー未使用時は0x00
  • 14B

    • タイマー変更(タイマー種類の変更も時間の変更も) あり/なし +0x01/00
    • タイマー状態 切り/入り/なし +0x02/04/00
  • 15B

    • 内部クリーン ON/OFF 0x04/0x00
  • 16B

    • パワフル/なし 0x01/0x00
  • 17B

    • 0x00
  • 18B

    • チェックサム

備考

  • Panasonicのシーリングライトの信号を受信した際のピッというスピーカーは外せる.(自己責任でお願いします)

本記事の続き

参考にさせていただいた記事など

27
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
27
Help us understand the problem. What is going on with this article?