6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

赤外線リモコンのON/OFF専用コードを発見する

Last updated at Posted at 2022-01-08

#赤外線リモコンのON/OFF専用コードを発見する

赤外線リモコンを使ってTVを制御する時に困るのが「電源」ボタンがトグル動作だということです。ONしようと思ったらOFFになってしまったりという問題が起きます。
加えて、送受信エラーを防ぐために複数回の送信をするといったこともできません。

おそらくトグルではなくON専用、OFF専用のコードがあるだろうと思って調べてみました。

##検索してみる
赤外線リモコンの送信データはインターネットのどこかにあるだろうと思って調べてみたのですが、決定版的なものは見つかりませんでした。
以下は比較的多くのデータが登録されているので、まずはここで確認するのが良いと思います。

例えば、東芝のTVのON/OFF専用コードは codes/Toshiba/TV/64,-1.csv に記載されています。

ToshibaTV-SendPowerON.cpp
uint32_t data = irsend.encodeNEC(64,126); //device=64,function=126
irsend.sendNEC(data,32);

##探してみる
検査で見つからなかった場合の探し方がこの記事です。
方法は原始的で、片っ端から送ってみる方法です。

##範囲を絞る
探したかったAQUOSで、まずはコードを調べます。
ESP8266に赤外線リモコン読み取りデバイスを接続して、実際の赤外線リモコンのボタンを押して、表示されたコードから解析を開始します。

秋月電子で販売しているOSRB38C9AA(2個で100円)を使用しました。

このデバイスは3.3Vでも5.0Vでも利用でき、それぞれに応じた電圧のアウトプットをしてくれます。また、ノイズの少ない環境では外付けのコンデンサや抵抗なども必要なく、実際ESP8266に3本直結でOKでした。

読み取りに使ったソフトウエアは、ESP8266 / IRRemote8266 です。OSRB38C9AAのデータピンはソフトにあるようにGPIO14に接続します。

IRremoteESP8266 の examples/IRrecvDumpV2 をそのまま使って調べました。

AQUOSのデータはPanasonicの48bitデータフォーマットで、電源ON/OFFボタンは 0x555AF148688B でした。

stdout.txt
Protocol  : PANASONIC
Code      : 0x555AF148688B (48 Bits)
uint16_t rawData[99] = {3402, 1650,  440, 390,  446, 1234,  442, 394,  432, 1244,  440, 394,  442, 1228,  446, 396,  440, 1214,  462, 394,  442, 1234,  440, 394,  440, 1182,  486, 1234,  442, 396,  444, 1226,  446, 394,  442, 1230,  442, 1228,  
446, 1232,  442, 1230,  390, 478,  412, 390,  448, 390,  444, 1228,  446, 398,  438, 1236,  436, 392,  446, 392,  442, 1262,  412, 390,  448, 388,  392, 446,  440, 396,  444, 1226,  444, 1230,  448, 388,  444, 1262,  414, 396,  436, 396,  446, 388,  446, 1228,  446, 390,  444, 390,  446, 390,  440, 1234,  448, 392,  444, 1230,  442, 1230,  444};  // PANASONIC 555AF148688B
uint32_t address = 0x555A;
uint32_t command = 0xF148688B;
uint64_t data = 0x555AF148688B;

IRrecvDumpV2/V3 でリモコンデータを読み込んだ時、Protocol:'UNKNOWN' と表示された場合の Code: はrawDataを素直にコード化したものではありません。
UNKNOWNのコードを解析する場合、独自にRawdataを解析するプログラムを組む必要があると思います。

総当りで送るにしても、ある程度範囲を絞らないと現実的ではありません。最低限のトライで済ませるためにデータを解析します。
他のいくつかのコードはこんな感じ。

コード ボタン
0x555AF148688B 電源
0x555AF148724C 1
0x555AF148F244 2
0x555AF1480A43 3
0x555AF1488A4B 4
0x555AF1484A47 5

赤外線リモコンフォーマットの概要から推察すると、これは家製協(AEHA)フォーマットっぽいです。
http://elm-chan.org/docs/ir_format.html

555Aがカスタマーコード、5^5^5^A=Fでパリティ。
148688がデータで、1^4^8^6^8^8=Bがパリティです。

カスタマーコード パリティ コード パリイティ ボタン
555A F 148688 B 電源
555A F 148724 C 1
555A F 148F24 4 2
555A F 1480A4 3 3
555A F 1488A4 B 4
555A F 1484A4 7 5

まだコード部分が24bitもあります。
コード部分の 148 は固定っぽいので除いて12bit=4096個。これくらいなら試せそうです。

おそらく連続コードになっていそうな、1,2,3,4,5のコード部分に注目すると、エンディアンが逆だと推測できます。

コード エンディアン逆転 ボタン
688 116 電源
724 247 1
F24 24F 2
0A4 250 3
8A4 251 4
4A4 252 5

だいぶ構造が見えてきました。
エンディアンを逆にした番号順に試してみることにしました。

##送信装置
送信装置は秋月の赤外線LED OSI5FU5111C-40 をトランジスタでドライブします。

パルスで1Aまで流せて値段も手頃です。
ざっと400mAくらい流せるように抵抗を選んでみましたが、実測では300mA程度しか流れていませんでした。(電源かトランジスタの能力不足)
コンデンサはなくても動くと思います。
抵抗が4つなのは手持ちが1/4W抵抗だった対策なので、これもパルスなら大丈夫かもしれません。
手持ちがトランジスタだったので使いましたが、MOSFETのほうがいいと思います。

##総当り
ここからは全データ送信して総当りします。
イテレーションを早くするために、スキャンするコードはMQTTでリアルタイムに制御します。
ここでは自宅のMQTTブローカーを使っています。(Raspberry Pi)

IRTest.cpp
#include <Arduino.h>
#include <IRremoteESP8266.h>
#include <IRsend.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>   // MQTT

#define ASSETID 0x555a
#define DEVICEID  0x148

IPAddress MQTT_SERVER_IP(192, 168, 1, 111);  // 自宅のMQTTサーバ
#define MQTT_CLIENTID   "ESP8266-0000"
#define MQTT_SUBSCRIBE  "IR/#"

#define IR_LED  4
IRsend irsend(IR_LED);  // Set the GPIO to be used to sending the message.
WiFiClient wifiClient;

uint32_t  startData = 1;
uint32_t  endData = 0;
int   lastMillis;

// 4bit xor チェックディジット
uint8_t checkDigit(uint64_t data)
{
  uint8_t c = 0;
  for(int i=0;i<(64/4);i++){
    c ^= data & 15;
    data >>= 4;
  }
  return  c;
}

uint64_t makeData(uint64_t maker, uint64_t data)
{
  uint64_t  ret = 0;
  uint64_t  cd = checkDigit(maker);
  
  ret = maker << 32;
  ret |= (cd << (32-4));

  cd = checkDigit(data);
  ret |= (data << 4);
  ret |= cd;

  return  ret;
}

void callback(char *topic, byte *payload, unsigned int length) {
  for (unsigned int i = 0; i < length; i++) {
    Serial.print((char) payload[i]);
  }
  Serial.println();

  char  *buff = new char[length+1];
  memcpy(buff,payload,length);
  buff[length] = '\0';

  char  *nextPos;
  char  *p = buff;

  while(isspace(*p))  p++;
  startData = strtol(p,&nextPos,16);
  p = nextPos;
  while(isspace(*p))  p++;
  if( *p == '-'){
    p++;
    while(isspace(*p))  p++;
    endData = strtol(p,&nextPos,16);
  }
  else{
    endData = startData;
  }
  delete buff;
}

PubSubClient client(MQTT_SERVER_IP, 1883, callback,  wifiClient);

void reconnect(const char *clientID,const char *subscrive) {
  while (!client.connected()) {
      Serial.println("connect to MQTT");
      if (client.connect(clientID)) {
        Serial.println("connected");
        if(subscrive!=0){
          client.subscribe(subscrive);
        }
      }
      else {
        delay(5000);
      }
  }
}

// エンディアン逆転
uint32_t  endianRev(uint32_t d,int bit)
{
  uint32_t  ret = 0;
  for(int i=0;i<bit;i++){
    ret <<= 1;
    ret |= d&1;
    d >>= 1;
  }
  return  ret;
}

void setup()
{
  Serial.begin(115200);

  WiFi.mode(WIFI_STA);  
  WiFi.begin("SSID","PASSWD");
  while( WiFi.status() != WL_CONNECTED ) {
    delay(500);
  }
  irsend.begin();
  lastMillis = millis();
}

void loop()
{
  reconnect(MQTT_CLIENTID,MQTT_SUBSCRIBE);

  if( (millis()-lastMillis) >= 100 ){
    lastMillis = millis();
    if( startData <= endData ){
      uint32_t d = endianRev(startData,12) & 0xfff | (DEVICEID<<12);
      uint64_t  data;
      data = makeData(ASSETID,d);
      Serial.printf("%lx %llx\n",startData,data);
      irsend.sendPanasonic64(data,48,0);
      startData ++;
    }
  }

  client.loop();
  delay(1); 
}

##スキャンの指示はMQTTLensで
スキャンの指示はChromeのアプリのMQTT Lensを使いました。
IR/1 にメッセージとして、開始番号-終了番号 をPublishすると、100msごとに順番に赤外線信号を送ります。

image.png

TVを電源OFFにした状態でデータを送り始め、電源がONになったら、そのあたりの番号をさらに絞り込んでゆく地道な作業です。

##結果
結果として無事に電源ON、OFFのコードを発見できました。

コード (番号) ボタン
0x555AF148688B 116 ON/OFF
0x555AF148524E 24A ON
0x555AF148D246 24B OFF
6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?