적외선 리모콘 (분석의 친구) [Arduino]


http://hello-world.blog.so-net.ne.jp/2011-05-19
/ / IR 분석 스케치 
# define IR_IN 2           / / IR Receiver

# define NEC 1
# define AEHA 2
# define     3

# define BUF_SIZE (512)     / / ATmega168이라면 128 정도하지 않으면 문제

void  setup () { 
   pinMode (IR_IN, INPUT );                         / / Vout -> digital 2 
  pinMode (3, OUTPUT );   digitalWrite (3,   LOW );   / / GND -> digital 3 LOW 
  pinMode (4, OUTPUT );   digitalWrite ( 4, HIGH );   / / Vcc -> digital 4 HIGH
   . begin (115200);
}

void  loop () {
   unsigned  long usec, nec_ = 0;
   unsigned  int I, n, irOffTime, minTime, aveCnt = 0, aveAdd = 0;
   unsigned  int irdata [BUF_SIZE] timeunit, leaderH, leaderL, datalen;
   unsigned  int format = 0, hex = 0, sony_data = 0, sony_adrs = 0, sony_adrs_bit = 0;
   boolean IsValid = ;
   / / ● 적외선을 감지 할 때까지 대기 
  while ( digitalRead (IR_IN) == HIGH );
   / / ● 원시 데이터를 가져 
  for (i = 0; i <BUF_SIZE;) {
    usec =  micros ();
     while ( digitalRead (IR_IN) == LOW );            / / IR 신호가 ON 시간을 측정 
    irdata [i] =  micros () - usec;
    irdata [+ + i] = 0;
    usec =  micros ();
     while ( digitalRead (IR_IN) == HIGH ) {          / / IR 신호가 OFF 시간을 측정 
      irOffTime =  micros () - usec;
       ​​if (irOffTime> 65000) goto ir_exit;          / / 신호 두절이라면 종료
    }
    irdata [i + +] = irOffTime;
  }
  ir_exit :
  Serial . println ( "<< IR data analyser >>" );
   / / ● 시간 단위를 조사 
  minTime = irdata [0];                     / / 먼저 최소값을 확인 
  for (i = 0; irdata [i]; i + +) minTime = min (minTime, irdata [i]);
   for (i = 0; irdata [i]; i + +) {              / / 최소 값의 50 %까지를 시간 단위로한다 
    if (minTime * 3 / 2> irdata [i] ) {aveAdd + = irdata [i] - minTime; aveCnt + +;}
  }
  timeunit = aveAdd / aveCnt + minTime;
  if (timeunit <300) return ;             / / 시간 단위가 너무 짧은 때 이상이라고 판단 
  / / ● 시간 단위로 데이터를 변환 
  for (i = 0; irdata [i]; i + +) irdata [i] = (irdata [i] + timeunit / 2) / timeunit;
   / / ● 적외선 파형을 표시 
  for (i = 0; irdata [i]; i + +) for (n = 0; n <irdata [i]; n + +) Serial . print ((i % 2)? "_" : "|" );
   Serial . println ( "." );  
   / / ● 분석하기 쉽게하기 위해 데이터 정리 
  leaderH = irdata [0];                 / / 리더 부 High의 길이 
  leaderL = irdata [1];                 / / 리더 부 Low 길이 
  for (i = 0;; i + = 2) {                   / / 데이터 분석을 위해 리더 부와 반복을 제거 · 정리
    irdata [i] = irdata [i +2]; irdata [i +1] = irdata [i +3];
    if (irdata [i +1]> 10 | | irdata [i +1] == 0) {irdata [i +1] = 0; datalen = i / 2 + 1;   break ;}
  }
  / / ● 각종 기본 데이터를 표시 
  Serial . print ( "Time Unit (usec) :" );   Serial . println (timeunit, DEC );
   Serial . print ( "Leader (On / Off) :" );
   Serial . print ( leaderH, DEC );   Serial . print (   "/" );   Serial . println (leaderL, DEC );
   / / ● 리더 부 길이로 포맷을 판단 
  Serial . print ( "Format :" );
   if ((leaderH> 14 | | leaderH <18) && leaderL == 8) {format = NEC;   Serial . println ( "NEC"   );}
   else  if            (leaderH == 8 && leaderL == 4) {format = AEHA; Serial . println ( "AEHA" );}
   else  if            (leaderH == 4 && leaderL == 1) {format = SONY; Serial . println ( "SONY" );}
   else   Serial . println ( "??" );
   / / ● 형식 마다 결과를 표시 
  switch (format) {                
     0 :         / / ■ 알 수없는 형식의 경우 
      Serial . println ( "! Analysing as NEC format!" );
     case NEC :       / / ■ NEC 형식 
      Serial . print ( " data : (LSB) " );
       for (n = 0; n <datalen - 1; n + +) {   / / 정지 비트 직전까지 반복 
        if (n % 8 == 0) Serial . print ( "" );
         if (irdata [ n * 2]! = 1) { Serial . print ( "?" ); isvalid = false ; continue ;}
         if (irdata [n * 2 +1]! = 1 && irdata [n * 2 +1]! = 3 ) { Serial . print ( "?" ); isvalid = false ; continue ;}
         Serial . print ((irdata [n * 2 +1] == 1)? "0" : "1" );
        nec_data | = ((irdata [n * 2 +1] == 1)? 0UL : 1UL) << n;
      }
      Serial . println ( "(MSB)" );
       if (! isvalid) break ;     / / 데이터에 문제가 있으면 이후는 표시하지 
      Serial . print ( "Custom       : " ); printlnHexcode (nec_data % 256);
       Serial . print ( "Custom code ':" ); printlnHexcode ((nec_data >> 8) % 256);
       Serial . print ( "Data code :" ); printlnHexcode ((nec_data >> 16) % 256);
       Serial . print ( "Data code (nega) : " ); printlnHexcode ((nec_data >> 24) % 256);
       break ;
     case AEHA :      / / ■ 가전 협회 포맷 
      Serial . print ( "Binary data : (LSB)" );
       for (n = 0 ; n <datalen - 1; n + +) {   / / 정지 비트 직전까지 반복 
        if (n % 4 == 0) Serial . print ( "" );
         if (irdata [n * 2]! = 1) { Serial . print ( "?" ); isvalid = false ; continue ;}
         if (irdata [n * 2 +1]! = 1 && irdata [n * 2 +1]! = 3) { Serial . print ( "?" ); isvalid = false ; continue ;}
         Serial . print ((irdata [n * 2 +1] == 1)? "0" : "1" );
      }
      Serial . println ( "(MSB)" );
       if (! isvalid) break ;     / / 데이터에 문제가 있으면 이후는 표시하지 
      Serial . print ( "Hexadecimal data : (LSB)" );
       for (n = 0; n <datalen; n + +) {
        hex | = ((irdata [n * 2 +1] == 1)? 0:1) << (n % 4);
        if (n % 4 == 3) {   Serial . print (hex, HEX ); Serial . print ( "" ); hex = 0;}
      }
      Serial . println ( "(MSB)" );
       break ;
     case SONY :      / / ■ SONY 포맷 
      Serial . print ( "Binary data : (LSB)" );
       for (n = 0; n <datalen; n + +) {
         if ( irdata [n * 2 +1]! = 0 && irdata [n * 2 +1]! = 1) { Serial . print ( "?" ); isvalid = false ; continue ;}
         if (irdata [n * 2]! = 1 && irdata [n * 2]! = 2) { Serial . print ( "?" ); isvalid = false ; continue ;}
         Serial . print (irdata [n * 2] -1);
         if (n == 6 ) Serial . print ( "" );
         if (n <7) sony_data | = (irdata [n * 2] -1) << n;
         else          sony_adrs | = (irdata [n * 2] -1) << sony_adrs_bit + +;
      }
      Serial . println ( "(MSB)" );
       if (! isvalid) break ;     / / 데이터에 문제가 있으면 이후는 표시하지 
      Serial . print ( "Data (7bit) :" ); printlnHexcode (sony_data);
       Serial . print ( "Adress (bit) : " );   Serial . print (sony_adrs_bit); Serial . println ( "bit" );
       Serial . print ( "Adress :" ); printlnHexcode (sony_adrs);
       break ;
  }
  / / ● 이상 종료 
  Serial . println ( "" );
}

void printlnHexcode ( unsigned  int D) {     / / 16 진수를보기 좋게 표시 줄 바꿈 
  Serial . print ((d <0x10)? "0x0" : "0x" );
   Serial . print ((d <0x1000 && d> 0xff) ? "0" : "" );
   Serial . println (d, HEX );
}

시리얼 모니터에 결과를 표시합니다.
kirigamine.png

댓글

이 블로그의 인기 게시물

4,5,6 띠 저항의 색띠를 읽는 법(띠저항 값)

수지에서 인천공항 리무진 버스 (인천공항버스정보)(2022년3월업데이트)

수지에서 김포공항 리무진 버스 ( 2022년 3월 업데이트 )