적외선 리모콘 (분석의 친구) [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 ); }
시리얼 모니터에 결과를 표시합니다.
댓글