Chia sẻ Khóa điện CodeLock dùng Atmega 8 ( hoàn thiện, có video)

xaxa9ztb

Kỹ sư
Thành viên BQT
#1
Mấy ngày trước mình đã đăng bài này nhưng có thay đổi về thiết kế sau khi làm phần cứng nên mình đã xóa đi và thiết kế lại. Thay đổi các vấn đề như sau:​
  1. Khóa điện mình tưởng là có lò xo. Nhưng khi lắp mới biết nó có hai hành trình đóng mở (thò ra thụt vào) khi đổi chiều dòng điện. Vậy nên bài hôm trc dùng 1 relay để đóng ngắt là k thể làm được. Mình đã thiết kế lại cầu H để điểu khiển chiều dòng điện. Mình dùng 4 con relay để làm cầu H cho nó đơn giản và dễ hiểu. Khóa điện này mua ở ngoài Minh Hà, chạy điện 9-12VDC. Bên Minh Hà có treo cái khóa này ở trên tường, nhưng họ đóng mở bằng RF điều khiển 4 con relays.
  2. Mạch nguồn hôm trước dùng 7805 rất là nóng vì mạch này chạy liên tục 24/24h. Mình đã thay bằng 7805 bằng Lm2576 cho dòng lớn hơn, ổn định hơn và ít nóng hơn 7805​
Tính năng:
  1. Không reset password về mặc định ban đầu (1111) khi bị mất nguồn. Vì dữ liệu được lưu vào eeprom.​
  2. Có thể change pass bất kì lúc nào. Sau khi nhập pass từ keypad , ấn phím A để changepass, ấn phím 'Ok' ( * ). khi changepass, nhập hai lần password mới để xác nhận​
  3. Mật khẩu là một số tự nhiên từ 1-9999. Nếu nhập số quá 4 chữ số sẽ báo "Invalid Pass"​
  4. Tự động đóng băng hệ thống trong 1 khoảng thời gian sau khi nhập sai pass 4 lần.​
  5. Nhập số giống như trên điện thoại. Nhập sai 1 ký tự ấn phím 'Del' (#) để xóa kí tự vừa nhập. Ấn phím 'D' để xóa kí tự vừa nhập. Trong chế độ changepass có thể bấm phím 'B' để hủy change pass, thoát ra ngoài​
  6. Khi phím được ấn thì còi chip kêu 1 tiếng. Ngoài ra còn kêu 2 tiếng, 3 tiếng hoặc 4 tiếng tùy vào chức năng đang sử dụng​
Mạch Nguyên lý:
Mạch nguồn:
powerschemtic_zps42357f28.png

Mạch cầu H (4 relays):
relayschematic_zps4a137572.png

Mạch điều khiển: (quên mất chân reset của jump nạp isp :D)

controlerschematic_zps9a91d620.png

Code: mình viết bằng avrstudio, các bạn xem file đính kèm bên dưới, nếu file project không mở được thì các bạn tạo project mới rồi add các file .c .h của mình vào là đc.​
  • Hàm quét Keypad 4x4:
/*
* keypad.h
*
* Created: 15/05/2014 4:10:46 SA
* Author: LeThanhTung
*/


#ifndef KEYPAD_H_
#define KEYPAD_H_
#include <avr/io.h>
#include <util/delay.h>
#define KEYPAD_DDR DDRD
#define KEYPAD_PORT PORTD
#define KEYPAD_PIN PIND

uint8_t scan_code[4]={0x0E,0x0D,0x0B,0x07};
uint8_t ascii_code[4][4]={ {'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'},};


uint8_t GetKeyPressed()
{
//---khai bao huong cho cac chan ket noi keypad
KEYPAD_PORT=0x0F; //*
KEYPAD_DDR=0xF0; //*
//*********************************************
uint8_t i,j,keyin;
for(i=0;i<4;i++)
{
KEYPAD_PORT=0xFF-(1<<(i+4));
_delay_ms(40);
keyin=KEYPAD_PIN & 0x0F;
if(keyin!=0x0F)
for(j=0;j<4;j++)
if(keyin==scan_code[j]) return ascii_code[j];
}
return 0;
}
#endif /* KEYPAD_H_ */

  • Hàm đóng mở relays để bật tắt và đổi chiều dòng điện:
/*
* relay.h
*
* Created: 21/05/2014 9:41:14 CH
* Author: LeThanhTung
*/

#ifndef RELAY_H_
#define RELAY_H_
#include <avr/io.h>
#define Relay_PORT PORTC
#define Relay_DDR DDRC
//mo
void open()
{ Relay_PORT =0x21; //treo cao pin 0 va 5
_delay_ms(500);
Relay_DDR =0x21; //pin pC0 pc5 set la input
lcd_clrscr();
lcd_gotoxy(0,0);
lcd_puts("Open the door");
_delay_ms(50);
}
// dong cua (khoa day ra)
void close()
{ Relay_PORT =0x12; //treo cao pin 1 va 4
_delay_ms(500);
Relay_DDR =0x12; // pin pC4 pc1 set la output
lcd_clrscr();
lcd_gotoxy(0,0);
lcd_puts("Close the door");
_delay_ms(2000); // thoi gian du dai de khoa kip day ra
Relay_DDR =0x00;
Relay_PORT = 0x00; // off tat ca cac relay. de tiet kiem dien
}
#endif /* RELAY_H_ */
    • Khai báo giá trị mặc định ban đầu của pass:
uint16_t EEMEM pass1 = 1111;

    • Chương trình chính:
#include <avr/io.h>
#define F_CPU 12000000UL
#include <util/delay.h>
#include <avr/eeprom.h>
#include "lcd.h"
#include "keypad.h"
#include "relay.h"
#include "buzzer.h"
#include "user.h"
#include "changepass.h"

int main(){
uint16_t key2;
uint16_t number=0, i =0,l=0;
lcd_init(LCD_DISP_ON);
lcd_clrscr();
while(1)
{
lcd_gotoxy(0,0);
lcd_puts("Enter password: ");
key2=GetKeyPressed(); //doc keypad
//neu mot trong cac phim tu 0-9 dc bam thi giatri = giatri*10 +(key-48)
//vi du: gia tri =123. sau khi bam phim 1 (ma ascii la 49). giatri moi se la 123*10 +(49-48) =1231
if((key2=='0')||(key2=='1')||(key2=='2')||(key2=='3')||(key2=='4')||(key2=='5')||(key2=='6')||(key2=='7')||(key2=='8')||(key2=='9'))
{
_1beep();
number = ((number*10) + (key2-48));
i++;
if((i>4)||(i<0))
{
_delay_ms(300);
i=0;
number=0;
lcd_clrscr();
lcd_gotoxy(0,0);
_3beep();
lcd_puts("Invalid Pass"); //qua 4 chu so
_delay_ms(500);
}
else if ((i>0)&&(i<5))
{
lcd_gotoxy(i,1);
lcd_putc(42);
}
} //end of IF phim bam tu 0-9
//bam D de nhap lai tu dau. xoa gia tri
else if(key2 == 'D')
{
lcd_clrscr();
number = 0;
_1beep();
i=0;
}//end of Xoa gia tri
// bam # de xoa ki tu vua nhap sai. 1234->123
else if (key2=='#')
{
lcd_gotoxy(i,1);
lcd_puts(" ");
i--;
number = number/10;
_1beep();
} //end of Xoa gia tri
// bam * (OK) de so sanh gia tri nhap vao voi pass de mo cua
else if (key2=='*')
{
_1beep();
_delay_ms(300);
// neu gia tri nhao vao bang pass luu san trong eeprom, mo cua
if (number == eeprom_read_word(&pass1))
{
_2beep();
_delay_ms(50);
open(); // open the door
_delay_ms(10000); // sau 10s dong cua //xung 8mhz
_2beep();
_delay_ms(50);
close(); //close the door
number=0,
i =0;
l=0;
}
//neu gia tri khac pass luu san trong eeprom, khong cho mo cua
else if (number != eeprom_read_word(&pass1))
{
l++;
lcd_clrscr();
_3beep();
lcd_puts("wrong pass"); // pass sai
_delay_ms(500);
if (l>3)
{
lcd_clrscr();
lcd_gotoxy(0,0);
_4beep();
lcd_puts("NOT ALLOW IN 30sec");
_delay_ms(30000); // dong bang he thong sau 4 lan nhap sai pass
l=0;
lcd_clrscr();
_2beep();
}

number=0,
i =0;
}
}
// bam phim A de vao che do changpass
else if (key2=='A') //bam A changepass
{
_1beep();
_delay_ms(100);
//neu giatri nhap vao bang gia tri luu san trong epprom thi cho changepass
if (number == eeprom_read_word(&pass1))
{
change_pass();
lcd_clrscr();
number=0,
i =0;
l=0;
}// end of change pass
else if (number != eeprom_read_word(&pass1))
{
l++;
lcd_clrscr();
_3beep();
lcd_puts("Wrong pass");
_delay_ms(500);
if (l>3)
{
lcd_clrscr();
lcd_gotoxy(0,0);
_4beep();
lcd_puts("NOT ALLOW IN 30sec");
_delay_ms(30000); // dong bang he thong sau 4 lan nhap sai pass
l=0;
lcd_clrscr();
_2beep();
}
number=0,
i =0;
}
}//end of changepass
}//end of while(1)

}//end of ham main
  • Chương trình Changepass:
/*
* changepass.h
*
* Created: 22/05/2014 7:23:09 SA
* Author: LeThanhTung
*/

#ifndef CHANGEPASS_H_
#define CHANGEPASS_H_
#include <avr/io.h>
#include <util/delay.h>
#include <avr/eeprom.h>
#include "lcd.h"
#include "keypad.h"
#include "relay.h"
#include "buzzer.h"
#include "user.h"
void change_pass()
{ uint16_t key1,m=0,n=0;
unsigned char flag1=1, flag2 =1;
int j=0,k=0;
lcd_clrscr();
while(flag1==1)
{
lcd_gotoxy(0,0);
lcd_puts("Input new pass:");
key1=GetKeyPressed();
if((key1=='0')||(key1=='1')||(key1=='2')||(key1=='3')||(key1=='4')||(key1=='5')||(key1=='6')||(key1=='7')||(key1=='8')||(key1=='9'))
{
_1beep();

n = ((n*10) + (key1-48));
j++;
if((j>4)||(j<0))
{
_delay_ms(300);
j=0;
n=0;
lcd_clrscr();
lcd_gotoxy(0,0);
_3beep();
lcd_puts("Invalid Pass"); //qua 4 chu so
_delay_ms(500);
}
else if ((j>0)&&(j<5))
{
lcd_gotoxy(j,1);
lcd_putc(42);
}
}
else if(key1 == 'D') // bam D de huy nhap so
{
lcd_clrscr();
n = 0;
_1beep();
j=0;
}
else if (key1=='#') // bam # de huy 1 chu so vua nhap sai
{
lcd_gotoxy(j,1);
lcd_puts(" ");
j--;
n = n/10;
_1beep();
}

else if (key1=='B') //huy check va change pass
{
_1beep();
j=0;
n=0;
flag1=0;
}
else if (key1=='*') //check lai pass 1 lan nua
{
_1beep();
lcd_clrscr();
while(flag2==1)
{
lcd_gotoxy(0,0);
lcd_puts("Input again:");
key1=GetKeyPressed();
if((key1=='0')||(key1=='1')||(key1=='2')||(key1=='3')||(key1=='4')||(key1=='5')||(key1=='6')||(key1=='7')||(key1=='8')||(key1=='9'))
{
_1beep();
m = ((m*10) + (key1-48));
k++;
if((k>4)||(k<0))
{
_delay_ms(300);
k=0;
m=0;
lcd_clrscr();
lcd_gotoxy(0,0);
_3beep();
lcd_puts("Invalid Pass");
_delay_ms(500);
}
else if ((k>0)&&(k<5))
{
lcd_gotoxy(k,1);
lcd_putc(42);
}

}
else if(key1 == 'D')
{
lcd_clrscr();
m = 0;
_1beep();
k=0;
}
else if (key1=='#')
{
_1beep();
lcd_gotoxy(k,1);
lcd_puts(" ");
k--;
m = m/10;
}
else if (key1=='B') // huy check va change pass
{
_1beep();
j=0;
n=0;
flag2=0;
flag1=0;
}
else if (key1=='*') //bam OK
{
_1beep();
_delay_ms(300);
if (m == n)
{
lcd_clrscr();
lcd_puts("checked OK");
_2beep(); // neu check pass ok, se luu lai vao epprom va chuyen gia tri co ve 0=> thoat vong lap
_delay_ms(500);
eeprom_write_word(&pass1,m);
lcd_clrscr();
lcd_gotoxy(0,0);
lcd_puts("pass is changed");
_2beep();
_delay_ms(500);
lcd_clrscr();
flag2=0; //thoat vong lap check
flag1=0; //thoat ham change
}
else if(m != n)
{
lcd_clrscr();
lcd_puts(" checked Wrong"); // check pass sai, quay lai vong lap
m=0;
_3beep();
k=0;
flag2 =1; //lap lai check
flag1=1; //lap lai change
_delay_ms(500);
lcd_clrscr();
}
} //end of '*'
} //end while
}// end of check
} //end of change
} //thoat ham change
#endif /* CHANGEPASS_H_ */
  • Ngoài ra còn có thêm chương trình cho LCD và Còi chip, các bạn xem chi tiết trong file đính kèm.
PCB: mình thiết kế thành hai board: 1 board 1 lớp gồm mạch nguồn và 4 relays, 1 board 2 lớp gồm chip at8, keypad, lcd, jump, conector
  1. board nguồn
pcbrelay2_zps211cf726.png
pcdrelay1_zps7e6db4fc (1).png

2. Board điều khiển:
Mặt trên:
pcbschematicscontrolboardtop_zpscc00f62a.png
pcd2top_zpsbfc3df67.png

Mặt dưới
pcbschematicscontrolboardbot_zpsf151fa9a.png
pcb2bot_zpsa4d602fe.png

Linh Kiện:
Vi xử lý: atmega8, lcd 16x2, biến trở 3 chân 10k , buzzer 5V, led 3mm, diode dán ss43, tụ 103 dán 0805, tụ 104 dán 0805, trở 1k 330 Ohm dán, jump đực, jump cái, jump isp, header4 + dây 4, khóa điện.
IC nguồn 2576T (5 chân thẳng TO 220-5), tụ 470uF/35V, tụ 1000uF, tụ 104, cuộn cảm 220uH, công tắc nhấn 6 chân, jack DC IN, Relay 5v 10A, transistor npn ECB C1815, led 3mm, trở 330, header 4, header 2.
Video: vì mạch in mình đặt chưa được lấy nên mình cắm tạm lên boardtest trước


p/s: Lần này đăng chắc là hoàn chỉnh rồi, test không thấy có lỗi nữa. Ở board mạch relay và nguồn có 1 dây phải câu lên trên. mình định thêm mấy con diode chống dòng ngược nữa nhưng k thiết kế nổi 1 mặt, thực nghiệm thì thấy dòng ngược k bị ảnh hưởng nhiều ( khi tắt relays thì có thấy khóa điện "rung rinh" :).

Bên dưới mình đính kèm file bao gồm code, file thiết kế altium, một số screenshot. Riêng về khoản mô phỏng Proteus thì mình k biết mô phỏng có giá trị ban đầu của epprom như thế nào, toàn lỗi thôi. Với lại mình có kit ATmega8 rồi nên k cần dùng mô phỏng, cứ làm đến đâu thì nạp thẳng vào kit để test.
Cảm ơn mọi người đã quan tâm. Bạn nào có góp ý gì thì cứ đưa ra mình sẽ vui vẻ đón nhận :))
Nếu có sai sót gì thì báo mình luôn nhé :)

Đính kèm: 4Share.vn :: Tot nhat, nhanh nhat
update #2
 

Đính kèm

Sửa lần cuối:

xaxa9ztb

Kỹ sư
Thành viên BQT
#2
update: hôm nay mới hàn đc cái board điều khiển. phát hiện ra là chân 5 (RST) của jump isp chưa nốt vào với PC6 :'(. lại phải câu 1 dây..
cái này bất tiện cho nạp mạch, nếu bác nào nạp code bên ngoài thì k cần câu dây cũng đc. mạch chạy ngon lành.
Em đang kiếm cái nguồn 12v 2A rồi lắp khóa điện vào nữa là ok. ở nhà có cái nguồn 9v 0.6A khi chạy khóa điện thì toàn sụt nguồn. Khóa của tàu nên k biết chính xác công suất là bao nhiêu =='
IMG-20140607-00013.jpg


 
Sửa lần cuối:

vanmanh1988

Học sinh trung cấp
#3
Sao tích hợp nguồn luôn đi bạn. Cắm là chạy khỏi phải kết nối nhiều
 

xaxa9ztb

Kỹ sư
Thành viên BQT
#4
Sao tích hợp nguồn luôn đi bạn. Cắm là chạy khỏi phải kết nối nhiều
nguồn mình để tách riêng ra vì trên thực tế màn hình và phím bấm sẽ để ở ngoài cửa, còn cơ cấu khóa điện, chip điều khiển ngta sẽ để trong nhà, chứ chẳng ai dại lại để ở ngoài cửa cả :D
 

vanmanh1988

Học sinh trung cấp
#5
Mình đâu có nói để chip ở bên ngoài cửa đâu nà. hjhjj
 

mt7m

Học sinh phổ thông
#6
Giúp mình đoạn code ghi pass vào eeprom AVR. không bít là khai báo và code như thế nào. Thanks mọi người.
 
Sửa lần cuối:

xaxa9ztb

Kỹ sư
Thành viên BQT
#7
Giúp mình đoạn code ghi pass vào eeprom. không bít là khai báo như thế nào. Thanks mọi người.
Khai báo giá trị ban đầu
Mã:
uint16_t EEMEM pass1 = 1111; // khai báo biến pass1 trong EEMEM
Đọc giá trị từ eeprom
Mã:
eeprom_read_word(&pass1); //hàm đọc giá trị từ biến pass1
ghi giá trị vào eeprom
Mã:
eeprom_write_word(&pass1,m);//hàm ghi giá trị m vào biến pass1
sử dụng thuộc tính EEMEM của epprom thì cách ghi và đọc rất đơn giản, giống như làm việc với 1 biến bình thường thôi
 

Đính kèm

Quảng cáo Google

Quảng cáo Google