赤外線リモコン受信データ解析

PCで解析したところ、基本的に次の処理で解析できた。

1.最小値で各値を割る(実際には最小値を0.9倍したものを使う)
2.リーダー部の最初の値を2番目の値で割って商が2ならNECかAEHA
3.リーダー部の最初の値が16ならNEC、8ならAEHA、4ならSONY

NECフォーマットなら
1.リーダー部の次から1, 1または1, 3を判定してそれぞれ0, 1とデータ部を組み立てる
2.1, 3以外の値が出たら終了

AEHAフォーマットなら
1.リーダー部の次から1, 1または1, 3を判定してそれぞれ0, 1とデータ部を組み立てる
2.1, 3以外の値が出たら終了

SONYフォーマットなら
1.リーダー部の次から1, 1または1, 2を判定してそれぞれ0, 1とデータ部を組み立てる
2.データ部が7ビット、アドレス部が5/8/13ビットなので、それに合わせてデコードする


#define BUFF_SIZE 256
#define NEC   1
#define AEHA  2
#define SONY  3

volatile int state = HIGH;
unsigned long prev;
unsigned long time;
int index = 0;
unsigned long buff[BUFF_SIZE];
unsigned char data[BUFF_SIZE/8];
unsigned char temp;
int pos;
char format = 0;
int error = 0;

void setup() {
  prev = micros();
  Serial.begin(9600);
  pinMode(13, OUTPUT);
  attachInterrupt(0, blink, CHANGE);
}

void loop() {
  digitalWrite(13, state);
  time=micros();
  if ((index > 0) && (time-prev > 200000)) {
    error = 0;
    format = 0;
    pos = 0;
    analyzePass1();
    analyzePass2();
    Serial.println("****************");
    if (format==NEC) {
      Serial.println("Format=NEC");
    } else if (format==AEHA) {
      Serial.println("Format=AEHA");
    } else if (format==SONY) {
      Serial.println("Format=SONY");
    } else {
      Serial.println("Format=UNKNOWN");
      Serial.print("Error=");
      Serial.println(error);
    }
    Serial.println(">>>>>>>>>>>>>>>>");
    for (int i = 0; i < pos; i++) {
      Serial.println(data[i]);
    }
    if (error) {
      Serial.println("****************");
      for (int i = 1; i < index; i++) {
        Serial.println(buff[i]);
      }
    }
    index = 0;
    prev=time;
  }
  delay(10);
}

void blink() {
  state = !state;
  time = micros();
  buff[index]=time-prev;
  prev=time;
  index++;
  if (index >= BUFF_SIZE) {
    index=0;
  }
}

void analyzePass1() {
  unsigned long minval = 10000000;
  for (int i = 0; i < index; i++) {
    if ((buff[i] > 350) && (buff[i] < minval)) {
      minval = buff[i];
    }
  }
  minval = (minval * 9) / 10;
  for (int i = 0; i < index; i++) {
    buff[i] = buff[i] / minval;
  }
}

void analyzePass2() {
  if (index < 20) {
    error = 1;
    return;
  }
  if (buff[2] == 0) {
    error = 2;
    return;
  }
  int leader;
  leader = buff[1] / buff[2];
  if (leader == 2) {
    if ((buff[2] >= 8) && (buff[2] <= 11)) {
      // NEC format
      if (nec()) {
        format=NEC;
      }
    } else if ((buff[2] == 4) || (buff[2] == 5)) {
      // AEHA format
      if (aeha()) {
        format=AEHA;
      }
    } else {
      Serial.print("!!!buff[2]=");
      Serial.println(buff[2]);
      error = 3;
      return;
    }
  } else if ((buff[1] == 4) || (buff[1] == 5)) {
    // SONY format
    if (sony()) {
      format=SONY;
    }
  } else {
    error = 4;
    Serial.print("!!!leader=");
    Serial.println(leader);
    Serial.print("!!!buff[1]=");
    Serial.println(buff[1]);
    Serial.print("!!!buff[2]=");
    Serial.println(buff[2]);
    return;
  }
}

int nec() {
  int b = 0;
  temp = 0;
  for (int i = 3; i < index; i+=2) {
    if (buff[i]==1) {
      if (buff[i+1]==1) {
        // 0
      } else if (buff[i+1]==3) {
        // 1
        temp |= 1<=4) {
        return 1;
      } else {
        error = 5;
        Serial.print("!!!pos=");
        Serial.println(pos);
        Serial.print("!!!bit=");
        Serial.println(b);
        Serial.print("!!!buff[i+1]=");
        Serial.println(buff[i+1]);
        return 0;
      }
    } else if (pos>=4) {
      return 1;
    } else {
      error = 6;
      Serial.print("!!!pos=");
      Serial.println(pos);
      Serial.print("!!!bit=");
      Serial.println(b);
      Serial.print("!!!buff[i]=");
      Serial.println(buff[i]);
      return 0;
    }
    b++;
    if (b==8) {
      data[pos++]=temp;
      b=0;
      temp=0;
      if (pos >= BUFF_SIZE/8) {
        error = 7;
        return 0;
      }
    }
  }
  if (b > 0) {
    data[pos++]=temp;
  }
  return 1;
}

int aeha() {
  int b = 0;
  temp = 0;
  for (int i = 3; i < index; i+=2) {
    if (buff[i]==1) {
      if (buff[i+1]==1) {
        // 0
      } else if (buff[i+1]==3) {
        // 1
        temp |= 1<= 3) {
        return 1;
      } else {
        error = 5;
        Serial.print("!!!i=");
        Serial.println(i);
        Serial.print("!!!buff[i+1]=");
        Serial.println(buff[i+1]);
        return 0;
      }
    } else if (pos >= 3) {
      return 1;
    } else {
      error = 6;
      return 0;
    }
    b++;
    if (b==8) {
      data[pos++]=temp;
      b=0;
      temp=0;
      if (pos >= BUFF_SIZE/8) {
        error = 7;
        return 0;
      }
    }
  }
  if (b > 0) {
    data[pos++]=temp;
  }
  return 1;
}

int sony() {
  int b = 0;
  temp = 0;
  for (int i = 2; i < 16; i+=2) {
    if (buff[i]==1) {
      if (buff[i+1]==1) {
        // 0
      } else if (buff[i+1]==2) {
        // 1
        temp |= 1<= 3) {
        return 1;
      } else {
        error = 5;
        Serial.print("!!!i=");
        Serial.println(i);
        Serial.print("!!!buff[i+1]=");
        Serial.println(buff[i+1]);
        return 0;
      }
    } else {
      Serial.print("!!!i=");
      Serial.println(i);
      Serial.print("!!!buff[i]=");
      Serial.println(buff[i]);
      error = 6;
      return 0;
    }
    b++;
  }
  data[pos++]=temp;
  b=0;
  temp=0;
  for (int i = 16; i < index; i+=2) {
    if (buff[i]==1) {
      if (buff[i+1]==1) {
        // 0
      } else if (buff[i+1]==2) {
        // 1
        temp |= 1<= 1) {
        data[pos++]=temp;
        return 1;
      } else {
        error = 5;
        Serial.print("!!!i=");
        Serial.println(i);
        Serial.print("!!!buff[i+1]=");
        Serial.println(buff[i+1]);
        return 0;
      }
    } else {
      data[pos++]=temp;
      return 1;
    }
    b++;
    if (b==8) {
      data[pos++]=temp;
      b=0;
      temp=0;
      if (pos >= BUFF_SIZE/8) {
        error = 7;
        return 0;
      }
    }
  }
  return 1;
}
カテゴリー: Android, センサー タグ: パーマリンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA