본문 바로가기
대한상공회의소 스마트팩토리 교육/IoT 디바이스 개발

[IoT 디바이스 개발] AVR(ATmega128A)«평가» : Atmega128A 모듈을 이용한 과목 최종 평가

by 나는영하 2022. 3. 10.

※ 주의사항 

본 블로그는 수업 내용을 바탕으로 제가 이해한 부분을 정리한 블로그입니다.
본 내용을 참고로만 보시고, 틀린 부분이 있다면 지적 부탁드립니다!

감사합니다😁

 

안녕하세요!!

최근에 ATmega128A 모듈을 이용하여 본 과목의 최종 평가를 진행하였습니다.

진행 과정과 제가 작성한 코드 및 하드웨어 동작을 설명하는 내용을 담아보았습니다.


1. 평 가 문 항

❗ Atmega128A 모듈을 이용하여 PC 터미널 및 스마트폰(블루투스연결)을 통해 다음 기능을 제어할 수 있도록 기능을 구현하고 결과물을 제출하시오.

✅ 기능 1. key 1~4 입력시 해당 숫자만큼 LED를 점등시키고(‘0’ 입력시 OFF), 결과를 PC터미널로 전송

✅ 기능 2. PIR 센서에 의한 인체 이동 감지시 메시지(: Alert!!) PC 터미널로 전송하고, LED 4개가 Button1로 정지 전까지 지속 점멸(ON/OFF)

✅ 기능 3. ·습도 센서값 정보를 PC로 출력 (key ‘t’ : 온도, key ‘h’ : 습도) 

 


 

2. 회로 및 동작 사진

2-1. 회로 구성 사진

- PORTA 0~3번 PIN : 센서 및 LED 제어에 반응할 Led Diode 연결(220옴 저항 사용)

- PORTC 0번 PIN : 온습도 센서(DHT11) 연결

- PORTD 0번 PIN : PIR 센서 연결

- PORTD 1번 PIN : PIR 센서 감지시 LED 점멸동작을 소등시킬 Push Button 연결(Pull-Up 저항)

- PORTD 2~3번 PIN : UART1번 RX, TX핀으로 블루투스 연결

 

2-2. PC 터미널 및 스마트폰(블루투스) 사진

- 아래의 코드를 컴파일 및 업로드하고 동작 확인 사진

- 스마트폰(블루투스) 및 PC 터미널을 통해 제어할때 뜨는 문구는 동일

(각각 UART1번과 UART0번 관련 함수 사용)

- 스마트폰을 통해 통신할때 Reset을 수행할 시 간혹 위와 같은 쓰레기(?)값이 나온다.

(디버깅 실패..)

 


 

3. Source Code

3-1. 전처리문

#define F_CPU 16000000L
#define DHT11_PIN 0

#include <util/delay.h>
#include <avr/io.h>
#include "UART0.h"
#include "UART1.h"
#include <stdio.h>
#include <avr/interrupt.h>

volatile uint8_t PIR_value = 1;
uint8_t RH_integral, RH_decimal, T_integral, T_decimal, CheckSum;

- 스마트폰(블루투스)과 PC 터미널로 각각 통신을 하기 위해 UART 2개 사용

- DHT-11 및 PIR 센서를 사용하기 위한 각종 변수 선언

 

3-2. PIN 및 Interrupt 초기화 함수부

void Function1_Init(void){ // LED 설정 초기화 함수부
	DDRA = 0X0F;
	PORTA = 0X00; 
}

void INT0_init(void){ //PIR 센서 관련 외부 인터럽트(INT0) 설정 함수부
	DDRD |= 0X00;
	EICRA |= ((1<<ISC01)|(1<<ISC00)); // 상승 에지에서 enable
	EIMSK |= (1<<INT0); // INT0 외부 인터럽트 enable
} 
	
void INT1_init(void){ // Pushbutton 관련 외부 인터럽트(INT1)설정 함수부
	DDRD |= 0X00;
	EICRA |= (1<<ISC11); // 하강 에지에서 enable
	EIMSK |= (1<<INT1); // INT1 외부 인터럽트 enable
}

- PIR센서를 외부 인터럽트(INT0)와 연결해서 PIR 센서에 신호가 수신되면(상승에지) 인터럽트가 발생

- PushButton을 외부 인터럽트(INT1)와 연결해서 PIR 센서 신호가 수신되고 LED가 점멸동작을 할때 Reset 하기 위한 인터럽트 Enable 부분 (Pushbutton은 하드웨어적으로 Pull-Up 저항으로 연결했음)

 

3-3. ISR 함수부

ISR(INT0_vect){
	UART0_print_string("PIR 센서 동작!!!!!!! \n\r");
	UART0_print_string("센서를 OFF 하고 싶으면 PUSH BUTTON을 눌러주세요.\n\r");
 	UART1_print_string("PIR 센서 동작!!!!!!! \n\r");
 	UART1_print_string("센서를 OFF 하고 싶으면 PUSH BUTTON을 눌러주세요.\n\r");
 	TIMSK |= (1<<TOIE1); //PIR 센서에 신호가 들어오면 1번 타이머 오버플로 인터럽트 활성화
 	TCCR1B |= (1<<CS12); } //256분주, 오버플로 약 1초마다 발생
	
ISR(INT1_vect){
 	UART0_print_string("적외선 감지 센서를 Reset 합니다.\n\r");
 	UART1_print_string("적외선 감지 센서를 Reset 합니다.\n\r");
 	TIMSK = 0X00; // 푸시버튼을 누르면 1번 타이머 인터럽트 비활성화
	PORTA = 0X00; // 외부 인터럽트1(INT1) 발생시 LED 소등
 }
 
 ISR(TIMER1_OVF_vect){ 
 PIR_value = !PIR_value; // 1번 타이머 오버플로 발생시 LED 반전
 	if(PIR_value==1){ PORTA = 0x0f; }
 	else{ PORTA = 0x00; }
}

- 스마트폰과 PC 터미널로 통신을 하기위해 같은 문구를 두번씩 통신하여 송수신 한다.

(WHY? 스마트폰과 PC 터미널은 사용하는 UART가 달라서 각각 해당 스트링을 송신)

→ 한개의 문장을 두개의 UART통신으로 보내기 위한 방법은 고민해봐야할 과제 😥

 

- 1번 타이머(16비트)를 256분주로 하여서 오버플로 발생시 인터럽트가 수행되도록 오버플로 인터럽트 활성화

(16비트 타이머의 256분주가 오버플로되면 약 1초의 시간이 소요된다)

 

3-4. 온습도센서(DHT-11) Data 처리 함수부

void Request(){
 	DDRC |= (1<<DHT11_PIN);
 	PORTC &= ~(1<<DHT11_PIN);
 	_delay_ms(20);
	PORTC |= (1<<DHT11_PIN); 
}
	
void Response(){
 	DDRC &= ~(1<<DHT11_PIN);
 	while(PINC & (1<<DHT11_PIN));
 	while((PINC & (1<<DHT11_PIN)) ==0);
	while(PINC & (1<<DHT11_PIN)); 
}
	
uint8_t Receive_data(){
 	int data =0;
 	for(int i =0; i < 8; i++){
 		while((PINC &(1<<DHT11_PIN))==0);
 		_delay_us(30);
 		if(PINC & (1<<DHT11_PIN))
 		data = (data<<1) + 1;
 		else
 		data = (data <<1);
 		while(PINC & (1<<DHT11_PIN));
	}
 	return data; 
}

- 온습도센서에서 Data를 주고 받을때 필요한 함수부로 관련 코드는 지난 온습도 센서 교육 내용 참고

2022.03.03 - [IoT 디바이스 개발] - [IoT 디바이스 개발] AVR(ATmega128A)«수업-22» : 온습도 센서(DHT11)

 

[IoT 디바이스 개발] AVR(ATmega128A)«수업-22» : 온습도 센서(DHT11)

※ 주의사항 ※ 본 블로그는 수업 내용을 바탕으로 제가 이해한 부분을 정리한 블로그입니다. 본 내용을 참고로만 보시고, 틀린 부분이 있다면 지적 부탁드립니다! 감사합니다😁 안녕하세요!!

920416.tistory.com

 

3-5. MAIN 함수

int main(void){
 	char str[16];
 	Function1_Init();
 	INT0_init();
 	INT1_init();
 	UART0_init();
 	UART1_init();
 	sei();
		
 	uint8_t value;
 	uint8_t value_2;
		
 	UART0_print_string("****************************************************************\n\r");
 	UART0_print_string("Please enter the Key!! \n\r");
 	UART0_print_string("0 : LED ALL OFF / 1 : LED 1 ON / 2 : LED 2 ON / 3 : LED 3 ON / 4 : LED 4 ON \n\r");
 	UART0_print_string("temperature : t / humidity : h \n\r");
 	UART0_print_string("****************************************************************\n\r");
		
 	UART1_print_string("****************************************************************\n\r");
 	UART1_print_string("Please enter the Key!! \n\r");
 	UART1_print_string("0 : LED ALL OFF / 1 : LED 1 ON / 2 : LED 2 ON / 3 : LED 3 ON / 4 : LED 4 ON \n\r");
 	UART1_print_string("temperature : t / humidity : h \n\r");
 	UART1_print_string("****************************************************************\n\r");
 	while (1){
 		if(UCSR0A & (1<<RXC0)){ //UART0의 수신버퍼에 읽지 않은 문자가 있으면 if문 수행
 			value = UART0_receive();
 		}
 		else if(UCSR1A & (1<<RXC1)){ //UART1의 수신버퍼에 읽지 않은 문자가 있으면 if문 수행
 			value = UART1_receive();
 		}
 		switch(value){
 			case '0':
 			PORTA = 0X00;
 			UART0_print_string("LED가 전부 소등되었습니다.\n\r");
 			UART1_print_string("LED가 전부 소등되었습니다.\n\r");
 			_delay_ms(100); break;
				
 			case '1':
 			PORTA = 0X01;
 			UART0_print_string("LED가 1개 점등되었습니다.\n\r");
 			UART1_print_string("LED가 1개 점등되었습니다.\n\r");
 			_delay_ms(100); break;
				
 			case '2':
 			PORTA = 0X03;
 			UART0_print_string("LED가 2개 점등되었습니다.\n\r");
 			UART1_print_string("LED가 2개 점등되었습니다.\n\r");
 			_delay_ms(100);	break;
				
 			case '3':
 			PORTA = 0X07;
 			UART0_print_string("LED가 3개 점등되었습니다.\n\r");
 			UART1_print_string("LED가 3개 점등되었습니다.\n\r");
 			_delay_ms(100); break;
				
 			case '4':
 			PORTA = 0X0F;
 			UART0_print_string("LED가 4개 점등되었습니다.\n\r");
 			UART1_print_string("LED가 4개 점등되었습니다.\n\r");
 			_delay_ms(100); break;
				
 			case 'T': case 't':
 			Request(); //DHT-11 센서 시작 신호
 			Response(); //DHT-11 센서 응답 신호
 			RH_integral = Receive_data();
 			RH_decimal = Receive_data();
 			T_integral = Receive_data();
 			T_decimal = Receive_data();
 			CheckSum = Receive_data();
 			if((RH_integral + RH_decimal + T_integral + T_decimal) == CheckSum){
 				sprintf(str,"%d.%d C",T_integral, T_decimal);
 				UART0_print_string("현재 온도는 : ");
 				UART0_print_string(str);
 				UART0_print_string("\n\r");
 				UART1_print_string("현재 온도는 : ");
	 			UART1_print_string(str);
		 		UART1_print_string("\n\r");
				_delay_ms(200); 
 			}
 			else{
 				UART0_print_string("DHT11 센서 오류 입니다.\n\r");
 				UART1_print_string("DHT11 센서 오류 입니다.\n\r"); 
 			}
 			break;
				
 			case 'H': case 'h':
 			Request(); //DHT-11 센서 시작 신호
 			Response(); //DHT-11 센서 응답 신호
 			RH_integral = Receive_data();
 			RH_decimal = Receive_data();
 			T_integral = Receive_data();
 			T_decimal = Receive_data();
 			CheckSum = Receive_data();
 			if((RH_integral + RH_decimal + T_integral + T_decimal) == CheckSum){
 				sprintf(str,"%d.%d",RH_integral, RH_decimal);
 				UART0_print_string("현재 습도는 : ");
 				UART0_print_string(str);
 				UART0_print_string("%\n\r");
				UART1_print_string("현재 습도는 : ");
 		        UART1_print_string(str);
 				UART1_print_string("%\n\r");
				_delay_ms(200); 
 			 }
 			else{
				UART0_print_string("DHT11 센서 오류 입니다.\n\r");
				UART1_print_string("DHT11 센서 오류 입니다.\n\r"); 
 			 }
 			break;				
 			default: break;
		}
 	}	
    return 0; 
}

UCSRnA레지스터의 RXCn비트의 값을 읽어서 해당 UART통신의 수신버퍼에 데이터가 들어와 있으면 해당 UART의 Data값을 받도록 if문을 구성하여 동작 수행 (while문 첫부분)

댓글