[[Arduino勉強会]]

#contents

2014/05/03からのアクセス回数 &counter;

** 赤外線リモコンのフォーマット [#r63ad23a]
赤外線リモコンには、以下の3つのフォーマットがありますが、ここではNEC方式を使用します。
(([[赤外線リモコンの通信フォーマット>http://elm-chan.org/docs/ir_format.html]]を参考にしました))

- NEC(現ルネサスエレクトロニクス)フォーマット
- AEHA(家製協)フォーマット
- SONYフォーマット

*** NECフォーマットについて [#b7be1649]
最もよく使われているNECフォーマットを使って実験することにします。

NECフォーマットでは、ビット情報は38KHz(1/3duty)で送信され、Frameと呼ばれるデータ単位
に続いてRepeatと呼ばれるFrameの終わりを表すデータがボタンが押されている間繰り返されます。

Frameは、以下の形式を持っています。データが1の時には、0.56msのON, 1.69msのOFFを送り、
データが0の場合には、0.56msのON, 1.69msのOFFを送ります。
- Leader(9msのON, 4.5msのOFF)
- Customer Code(16bitのカスタマコードをLSBから順に送信)
- Data(8bit)
- Dataのビット反転値(8bit)
- Stopビット

** Arduinoを使ってNECフォーマットのデータを送る [#sedc3517]
38KHzでオン・オフを繰り返すには、digitalWriteでは時間がかかるため、PORTDに直接ビットをセットします。
このため使用可能なデジタルピンは、0から7番までとなっています。

Arduinoを使って赤外線リモコンを送信する例題は、いくつかありましたが、今回参考にさせて頂いたのは、以下の3サイトです。
- Arduinoで遊ぶページの [[赤外線リモコンの実験>http://garretlab.web.fc2.com/arduino/lab/infrared_controller/index.html]]
- 戸田よろず研究所の[[赤外線リモコンの複製2(38 kHzをソフトウェアで制御)>http://tyk-systems.com/ircopy2/ircopy2.html]]
- セミコロンラボの[[Arduinoで赤外線リモコン送信>http://www.cjpr.sakura.ne.jp/arduino/irrcsend.html]]

ここでは、Arduinoで遊ぶページをメインに参考にさせて頂き、東芝REGZAの電源オン・オフを試みます。

*** リモコン側のブレッドボード [#q5ebb4dd]
ちょっと乱暴ですが、動作を確認するだけなので、赤外線LEDの線の長い方を直接2番と短い方をGNDに接続して試してみます。

今回使った赤外線LEDは、スイッチサイエンスの
[[SIR-34ST3F>http://www.switch-science.com/catalog/1484/]]
です。

&ref(IR_Send_Bread.png);


*** リモコン側のスケッチ [#hcac2606]
使用するスケッチは、以下の様にします。

#pre{{
class IrControlNecFormat {
  public:
    // constructor
    IrControlNecFormat(byte ledPin, byte custom0, byte custom1);
    void sendCommand(byte data);
  private:
    byte _ledPinMask;   // the pin mask which the LED is connected
    byte _custom0;  // custom code
    byte _custom1;  // custom code'
  
    void sendData(byte date);
    void on(int num);
};

IrControlNecFormat::IrControlNecFormat(byte ledPin, byte custom0, byte custom1) {
  _ledPinMask = 1 << ledPin;
  _custom0 = custom0;
  _custom1 = custom1;
 
  pinMode(ledPin, OUTPUT);  // set the ledPin as an OUTPUT
}

void IrControlNecFormat::sendCommand(byte data){
  on(346);                  // leader code(ON)
  delayMicroseconds(4500);  // leader code(OFF)
 
  sendData(_custom0);       // custom code
  sendData(_custom1);       // custom code
 
  sendData(data);           // data
  sendData(~data);          // ~data
 
  on(22);                   // stop bit
}

void IrControlNecFormat::sendData(byte data) {
  for(int i = 0; i < 8; i++) {
    on(22);
    int delayU_Sec = ( data & 0x01 ) ? 1690 : 565;
    delayMicroseconds( delayU_Sec );
    data = data >> 1;
  }
}

void IrControlNecFormat::on(int num) {
  for(int i = 0; i < num; i++) {
    PORTD |= _ledPinMask;
    delayMicroseconds(9);
    PORTD &= ~_ledPinMask;
    delayMicroseconds(17);
  }
}

// 赤外線LEDを2番ピンとGNDに接続
// 東芝REGZAのカスタマコードは、 0x40, 0xBF
IrControlNecFormat controller(2, 0x40, 0xBF);

void setup() {
}

void loop() {
  // REGZAの電源コードは、0x12
  controller.sendCommand(0x12);
  // 5秒間隔でオン・オフを繰り返す
  delay(5000);
}
}}

スケッチの以下の部分で2番ピンにカスタマコードとして、0x40, 0xBFとして、IrControlNecFormatクラスのインスタンスを生成します。
#pre{{
IrControlNecFormat controller(2, 0x40, 0xBF);
}}

これで、東芝REGZAのコントロールができるcontrollerができます。
これに、0x12(電源のコード)をsendCommandで送ると電源のオン・オフを繰り返します。

*** 実際に動かしてみる。 [#x5795c9f]
ブレッドボードを組み立てて、LEDをテレビに向けてリセットスイッチを押してみて下さい。
5秒間隔でオン・オフを繰り返します。((どうもREGZAでは電源オフで上手くできないことがあります))

&ref(IR_Send_Setting.png);


*** 他の操作方法 [#y823a5e1]
上記のスケッチのカスタマコードとコードを変えるといろんな処理ができるようになります。


以下のPDFに各種テレビのカスタムコードとデータの意味がまとめられています。
- [[NECフォーマット 赤外線リモコン コード表>http://www.ne.jp/asahi/o-family/extdisk/ATBextension/ATBIRrecvNEC/ATBIRrecvNEClst.pdf]]

** 赤外線受信機 [#f876ebf3]
赤外線リモコンのコードが公開されていない場合には、どうしたらよいのでしょう。

今回は、スイッチサイエンスの
[[RPM6938リモコン受光モジュール>http://www.switch-science.com/catalog/list/?keyword=RPM6938]]
を使って実験してみます。

&ref(RPM6938_master_10.jpg);

ピンの配置は、データシートから引用します。丸い突起のある面の左からRout, GND, Vccとなっています。


&ref(IR_Receiver.png);




*** 赤外線受光器のブレッドボード [#y6ebc8dd]
以下の様にブレッドボードを組み立てます。受光モジュールが同じものがなかったので、形の似たもので表示しています。

&ref(IR_Rec_Bread.png);



*** 赤外線コード解析 [#p18333c5]

Arduinoで遊ぶページの[[赤外線リモコンコード解析(NECフォーマット)>http://garretlab.web.fc2.com/arduino/make/infrared_sensor_nec_format/]]
に紹介されている赤外線リモコン解析スケッチが重宝します。

以下に引用して表示します。

#pre{{
#define COUNT_NUM 68

const int pin = 2;              /* 赤外線センサの出力を接続するデジタルピン */
unsigned long time[COUNT_NUM];  /* 時刻を格納する配列 */

void setup () {
  pinMode(pin, INPUT);
  Serial.begin(9600);
}

void loop () {
  int repeat = 0;
  int mode; /* 読み取るデータを決める */
  char str[64];
 
  /* 68回データを読み取る */
  mode = HIGH; /* 最初はHIGH */
  for (int i = 0; i < COUNT_NUM; i++) {
    while(digitalRead(pin) == mode) { /* 状態が変わるまで待つ */
        ;
    }
    time[i] = micros(); /* 時刻を記録する */
   
    if (mode == HIGH) { /* onとoffが交互に来るので,待つべき状態を変える */
      mode = LOW;
    } else {
      mode = HIGH;
    }
   
    /* リーダコードのoffが2.25msだと次にストップビットが来て終了 */
    /* 3000ms以下かどうかで判定 */
    if ((i == 3) && ((time[2] - time[1])) < 3000)  {
      repeat = 1;
      break;
    }
  }
 
  /* データの出力 */
  Serial.print("--------- BEGIN ---------\n");
 
  sprintf(str, "Leader:\n  HIGH %dms\n", (time[1] - time[0]));
  Serial.print(str);
  sprintf(str, "  LOW  %4dms\n\n", (time[2] - time[1]));
  Serial.print(str);
 
  if(repeat) {
    Serial.println("Repeat");
  } else {
    Serial.println("Custom Code:");
    print_data(2);
    print_data(18);

    Serial.println("");
 
    Serial.println("Data:");
    print_data(34);
    print_data(50);
   
    Serial.print("---------  END  ---------\n\n");
  }
}

void print_data(int start) {
  int code = 0;
  char str[32];
 
  sprintf(str, "  ");
  for (int i = 0; i < 8; i++) {
    if ((time[2 * i + start + 2] - time[2 * i + start]) > 1500) {
      code |= 1 << i;
      sprintf(&str[2 * (i + 1)], "1 ");
    } else {
      sprintf(&str[2 * (i + 1)], "0 ");
    }
  }
 
  sprintf(&str[17], ", %02x", code);
  Serial.println(str);
}
}}

*** 赤外線コード解析を動かしてみる [#f59e8621]
それでは、赤外線コード解析スケッチを動かしてみます。

&ref(IR_Recv_Setting.png);


シリアルモニターを起動し、テレビ(REGZA)の電源ボタンを押すと以下の様に返ってきます。

&ref(IR_Recv_monitor.png);

最初に作った通り、カスタマコード0x40, 0xBFとデータ0x12が受信されていることが確認できます。

これを使えば、他のリモコンの解析もできます。

*** 再確認 [#jd87e4b7]
小出さまのご質問で、再度実験をしてみました。

もしかしてCPUのクロックが影響しているのかと思い、今回はDuemilanoveを使いました。

&ref(confirm.png);

起動直後は、きちんと動いていましたが、蛍光灯の明かりを消すと急に以下の様にシリアスコンソールに
表示されました。

#pre{{
--------- BEGIN ---------
Leader:
  HIGH 2152ms
  LOW   324ms

Repeat
--------- BEGIN ---------
Leader:
  HIGH 80ms
  LOW  2572ms

Repeat
}}

出力を遡ってみると、東芝のリモコンを押したときには、きちんとCustom Codeの出力でていました。

#pre{{
--------- BEGIN ---------
Leader:
  HIGH 72ms
  LOW  -18344ms

Custom Code:
  1 1 1 1 1 1 1 1, ff
  0 1 0 1 1 1 1 0, 7a

Data:
  1 0 0 0 0 1 0 0, 21
  0 0 0 1 0 1 0 0, 28
---------  END  ---------
}}
** コメント [#n42e613d]
#vote(おもしろかった[22],そうでもない[0],わかりずらい[2])
#vote(おもしろかった[22],そうでもない[0],わかりずらい[3])


皆様のご意見、ご希望をお待ちしております。勉強会で分からなかったこと等、お気軽に問い合わせて下さい。

スパム防止に画像の文字列も入力してください。
- たいへん興味深く、赤外線コード解析作製したのですが、東芝のリモコンを入力しても際限なくスクロールしていきます。受信されてないのか?同期が取れてないのでしょうか? -- [[小出]] &new{2015-07-10 (金) 08:22:36};
- 小出さま、「再確認」を見てください。状況によってはシリアル画面が流れることがありましたが、Leaderの検出がずっと出ているみたいです。キーを押したときの情報がないか探してみてください。 -- [[竹本 浩]] &new{2015-07-10 (金) 21:19:08};
- ありがとうございます。調べてみます。arduino興味深いんですが まだまだ始めたばかりでして。 -- [[小出]] &new{2015-07-11 (土) 09:42:28};
- Leader が流れるので 箱の中に入れたりしたのですが、電池2本で動作するよう3.3Vのmini使ってまして、センサーの電圧も不足してますね。お恥ずかしい限りです。 -- [[小出]] &new{2015-07-13 (月) 08:24:53};

#comment_kcaptcha

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
SmartDoc