Till toppen

Projektmål

Att bygga ett kodlås med en form av touchskärm och mönsterigenkänning liknande låsskärmen på en mobiltelefon. Användaren ska alltså kunna skriva in både en sifferkod eller dra ett mönster med fingret för att låsa upp den. Detta är tänkt att fungera med hjälp av IR-sändare och fotodioder. Enheten ska kunna ta emot en kod av en användare som sparas. Sedan ska den kontrollera om den nya inslagna koden är samma som den första och då antingen ge eller neka åtkomst. Alla steg från att ange en ny kod till att slå in en kod för att låsa upp ska synas på en LCD-display.
1. Bild som visar startskärmen. Användaren måste ange en 4-siffrig kod.
2. Bild som visar en vald kod.
3. Kodlåset är klart för inmatning av en kod
4. Bild som visar en inmatad kod
5. Tillgång beviljad!
6. Det är möjligt att inmata en kod som är för kort.
7. Kodlåset kommer att skicka ett felmeddelande om koden är för kort.

Rapport

Abstract

In the following article, a group project in the course Digitala System is described. The main requirement of the project was to construct a prototype circuit using the microprocessor ATmega1284.

The purpose of this project is to allow the group members to familiarize themselves with project planning and teamwork, as well as circuit design and programming of a microprocessor.

The group decided on constructing a digital codelock that allows the user to set a personal code which is stored in the unit's memory, the user can then use the code to unlock the device. A code lock with an unorthodox kind of keypad was designed. The keypad was made by combining IR-diodes and photodiodes with the same wavelength on the light emitting spectrum.

This was visualized on a 16×2 LCD-display where prompts for the users and the entered codes were displayed. In combination with the LCD, some audio and visual aids were implemented in the form of a piezo buzzer as well as red, green and yellow LEDs. All the components were connected to the ATmega1284 which served as the foundation for the whole project. When testing the original prototype, an issue occured where the spreading angle of the IR diodes was too high and caused a disturbance with the photodiodes. The group came together and got to practice their problem solving skills which resulted in printing a new case for the diodes, this time with obstructions in the form of walls with holes in them. With this new case, the problem was solved and the prototype was completed.

PDF av rapporten kan laddas ned här.

Källkod

          /*
          * keypad.c
          *
          * Created: 2022-05-13 12:34:20
          * Author : ca4215be-s
          */ 
         
         
         
         #define F_CPU 16000000UL 
         #include  
         #include  
         #include  
         #include 
         
         
         
         int fill_entered(); // Fills code entering array with -1
         int fill_correct(); // Fills code checking array with -1
         void enter_digit(int enter); // Enters digit into enter array
         void enter_code(); // Checks state, either the checking code or entering code, uses functions such as checkCode and too_Short
         int checkCode(); // Compares checking array with enter array, returns true if code i correct
         int too_short(); // Checks if input into checking array is less than 4 elements, returns true if true
         void clear(); // Clears the checking array or the enter code array and LCD 
         
         
         
         void lcd_data(unsigned char data); // Writes data to LCD
         void lcd_cmd(unsigned char command); // Sends a command code to LCD
         void stringwrite(unsigned char s[]); // Builds string to be printed on LCD
         void lcd_initialise(); // Initializes LCD
         
         
         
         void beep(); // beep
         void green(); // green
         void red(); // red
         
         
         
         int correct_code[16]; 					
         int entered_code[16]; 
         
         
         
         static int choose_or_enter = 0;  // States (0 = choose code), (1 = enter code)
         static int counter = 0;			// Keeps track of next place in the code array where entered number is to be placed			
         
         
         
         int main(void) {
         
           DDRB=0xFF; 
           DDRA|=(1<<0)|(1<<1)|(1<<3)|(1<<4)|(1<<2);
         
           lcd_initialise();
         
           sei(); // Initializes Interrupt function
           PCICR =  0b00001000; // chooses interrupt register bank (port D) 
           PCMSK3 = 0b00000111; 
             
         
           fill_correct(); // fills correct_code array with *s
           fill_entered(); // fills entered_code array with *s
           
         
         while(1) {
         
         }
         
         
         
         }
         
         
         
         ISR(PCINT3_vect) { // Interrupt-routine for button-push
         
           _delay_ms(30);
         
           if (PIND == 0b00001001) {
             stringwrite("1");
             beep();
             enter_digit(1);
         
           }
         
           else if (PIND == 0b00001010) {
         
             stringwrite("2");
             beep();
             enter_digit(2);
         
           }
         
           else if (PIND == 0b00001100) {
         
             stringwrite("3");
             beep();
             enter_digit(3);
         
           }
         
           else if (PIND == 0b00010001) {
         
             stringwrite("4");
             beep();
             enter_digit(4);
         
           }
         
           else if (PIND == 0b00010010) {
         
             stringwrite("5");
             beep();
             enter_digit(5);
         
           }
         
           else if (PIND == 0b00010100) {
         
             stringwrite("6");
             beep();
             enter_digit(6);
         
           }
         
           else if (PIND == 0b00100001) {
         
             stringwrite("7");
             beep();
             enter_digit(7);
         
           }
         
           else if (PIND == 0b00100010) {
         
             stringwrite("8");
             beep();
             enter_digit(8);
         
           }
         
           else if (PIND == 0b00100100) {
         
             stringwrite("9");
             beep();
             enter_digit(9);
         
           }
         
           else if (PIND == 0b01000010) {
         
             stringwrite("0");
             beep();
             enter_digit(0);
         
           }
         
           else if (PIND == 0b01000100) {
         
             enter_code();
         
           }
         
           else if (PIND == 0b01000001) {
         
             beep();
             clear();
             beep();
         
           }
         
           _delay_ms(40);
         
         }
         
         
         
         int fill_entered() { // 0 = correct_code, 1 = entered_code
         
           for (int k = 0; k<16; k++) {
             entered_code[k] = -1;
         
           }
         
         }
         
         
         
         int fill_correct() { // 0 = correct_code, 1 = entered_code
         
           for (int i = 0; i<16; i++) {
             correct_code[i] = -1;
         
           }
         
         }
         
         
         
         void enter_digit(int enter) {
         
           if (choose_or_enter == 0) {
             correct_code[counter] = enter;
             counter++;
         
           }
         
           else if (choose_or_enter == 1) {
             entered_code[counter] = enter;
             counter++;
         
           }
         
         }
         
         
         
         void enter_code() {
         
           lcd_cmd(0x01);
         
           if (choose_or_enter == 0) {  // when choosing code
         
             if (too_short()) {
               lcd_cmd(0x80);
               stringwrite("Code too short,");
               lcd_cmd(0xC0);
               stringwrite("enter code > 4");
               _delay_ms(1500);
               clear();
         
             }
         
             else {
         
               choose_or_enter = 1;
               lcd_cmd(0x80);
               stringwrite("Enter code:");
               lcd_cmd(0xC0);
               counter = 0;
         
             }
         
           }
         
           else if (choose_or_enter == 1) {  // when entering code
         
             if (checkCode()) {
               green();
               lcd_cmd(0x80);
               stringwrite("Access Granted!");
               lcd_cmd(0xC0);
               _delay_ms(1500);
               clear();
         
             }
         
             else {
         
               red();
               lcd_cmd(0x80);
               stringwrite("Access Denied!");
               lcd_cmd(0xC0);
               _delay_ms(1500);
               clear();
         
             }
         
             counter = 0;
         
           }
         
         }
         
         
         
         int checkCode() {
           if (entered_code[0] == -1){
             return 0;
           }
           for (int i = 0; i<16; i++) {
             if (entered_code[i] != -1 && entered_code[i] != correct_code[i]) {
               return 0;
             }
           }
           return 1;
         }
         
         
         
         int too_short() {
         
           int counter1 = 0;
           
           for (int y = 0; y<16; y++) {
             if (correct_code[y] == -1) {
               break;
             }
             counter1++;
           }
         
           if (counter1 < 4) {
             return 1;
           }
         
           else {
             return 0;
           }
         
         }
         
         
         
         void clear() {
         
           lcd_cmd(0x01);
         
           if (choose_or_enter == 0) {
             lcd_cmd(0x80);
             stringwrite("Choose code:");
             lcd_cmd(0xC0);
             fill_correct(); // fills correct_code array with -1
             counter = 0;
         
           }
         
           else if (choose_or_enter == 1) {
             lcd_cmd(0x80);
             stringwrite("Enter code:");
             lcd_cmd(0xC0);
             fill_entered(); // fills entered_code array with -1
             counter = 0;
         
           }
         
         }
         
         
         
         void lcd_data(unsigned char data) {
           PORTB=data;
           PORTA|=(1<<0);
           PORTA|=(1<<1);
           _delay_ms(10);
           PORTA&=(~(1<<1));
           _delay_ms(10);
         }
         
         
         
         void lcd_cmd(unsigned char command) {
           PORTB=command;
           PORTA &= ~(1<<0);
           PORTA |=(1<<1);
           
           _delay_ms(10);
           PORTA &=(~(1<<1));
           _delay_ms(10);
         
         }
         
         
         
         void stringwrite(unsigned char s[]) {
         
           int i;
         
           for (i=0;s[i]!=0;i++) {
             lcd_data(s[i]);
           }
         
         }
         
         
         
         void lcd_initialise() {
         
           lcd_cmd(0x38); // 16x2 8-bit
           lcd_cmd(0x0C); // display on, cursor off
           lcd_cmd(0x06); // Auto Increment cursor
           lcd_cmd(0x01); // clear display
           lcd_cmd(0x02); // cursor at home position
           stringwrite("Choose Code:");
           lcd_cmd(0xC0);
         
         }
         
         
         
         void beep() {
         
           PORTA|=(1<<3);
           _delay_ms(200);
           PORTA&=~(1<<3);
         
         }
         
         
         
         void red() {
         
           PORTA|=(1<<2);
           _delay_ms(200);
           PORTA&=~(1<<2);
         
         }
         
         
         
         void green() {
         
           PORTA|=(1<<4);
           _delay_ms(200);
           PORTA&=~(1<<4);
         
         }
        
Koden kan laddas ned här.

Kopplingsschema



Klicka på bilden för att öppna större version.