LoginSignup
0
0

More than 3 years have passed since last update.

Arduinoで赤外線受信を割り込み処理

Last updated at Posted at 2019-10-16

概要

Arduinoで赤外線受信IC VS1831 を使って、割り込みを使って赤外線リモコンを受信します。
対象のリモコンはNECフォーマットのみ
他の受信プログラムとちょっと違うのは、都度解析するのでは無く、全文受信したら解析するようにしています。
micros()の約70分のオーバーフローは未考慮
IRremoteライブラリは重たいので使わない方法で実現。
他のSONYフォーマットや家電製品協会フォーマットも作れそうですがやらない(^^;

レグザリモコン

電源ボタン
NEC:00000010111111010100100010110111:2FD48B7
音量+
NEC:00000010111111010101100010100111:2FD58A7
音量-
NEC:00000010111111010111100010000111:2FD7887
チャンネル+
NEC:00000010111111011101100000100111:2FDD827
チャンネル-
NEC:00000010111111011111100000000111:2FDF807
CH1
NEC:00000010111111011000000001111111:2FD807F
CH2
NEC:00000010111111010100000010111111:2FD40BF
CH3
NEC:00000010111111011100000000111111:2FDC03F

回路図

スクリーンショット 2019-10-16 14.52.31.png

基板

スクリーンショット 2019-10-16 14.53.54.png

引用

赤外線リモコン受信(Physical Computingに挑戦!)
http://physicom.digick.jp/
http://physicom.digick.jp/?p=3928

赤外線リモコンの通信フォーマット(elm-chanさん)
http://elm-chan.org/index_j.html
http://elm-chan.org/docs/ir_format.html

赤外線リモコンのフォーマット(電子工作の森さん)
http://www.asahi-net.or.jp/~gt3n-tnk/
http://www.asahi-net.or.jp/~gt3n-tnk/IR_TX1.html


// 赤外線リモコン 割り込み受信プログラム
// buffにIr割り込み時間を記録しておき、後に受信内容を解析
// NEC用リモコン専用
//http://elm-chan.org/docs/ir_format.html
//http://www.asahi-net.or.jp/~gt3n-tnk/IR_TX1.html
//

#define BUFF_SIZE 256
#define PIN_IRLED   2
#define PIN_RUNLED  4
#define PIN_IRIN    3

#define S_MAX(n,t)    (((n- 500) <= t) && (t < (n+ 500)))
#define V_MAX(n,t)    (((n- 100) <= t) && (t < (n+ 100)))

unsigned long prev;
unsigned long time;
int index = 0;
unsigned long buff[BUFF_SIZE];

//--------------------------------------------------------------------------------
// arduino初期化
//--------------------------------------------------------------------------------
void setup() {
  Serial.begin(115200);

  pinMode(PIN_RUNLED, OUTPUT);        // IR受信した時に光らせるLED
  pinMode(PIN_IRIN, INPUT);           // Ir受信ポート

  attachInterrupt(1, blink, CHANGE);  // Ir割り込みポート設定 ※PIN_IRIN 3 だけど、1を設定
  prev = micros();
}

//--------------------------------------------------------------------------------
// arduinoメインループ
//--------------------------------------------------------------------------------
void loop() {
  enum{
      ST_LEADER1 = 0,
      ST_LEADER2,
      ST_DATA_M,
      ST_DATA_L,
      ST_REPEAT,
      ST_OFF_RUN,
  };

  unsigned long temp = 0;
  unsigned long dat = 0;

  unsigned char Ir_state = ST_LEADER1;

  time = micros();

  if ((index > 0) && (time-prev > 20000)) { // この処理は見直したほうがいいかも。
    Serial.println("");
    Serial.println("****************");
    Serial.println(index,HEX);

    for (int i = 1; i < index; i++) { // buff に記録されている時間間隔を表示
      Serial.print(buff[i]);
      Serial.print(",");
    }
      Serial.println("");

    for (int i = 1; i < index; i++) { // buff 解析
      temp = buff[i];
      switch(Ir_state){
        case ST_LEADER1:
              if(V_MAX(8992,temp)){ // 562us * 16T = 8.992ms
                Serial.print("NEC");
                Ir_state = ST_LEADER2;
              }
                break;
        case ST_LEADER2:
              if(V_MAX(4496,temp)){ // 562us * 8T = 4.496ms
                Serial.print(":");
                Ir_state = ST_DATA_M;
              } if(V_MAX(2248,temp)){  // 562us * 4T = 2.248ms
                Ir_state = ST_REPEAT;
              } 
                break;
        case ST_DATA_M:
              if(temp < 616){ // 0.56ms * 1.1 = 0.616ms
                Ir_state = ST_DATA_L;
              }
              break;
        case ST_DATA_L:
              if(temp < 616){ // 0.56ms * 1.1 = 0.616ms
                Serial.print("0");
                dat=dat<<1;
              }
              else if(temp < 2475){ // 2.25ms * 1.1 =2.475ms
                Serial.print("1");
                dat=dat<<1;
                dat=dat|0x0001;
              }              
              Ir_state = ST_DATA_M;
              break;
        case ST_REPEAT:
              if(temp < 616){ // 0.56ms * 1.1 = 0.616ms
                Serial.print("Repeat");
              }
              break;
        default:
              break;
      }
    }

    Serial.print(":");
    Serial.println(dat,HEX);
    dat = 0;
    index = 0;
    prev = time;
  }
  delay(10);
}


//--------------------------------------------------------------------------------
// 赤外線受信割り込み処理
// 立ち上がり、立ち下がり両方で割り込みがかかります。
//--------------------------------------------------------------------------------
void blink() {
  PORTD |= _BV(2);  // PIN_IRLED 点灯
  time = micros();

  buff[index] = time - prev;
  prev = time;
  index++;
  if (index >= BUFF_SIZE) {
    index = 0;
  }
  PORTD &= ~_BV(2);  // PIN_IRLED 消灯
}
0
0
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
0
0