Marcus Remnélius Bou
Edwin Ericsson
Mohammed El-Dimassi
Casper Bernhardsson
Kris Jacobs
Lunds Tekniska Högskola, Campus Helsingborg
2022-05-23
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./* * keypad.c * * Created: 2022-05-13 12:34:20 * Author : ca4215be-s */ #define F_CPU 16000000UL #includeKoden kan laddas ned här.#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); }