아트메가/활용

아트메가를 사용한 디지털 도어락

원원 2017. 1. 18. 14:56

 

 

이번에는 아트메가128를 사용하여 도어락을 만들어 보겠습니다.

 

구현할 기능들

1. 서보모터를 사용하여 문 ON/OFF 하기

2. LCD화면과 키패드를 이용하여 비밀번호설정 & 입력 하기

3. 키패드가 내려간 상태에서 만약 어둡다면 LED 키기 (조도센서 사용)

4. ON됬을때 멜로디 발생시키기 (멜로디 ON/OFF로 제어가능)

5. 스마트폰 앱을 이용하여 도어락을 ON하기 (블루투스 연결)

 

 

 

 

 

 - 만든 과정 -

먼저 만들기전에 구현할 기능들을 브래드보드를 사용하여 테스트를 합니다...

 

 

 

 

테스트를 다했으면 외형을 만들고 고정시킵니다.

 

 

 

 

키패드 덮개도 만듭니다!

 

 

 

 

사용할 기능들을 만듭니다. 여기서 스위치는 덮개를 열었을때 올라가고

덮개를 열었을때 내려갑니다.

 

 

 

 

거의 다되었습니다. 문이 열렸을때 소리를 발생시키기위해 스피커를 달아줍니다.

 

 

 

 

 

 

 

 

- 실제 동작-

초기 키패드 덮개를 열기 전 모습입니다. 

현재 덮개때문에 조도센서(빛감지)의 값이 낮음에도 불구하고

 LED가 안켜지는것을 확인할 수 있습니다.

 

 

 

 

덮개를 내린 모습입니다. 처음 도어락을 켰으므로 비밀번호 설정하는 화면이 나옵니다.

그리고 손으로 조도센서를 가려서 어둡게 만들었더니 LED가 켜지는것을

확인할 수 있습니다. 이 기능을 구현한 이유는 밤에 도어락을 사용할때 어두우니까

키패드가 보이도록 하기 위함입니다.

 

 

 

 

비밀번호 설정을 해줍니다. 비밀번호는 4자리까지 됩니다.

비밀번호는 0630으로 하기위해 입력하고있는 모습입니다.

 

 

 

 

비밀번호를 입력하니 비밀번호를 입력하는 글자가 출력됩니다.

여기서 키패드에서 A를 누르면 새 비밀번호 설정모드가 됩니다.

 

 

 

 

도어락 내부입니다. 서보모터를 사용하여 문고리를 조종합니다.

 

 

 

 

 

스피커와 스위치입니다. 도어락이 ON된다면 멜로디가 출력되고 스위치를 사용하여

멜로디를 ON/OFF 설정 할 수 있습니다.

 

 

 

 

사용한 ATMEGA128입니다. 선이 연결되있는것을 볼 수 있고

왼쪽 아래에 블루투스 모듈이 연결되어 있습니다.

 

 

 

스마트폰 앱으로 도어락을 ON/OFF하도록 만든 간단한 앱 입니다.

블루투스를 연결하고 비밀번호를 전송하는 기능만 있습니다.

 

 

 

 

 

 

- 실제 작동 영상 -

처음에 말한 구현할 기능들에대한 동영상입니다. 

 

2. LCD화면과 키패드를 이용하여 비밀번호설정 & 입력 하기

3. 키패드가 내려간 상태에서 만약 어둡다면 LED 키기 (조도센서 사용)

 

 

 

 

 

1. 서보모터를 사용하여 문 ON/OFF 하기

4. ON됬을때 멜로디 발생시키기 (멜로디 ON/OFF로 제어가능)

 

올바른 비밀번호를 입력했을때 ON되는 모습입니다.

 

 

 

 

 

4. ON됬을때 멜로디 발생시키기 (멜로디 ON/OFF로 제어가능)

5. 스마트폰 앱을 이용하여 도어락을 ON하기 (블루투스 연결)

비밀번호를 0630으로 설정해 놨습니다. 처음에 비밀번호를 0638을 보냈을땐 동작을 안하고 0630으로 보냈을땐 동작합니다.

 

 

소스코드(메인)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
//맨위 1번
#define F_CPU 16000000UL
#define cbi(sfr, bit) {(_SFR_BYTE(sfr) &= ~_BV(bit));}
#define sbi(sfr, bit) {(_SFR_BYTE(sfr) |= _BV(bit));}
 
#include <stdio.h>
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <string.h>
#include "lcd.h" 
#include "16key.h"
 
volatile int cnt=0;
volatile char BUFF[30],key,current_State='A';
volatile char number[5],password[5];
volatile int keynum=0;
volatile char rx_ch[5];
volatile int i=0;
volatile char close;
void init_password()
{
    memset(password,'\0',sizeof(password));
}
 
void init_number()
{
    memset(number,'\0',sizeof(number));
}
void set_password()
{
        key=keyScan();
        if( (key>='0')  & (key<='9'|| (key=='*'|| (key =='#'))
        {
        
            if(keynum==0)
            {
                password[0]=key;
                password[1]='\0';
                }
            if(keynum==1)
            {
                password[1]=key;
                password[2]='\0';
            }
            if(keynum==2)
            {
                password[2]=key;
                password[3]='\0';
            }
            if(keynum==3)
            {
                password[3]=key;
                password[4]='\0';
            }
            keynum++;
        }
}
void insert_password()
{
 
        key=keyScan();
        if(key=='A')
        {
                current_State='A'//A모드로 돌아가라!
                init_password(); //패스워드 초기화 
                init_number(); //현재 입력한거 초기화
 
        }
 
        if( (key>='0')  & (key<='9'|| (key=='*'|| (key =='#'))
        {
 
 
            if(keynum==0)
            {
                number[0]=key;
                number[1]='\0';
                }
            if(keynum==1)
            {
                number[1]=key;
                number[2]='\0';
            }
            if(keynum==2)
            {
                number[2]=key;
                number[3]='\0';
            }
            if(keynum==3)
            {
                number[3]=key;
                number[4]='\0';
            }
            keynum++;
        }
}
void sensor_init()
{
    DDRF=0xfc// PF0 ADC , PF1 SWITCH 
    PORTF |= 0x02;
    ADCSRA=0xe7;
    ADMUX=0x40;
    
}
 void timer_init()
 {
     DDRB=0xff;
     TCCR0=0x6f;
    //
    TCCR2=0x05;
    TIMSK = 0x40;
 
    //
}
 
void usart_init()
{
        UCSR0A=0x00;
          UCSR0B=0x90//송신부 & 수신부 활성화
          UCSR0C=0x06;
          UBRR0H=0;
          UBRR0L=103//9600@16MHz 고정
        SREG=0x80;
}
 
ISR(SIG_OVERFLOW2){
    TCNT2=0x40//0.01ms
    if(cnt>=1000)
    {
        DDRE=0x00;
        PORTE=0x00;
        close='C'//닫혀있다
        OCR0=0x0f;
        cnt=0;
    }
    else
    {
        if(close=='O'//열려있다.
        {
            DDRE=0xf0
            PORTE=0xf0;
            cnt++;
        }
    }
}
 
ISR(USART0_RX_vect)
{
    rx_ch[i]=UDR0;
    i++;
        
    if(i==4)
    {
        
        if((!strcmp(rx_ch,password)))//같다면 모터 돌아가기
        { 
            OCR0=0x20;
            close='O';
        }
 
        i=0;
        memset(rx_ch,'\0',sizeof(rx_ch));
    }
 
    
}
 
 
 
int main()
{
 
 
    DDRF=0xfe;
 
    lcd_init();
    sensor_init();
    timer_init();    
    usart_init();
    DDRE=0x00
    OCR0=0x0f//디폴트 (닫혀있다)
    //
    
    //
    while(1)
    {
         if(!(PINF&0x02)) 
        {
            if(ADC<500)
                PORTF|=0x04;
            else
                PORTF &= 0b1111011;
                        
            if(current_State=='A'//비밀번호 설정
            {
                set_password();
                sprintf(BUFF,"key : %s ",password);
                writeString_LCD(0,0,"set password");
                writeString_LCD(0,1,BUFF);
                if(keynum==4)
                {
                    keynum=0;
                    current_State='B';
                    Command_set(0x01);// 화면지우기
                     
                }
            }
 
            if(current_State=='B'//비밀번호 입력
            {
                insert_password();
                sprintf(BUFF,"key : %s ",number);
                writeString_LCD(0,0,"insert key");
                writeString_LCD(0,1,BUFF);
                if(keynum==4)
                {
                    keynum=0;
                    current_State='C'//비밀번호 확인 모드
                }
            }
            if(current_State=='C'//비밀번호 검사
            {
                if((!strcmp(number,password)))//같다면 모터 돌아가기
                {
                    OCR0=0x20//열어라
                    close='O'// 열려있다
                }
                memset(number,'\0',sizeof(number));
                Command_set(0x01);// 화면지우기
                current_State='B';         
            } 
        }
        else
            Command_set(0x01);// 화면지우기
 
    }
}
cs

 

 

12key.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
 
unsigned char keyScan(void){
    char KeyBuf=0xFF;  // 키 값이 들어갈 버퍼, 초기값 0xFF
    DDRD=0; PORTD=0xFF;  // 포트 초기값, 입력핀 내부풀업저항 사용
 
  //키 1번만 하려고 while문씀 
  
  
      DDRD=0x01; PORTD&=~0x01; _delay_us(1); // 1번째 줄 선택
      while(!(PIND&0x10))KeyBuf='D';
      while(!(PIND&0x20))KeyBuf='C';
      while(!(PIND&0x40))KeyBuf='B'//
    while(!(PIND&0x80))KeyBuf='A';
      DDRD=0; PORTD=0xFF// 1번째 줄 해제
      //
      DDRD=0x02; PORTD&=~0x02; _delay_us(5); // 2번째 줄 선택
      while(!(PIND&0x10))KeyBuf='#'//
      while(!(PIND&0x20))KeyBuf='9';
      while(!(PIND&0x40))KeyBuf='6';
      while(!(PIND&0x80))KeyBuf='3';
      DDRD=0; PORTD=0xFF// 2번째 줄 해제
      //
      DDRD=0x04; PORTD&=~0x04; _delay_us(5); // 3번째 줄 선택
      while(!(PIND&0x10))KeyBuf='0';
      while(!(PIND&0x20))KeyBuf='8';
      while(!(PIND&0x40))KeyBuf='5';
      while(!(PIND&0x80))KeyBuf='2';
      DDRD=0; PORTD=0xFF// 3번째 줄 해제
      //
      DDRD=0x08; PORTD&=~0x08; _delay_us(5); // 4번째 줄 선택
      while(!(PIND&0x10))KeyBuf='*';
      while(!(PIND&0x20))KeyBuf='7';
      while(!(PIND&0x40))KeyBuf='4';
      while(!(PIND&0x80))KeyBuf='1';
      DDRD=0; PORTD=0xFF// 4번째 줄 해제
  
  
  //
  return KeyBuf; // Key 없으면 0xFF 리턴
}
 
cs
 
 
lcd.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
//
 //
void E_pulse()
{
    sbi(PORTA,0);
    _delay_ms(1);
    cbi(PORTA,0);
}
void Command_set( char s)
{
    cbi(PORTA,2); // 명령어 모드
    PORTC=s;
    E_pulse();
}
 
void Data_set( char s)
{
    sbi(PORTA,2);
    PORTC=s;
    E_pulse();
}
void cursor_at(char x,char y)
{
    switch(y){
        case 0: y=0x80break;
        case 1: y=0xc0 break;
        case 2: y=0x94break;
        case 3: y=0xd4 break;
    }
    y=y+x;
    Command_set(y);
}
 
void writeString_LCD(char x, char y, char *str){
    cursor_at(x,y);
    while(*str)
    Data_set(*str++);
}
 
void lcd_init()
{
    DDRA=0xff// 0 : Enable  , 1 : R/W , 2 : RS
    DDRC=0xff//data output
 
    _delay_ms(30);
 
    Command_set(0x38); //나는 8비트 데이터버스를 사용할거야.
    Command_set(0x0c); //나는 표시 커서 블링크 기능을 선택 사용할거야.
    Command_set(0x06); //주소자동증가와 표시가 시프트하지않을거야
    Command_set(0x01);
    _delay_ms(1);
}
 
cs