이글의 전부 또는 일부, 사진, 소스프로그램 등은 저작자의 동의 없이는 상업적인 사용을 금지합니다. 또한, 비상업적인 목적이라 하더라도 출처를 밝히지 않고 게시하는 것은 금지합니다.



1. 적외선(IR) 신호 읽기 - ATmega8 개선하기



2019/10/22 - [AVR/작품] - 적외선(IR) 신호 읽기 - ATmega8에서 IR 리모콘에서 오는 신호의 low 길이와 high 길이를 측정하는 프로그램을 만들었습니다. 이 프로그램은 Input Capture로 들어오는 의미 없는 첫 데이터를 그대로 표시한다는 문제점을 가지고 있었습니다. 이 문제점을 개선해 봤습니다.

//////////////////////////////////////////////////
// __TIMER1_CAPT (timer1 capture interrupt service routine)
// PARAM	NONE
// RETURN	NONE
// CHANGED	AL
//////////////////////////////////////////////////
__TIMER1_CAPT:
	PUSH	AL
	IN	AL,SREG
	PUSH	AL
	PUSH	AH
	PUSH	ZL
	PUSH	ZH
	IN	AL,ICR1L
	IN	AH,ICR1H
	LDI	ZL,0
	OUT	TCNT1H,ZL
	OUT	TCNT1L,ZL
	IN	ZL,TCCR1B
	SBRC	ZL,ICES1
	RJMP	__TIMER1_CAPT_SET_FALLING
	SBR	ZL,(1 << ICES1)
	OUT	TCCR1B,ZL
	CPI	IR_STATE,IR_STANDBY			// skip first useless data
	BREQ	__TIMER1_CAPT_QUIT
	LDI	ZL,LOW(IR_QUEUE_HIGH)
	LDI	ZH,HIGH(IR_QUEUE_HIGH)
	ADD	ZL,IR_QUEUE_HEAD_L
	ADC	ZH,IR_QUEUE_HEAD_H
	ST	Z+,AL
	ST	Z,AH
//	MOVW	ZL,IR_QUEUE_DATA_L			// data++;
//	ADIW	ZL,1
//	MOVW	IR_QUEUE_DATA_L,ZL
	MOVW	ZL,IR_QUEUE_HEAD_L			
	ADIW	ZL,2
	LDI	AL,LOW(IR_QUEUE_SIZE)			// head %= IR_QUEUE_SIZE;
	LDI	AH,HIGH(IR_QUEUE_SIZE)
	CP	ZL,AL
	CPC	ZH,AH
	BRLO	__TIMER1_CAPT_STORE_QUEUE_HEAD
	CLR	ZL
	CLR	ZH
__TIMER1_CAPT_STORE_QUEUE_HEAD:
	MOVW	IR_QUEUE_HEAD_L,ZL
__TIMER1_CAPT_QUIT:
	LDI	IR_STATE,IR_DATA_IN
	POP	ZH
	POP	ZL
	POP	AH
	POP	AL
	OUT	SREG,AL
	POP	AL
	RETI
__TIMER1_CAPT_SET_FALLING:
	CBR	ZL,(1 << ICES1)
	OUT	TCCR1B,ZL
	LDI	ZL,LOW(IR_QUEUE_LOW)
	LDI	ZH,HIGH(IR_QUEUE_LOW)
	ADD	ZL,IR_QUEUE_HEAD_L
	ADC	ZH,IR_QUEUE_HEAD_H
	ST	Z+,AL
	ST	Z,AH
	RJMP	__TIMER1_CAPT_QUIT

//////////////////////////////////////////////////
// __TIMER1_COMPA (timer1 output1A compare interrupt service routine)
// PARAM	NONE
// RETURN	NONE
// CHANGED	AL
//////////////////////////////////////////////////
__TIMER1_COMPA:
	PUSH	AL
	IN	AL,SREG
	CPI	IR_STATE,IR_DATA_IN
	BRNE	__TIMER1_COMPA_QUIT
	LDI	IR_STATE,IR_NO_MORE
__TIMER1_COMPA_QUIT:
	OUT	SREG,AL
	POP	AL
	RETI


두 개의 함수를 수정합니다.

첫번째로 Input Capture 인터럽트 서비스인 __TIMER1_CAPT를 수정합니다. 위 소스에 표시는 하지 않았지만 프로그램 시작시 각 종 변수들을 초기화하는 함수 VARIABLES_INIT 함수에서 IR_STATE에 IR_STANSBY 값을 넣습니다. 첫 데이터가 들어올 때에 __TIMER1_CAPT 함수에서 IR_STATE의 값을 검사해서값이 IR_STANDBY이면 현재 카운터 값은 의미없는 데이터이기 때문에 IR_QUEUE에 넣지 않고(24, 25행), IR_STATE 변수에 IR_DATA_IN을 넣고 인터럽트 서비스를 종료합니다. 이렇게하여 첫 데이터는 버리고, 두번째 데이터부터 IR_QUEUE에 넣을 수 있습니다.

두번째로 TIMER1 Compare match 인터럽트 서비스인 __TIMER1_COMPA를 수정합니다. IR_STATE 변수가 IR_DATA_IN인 상태에서 이 인터럽트가 걸렸을 때에만 데이터 입력이 종료되었다는 의미로 IR_STATE 변수에 IR_NO_MORE 값을 갖도록 합니다(75, 76, 77행).
이렇게 수정한 후에 MAIN_LOOP에서 IR_STATE의 값이 IR_NO_MORE가 될 때까지 대기합니다. IR_STATE의 값이 IR_NO_MORE가 되면 IR_QUEUE의 값을 모두 표시한 다음에 IR_STATE에 IR_STANDBY를 넣고, 다시 IR_STATE의 값이 IR_NO_MORE가 될 때까지 대기합니다.



2. 적외선 리모콘(IR remocon) 신호 분석 - ATmega8 개선하기



이전 글 2019/10/28 - [AVR/작품] - 적외선 리모콘(IR remocon) 신호 분석 - ATmega8을 두가지 사항을 개선합니다. 첫째는 위의 1. 적외선(IR) 신호 읽기 - ATmega8 개선하기에서와 마찬가지로 첫 데이터를 취합하지 않는 것입니다. 위의 예에서와 같이 __TIMER1_CAPT와 __TIMER1_COMPA 인터럽트 서비스 루틴을 수정합니다.

두번째는 IR 신호 분석 루틴인 ANALYZE_REMOCON 함수를 수정하는 것입니다. 이전의 글 2019/10/28 - [AVR/작품] - 적외선 리모콘(IR remocon) 신호 분석 - ATmega8에서 세 가지 IR 프로토콜(NEC 프로토콜, TC9012 프로토콜, SAMSUNG 하우젠 천정형 에어콘 프로토콜)의 신호를 분석했습니다. 이 세 프로토콜은 LEADER 신호의 길이는 모두 달랐습니다. low(0)과 high(1)의 길이는 NEC 프로토콜과 TC9012 프로토콜은 같았으나, 삼성 하우젠 천정형 에어콘 프로토콜은 다른 두 프로토콜보다 짧았습니다. 사실은 삼성 하우젠 천정형 에어콘의 리모콘 프로토콜의 사양을 모르기 때문에, 2019/10/22 - [AVR/작품] - 적외선(IR) 신호 읽기 - ATmega8에서 작성한 프로그램으로 측정한 값을 기초로 어림잡아 사용했습니다. 그러던 중에 2019/11/02 - [AVR/작품] - 적외선 리모콘(IR Remocon) 신호 보내기 - ATmega8에서 삼성 천정형 에어콘에 low(0)과 high(1)의 신호 길이를 NEC 프로토콜이나 TC9012 프로토콜과 같이 보내도 동작한다는 사실을 발견했습니다.
그래서 이전의 글에서는 NEC 프로토콜과 TC9012 프로토콜은 같은 루틴을 사용하고 삼성 하우젠 천정형 에어컨은 별도의 루틴으로 처리했던 것을 모두 하나의 루틴에서 처리하도록 개선했습니다. 이 때에 삼성 하우젠 천정형 에어콘 리모콘의 신호 길이가 다른 두 프로토콜 신호의 길이보다 조금 짧기때문에 low 값과 high 값의 신호 길이 범위를 정하는 매크로 MIN_0_LENGTH, MAX_0_LENGTH, MIN_1_LENGTH, MAX_1_LENGTH의 값을 조금 조정했습니다.

수정한 LengthIR_M8.asm과 RecieveIR_M8의 소스 프로그램을 첨부합니다.

LengthIR_M8.asm
11.8 kB
ReceiveIR_M8.zip
5.5 kB

블로그 이미지

엠쿠스

Microprocessor(STM32, AVR)로 무엇인가를 만들어 보고자 학습 중입니다.

,