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
#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.