적외선 신호포멧은 NEC, SONY, RC5, RC6 등 여러가지가 있으나 대표적으로 NEC(아시아 태평양 연안), RC5(유럽 등) 포멧이 주로 이용됩니다. 삼성과 LG는 NEC포멧을 사용합니다.
NEC 포멧은 아래와 같은 배열로 구성되어야 합니다.
Lead code
|
Custom code (8bit) |
Custom code (8bit) |
Data code (8bit) |
Data code (반전된 8bit) |
Lead code
- 신호가 시작됨을 알립니다.
삼성 : 4.5ms HIGH, 4.5ms LOW
LG : 9ms HIGH, 4.5ms LOW
Custom code
- 제조사와 제품별 구분용입니다.
16bit를 통째로 이용하거나 8bit와 반전된 8bit를 이용하기도 합니다.
Data code
- 데이타를 표시합니다
8bit 와 반전된 8bit를 이용합니다
포멧의 개념은 대충 이렇게 구성되는구나라고만 이해하면 됩니다.
// IR 리시버를 2번 포트에 연결해두었습니다.
#define IR_IN 2
// 코드 포맷입니다. 우리나라는 대부분 NEC.
#define NEC 1
#define AEHA 2
#define SONY 3
// 버퍼 사이즈 잡아놓고...
#define BUF_SIZE (512)
void setup() {
// 핀모드 인풋
pinMode( IR_IN , INPUT );
Serial.begin(115200);
}
void loop() {
unsigned long usec, nec_data = 0;
unsigned int i, n, irOffTime, minTime, aveCnt = 0, aveAdd = 0;
unsigned int irdata[ BUF_SIZE ], timeunit, leaderH, leaderL, datalen;
unsigned int format = 0;
boolean isvalid = true;
// 신호가 감지될 때까지 기다립니다. 할 일이 없어서 do가 없습니다.
while( digitalRead( IR_IN ) == HIGH );
// LOW 감지되면 시작
for( i=0; i < BUF_SIZE; ) {
// 현재 시간을 한번 체크
usec = micros();
// LOW인 시간 동안 멈춰!
while( digitalRead( IR_IN ) == LOW );
// 신호 길이를 기록하고, 다음 신호 길이는 일단 0으로.
irdata[ i] = micros() - usec;
irdata[++i] = 0;
// 같은 방식으로 다음 HIGH에 대해서도 체크합니다.
usec = micros();
while( digitalRead( IR_IN ) == HIGH ) {
irOffTime = micros() - usec;
// 65ms 이상 HIGH 이면 신호 끝난 것으로 인식.
if( irOffTime > 65000 ) goto ir_exit;
}
// 끝난게 아니면 길이 기록하고 다음으로 넘어감.
irdata[i++] = irOffTime;
}
// 신호가 끝난 상황이라면,
ir_exit:
// 신호 최소 시간을 찾아냄
minTime = irdata[0];
for( i=0; irdata[i]; i++) minTime = min( minTime, irdata[i]);
// 최소 시간 1.5배의 평균으로 시간 단위 잡습니다.
for( i=0; irdata[i]; i++) {
if( minTime * 3 / 2 > irdata[i] ) { aveAdd += irdata[i] - minTime; aveCnt++; }
}
timeunit = aveAdd / aveCnt + minTime;
// 시간 단위가 너무 짧으면 이상하니까 리턴
if( timeunit < 300 ) return;
// 아니면 시간 단위로 나누어 irdata[]에 넣습니다.
for( i=0; irdata[i]; i++) irdata[i] = ( irdata[i] + timeunit / 2 ) / timeunit;
// 코드 시작하기 전 반복을 제거합니다.
leaderH = irdata[0];
leaderL = irdata[1];
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( "nnFormat : ");
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 ) {
// NEC 포맷의 경우만
case NEC:
for( n=0; n < datalen - 1; n++) {
nec_data |= ( (irdata[n*2+1]==1) ? 0UL : 1UL ) << n;
}
if( !isvalid ) break;
Serial.print( "nCustom code : 0x");
Serial.print( nec_data % 256 , HEX);
Serial.print( "nCustom code' : 0x");
Serial.print( (nec_data >> 8) % 256 , HEX);
Serial.print( "nData code : 0x");
Serial.print( (nec_data >> 16) % 256 , HEX);
Serial.print( "nData code (nega) : 0x");
Serial.print( (nec_data >> 24) % 256 , HEX);
break;
}
}
댓글 1
번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
---|---|---|---|---|
» | IR 리모콘 코드 따기 [1] | 묵묵이 | 2017.02.10 | 14 |
공지 | rc 카 작업용 [1] | 묵묵이 | 2017.02.07 | 14 |
공지 | [sketch_mydust] 미세멘지 측정기 작업 용 [2] | 묵묵이 | 2017.02.07 | 35 |
4 | 아두이노 - DC모터 제어 [3] | 묵묵이 | 2017.01.10 | 2 |
3 | 우분투(Ubuntu)에서 아두이노(Arduino) 설치하고 실행하기 | 묵묵이 | 2017.01.09 | 4 |
2 | 아두이노 보드없이 123d circuit 즐기세요 | 묵묵이 | 2017.01.09 | 1 |
1 | 아두이노 우노를 이용하여 간단한 LED 제어 하기 | 묵묵이 | 2017.01.09 | 3 |
일본인 원본 소스