いじわるリモコン
An IR trick sketch.

 今回は赤外線リモコンを簡単にハックして、ちょっと意地悪なデバイスを作る Arduino スケッチを公開します。

 赤外線リモコンはテレビやエアコンで日常的に使われていますが、この信号の送受信をマイコンプログラミングするのは少々めんどくさかったりします。

 ここでは、Arduinoでサクッと赤外線リモコン信号を操作するために東京デバイセズのIRシールドを使ってみたいと思います。このシールドは、赤外線リモコン信号をシリアルに変換したり、シリアル信号から赤外線リモコン信号を送信したりできるものです。Arduinoシールドでありながら、FTDIケーブル用の端子を使うとPCに直接接続できるようにもなっています。

 公開されているデータシートにIRパケットと呼ばれているシリアルデータの仕様があるので、IRパケットを送受信できるArduinoスケッチを書いてみましたので公開します。

// IR packet
int hh,hl;
byte d1h,d1l;
byte d0h,d0l;
byte th,tl;
int len;
byte dat[50];

// last receive time
unsigned long last = 0;

int read_byte(){
  while(Serial.available() == 0);
  return Serial.read();
}

boolean rcv_pkt(){
  int i;
  byte cs = 0;
  
  if(read_byte() != 0xff) return false;
  cs += (i = read_byte());  hh = i * 256;
  cs += (i = read_byte());  hh += i;
  cs += (i = read_byte());  hl = i * 256;  
  cs += (i = read_byte());  hl += i;
  cs += (d1h = read_byte());
  cs += (d1l = read_byte());
  cs += (d0h = read_byte());
  cs += (d0l = read_byte());
  cs += (th = read_byte());
  cs += (tl = read_byte());
  cs += (i = read_byte());  len = i * 256;
  cs += (i = read_byte());  len += i;
  if (len > 400 || len <= 0) return false;
  for(i = 0;i < bytes(); i++){
    cs += (dat[i] = read_byte());
  }
  if(read_byte() != cs) return false;
  
  return true;
}

int bytes(){
  if(len == 0) return 0;
  return (len - 1) / 8 + 1;
}

byte checksum(){
  byte cs = 0;
  int i;
  
  cs += (byte)(hh >> 8) + (byte)(hh & 0xff);
  cs += (byte)(hl >> 8) + (byte)(hl & 0xff);
  cs += d1h + d1l + d0h + d0l + th + tl;
  cs += (byte)(len >> 8) + (byte)(len & 0xff);
  for(i = 0;i < bytes(); i++) cs += dat[i];

  return cs;
}

void snd_pkt(){
  Serial.write((byte)0xff);
  Serial.write((byte)(hh >> 8));
  Serial.write((byte)(hh & 0xff));
  Serial.write((byte)(hl >> 8));
  Serial.write((byte)(hl & 0xff));
  Serial.write(d1h);
  Serial.write(d1l);
  Serial.write(d0h);
  Serial.write(d0l);
  Serial.write(th);
  Serial.write(tl);
  Serial.write((byte)(len >> 8));
  Serial.write((byte)(len & 0xff));
  Serial.write(dat,bytes());
  Serial.write(checksum());
  read_byte();  // receive ACK
}

void setup(){
  pinMode(13,OUTPUT);
  Serial.begin(19200);
  len = 0;
}

void loop(){
  if (Serial.available() > 0){
    digitalWrite(13,HIGH);
    if(rcv_pkt()){
      last = millis();
    }
    digitalWrite(13,LOW);
  }
  
  if(millis() - last > 1000 && len > 0){
    digitalWrite(13,HIGH);
    snd_pkt();
    len = 0;
    digitalWrite(13,LOW);
  }
}

 ソースコードはsetup()とloop()を書き換えれば容易に再利用が効くと思いますのでご自由にお使い下さい。

 このソースコードはそのまま使うとちょっといじわるな動作をします。loop()を読んで頂ければわかりますが、簡単に解説すると、受信したリモコン信号と同じ信号を1秒後に赤外線送信します。例えば、TVの電源信号を受信すると1秒後に電源信号を送信するのです。ちょっといじわるですね。

 IRパケットを適当に作ってしまえば、Arduino間で赤外通信したりできそうなので遊んでみたいと思います。


Latest update at 2012/7/23