Zámok na kód I.: Rozdiel medzi revíziami
Zo stránky SensorWiki
Bez shrnutí editace |
|||
| Riadok 4: | Riadok 4: | ||
== Zadanie == | == Zadanie == | ||
Zadaním projektu bolo naprogramovať číslicový zámok s maticovou klávesnicou 4x3 kde po zadaní hesla sa rozsvieti LED | Zadaním projektu bolo naprogramovať číslicový zámok s maticovou klávesnicou 4x3 kde sa výstup vypisuje na LCD display a po zadaní celého hesla sa rozsvieti LED. | ||
[[Obrázok:KlonArduinoMega2560.jpg|400px|thumb|center|Vývojová doska Arduino MEGA CH340.]] | [[Obrázok:KlonArduinoMega2560.jpg|400px|thumb|center|Vývojová doska Arduino MEGA CH340.]] | ||
Verzia z 21:21, 28. máj 2026
Záverečný projekt predmetu MIPS / LS2026 - Adam Čulák
Zadanie
Zadaním projektu bolo naprogramovať číslicový zámok s maticovou klávesnicou 4x3 kde sa výstup vypisuje na LCD display a po zadaní celého hesla sa rozsvieti LED.

Literatúra:
Analýza a opis riešenia
Cieľom projektu bolo vytvoriť číslicový zámok využívajúci 4×3 maticovú klávesnicu, LCD displej a signalizáciu pomocou LED diód. Používateľ zadáva štvorciferné heslo pomocou klávesnice, pričom priebežne zadávané znaky sú zobrazované na LCD displeji. Po potvrdení hesla systém vyhodnotí správnosť zadaného kódu a následne zobrazí výsledok na displeji, odošle správu cez UART rozhranie a rozsvieti príslušnú LED diódu.
Použité hardvérové komponenty:
- Arduino Mega 2560
- Maticová klávesnica 4×3 (Datasheet Membránová klávesnica pre Arduino 3 x 4 matice)
- LCD displej 16×2 kompatibilný s HD44780 (Pre LCD som išiel podľa inštrukcií z cvičenia 9.)
- 2× LED dióda (signalizácia správneho a nesprávneho hesla)
- Rezistory pre LED diódy
- Breadboard a prepojovacie vodiče
Maticová klávesnica je pripojená na port A mikrokontroléra. Prvé štyri piny portu slúžia ako výstupy pre riadky klávesnice a ďalšie tri piny sú nakonfigurované ako vstupy pre stĺpce. Na vstupoch sú aktivované interné pull-up rezistory, čím sa eliminuje potreba externých rezistorov. Tlačidlo * slúži ako backspace na vymazanie posledne zadaného čísla a tlačidlo # slúži ako enter na potvrdenie hesla.
LCD displej slúži na zobrazovanie aktuálne zadávaného hesla a stavových hlásení systému. Výpis na LCD je realizovaný pomocou upravenej knižnice z cvičení, ktorá bola prispôsobená odlišnému mapovaniu pinov na platforme Arduino Mega.
Signalizácia výsledku overenia hesla je realizovaná pomocou dvoch LED diód:
- zelená LED – správne heslo
- červená LED – nesprávne alebo neúplné heslo
Čas svietenia LED diód je riadený pomocou časovača Timer1 a prerušení, čím sa zabezpečí automatické vypnutie signalizácie bez blokovania hlavného programu.

Nezabudnite doplniť schému zapojenia! V texte by ste mali opísať základné veci zo zapojenia, samotná schéma nie je dostačujúci opis.

Algoritmus a program
Algoritmus programu využíva základné knižnice pre uart a lcd z cvičení, pričom knižnica pre lcd bola upravená tak, aby fungovala s doskou Arduino Mega 2560. Úprava spočíva najmä v zmene používaných portov, pretože porty požité pri mikrokontroléri ATmega2560 sa líšia od portov použitých pri mikrokontroléri ATmega328P.
Pre obsluhu 4×3 maticovej klávesnice bola vytvorená vlastná knižnica klavesnica.h. Čítanie stlačeného tlačidla je realizované pomocou princípu skenovania klávesnice po riadkoch. Všetky riadky sú štandardne nastavené na logickú úroveň HIGH (+5 V), pričom aktuálne skenovaný riadok je nastavený na LOW (uzemnený). Následne sa načítava stav stĺpcov. Ak je niektoré tlačidlo stlačené, dôjde k spojeniu príslušného riadku a stĺpca, čo umožní identifikovať konkrétne tlačidlo.
V inicializačnej funkcii keypad_init() sú piny 22 až 25 nastavené ako výstupy pre riadky klávesnice a piny 26 až 28 ako vstupy pre stĺpce. Na vstupných pinoch sú aktivované interné pull-up rezistory, aby bol zabezpečený stabilný logický stav pri nestlačených tlačidlách.
Funkcia keypad_getkey() postupne skenuje jednotlivé riadky. Pre každý riadok nastaví všetky riadky do stavu HIGH a následne aktuálny riadok do stavu LOW. Po krátkej stabilizačnej pauze sa kontrolujú vstupy stĺpcov. Ak je detekované stlačené tlačidlo, funkcia vráti číselnú hodnotu reprezentujúcu jeho pozíciu v matici klávesnice. Táto hodnota je vypočítaná podľa vzťahu k = 3 * r + c kde:
- k je výsledný identifikátor tlačidla
- r predstavuje index riadku
- c predstavuje index stĺpca
Tento spôsob nahrádza rozsiahle podmienky typu if-else jednoduchším a prehľadnejším výpočtom. Ak nie je stlačené žiadne tlačidlo, funkcia vracia hodnotu -1.
#define F_CPU 16000000UL
#define BAUD 115200
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "uart.h"
#include "klavesnica.h"
#include "lcd_ch.h"
// Macra na nastavenie a vynulovanie bitu z cičenia
#define set_bit(ADDRESS, BIT) (ADDRESS |= (1 << BIT))
#define clear_bit(ADDRESS, BIT) (ADDRESS &= ~(1 << BIT))
// Funkcia delay z cvičenia
void delay(int delay)
{
for (int i = 0; i< delay; i++) _delay_ms(1);
}
// Prerušenie pomomocov timeru na bliknutie LED
ISR(TIMER1_OVF_vect)
{
TCCR1B = 0; // Vypnutie časovača
clear_bit(PORTB, PB0);
clear_bit(PORTB, PB1);
}
int main(void)
{
char password[] = "0159"; // Premenná ukladajúca nastavené heslo
char guess[5] = ""; // Premenná ukladajúca hádané heslo
int index = 0; // Index pola hádaného hesla
int last_key = -1; // Premenná pre ulozenie posledného stlačeného tlačidla
// Inicializácia knižníc
uart_init();
keypad_init();
lcd_init();
// Nastavenie pinov pre LED
set_bit(DDRB, PB0);
set_bit(DDRB, PB1);
TIMSK1 |= (1 << TOIE1);
// Mapovanie cisel k znakom
char keys[4][3] = {
{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}
};
sei(); // Zapnutie interuptov pre zhasnutie LED diod
while(1)
{
int k = keypad_getkey(); // Premenná pre numerickú hodnotu navrátenú z knižnice klavesnica
if (k != -1 && last_key == -1)
{
_delay_ms(20); // Debounce
k = keypad_getkey();
if (k != -1)
{
// Dekódovanie číselnej hodnoty na znak
char key = keys[k/3][k%3];
// BACKSPACE (*)
if (key == '*' && index > 0)
{
guess[--index] = '\0';
lcd_clear();
lcd_print(guess);
}
// Kontrola spravnosti hesla po stlaceni ENTER (#) alebo automaticky po 4 znakoch
else if (key == '#' || index == 4)
{
if (index == 4)
{
guess[4] = '\0'; // Nastavenie posledného znaku na string end
int same = 1; // Premenná pre kontrolu či sú heslá rovnaké
for (int i = 0; i < 4; i++)
{
if (guess[i] != password[i])
{
same = 0;
break;
}
}
if (same)
{
set_bit(PORTB, PB0); // Zasvietenie LED
TCCR1B |= (1 << CS12) | (1 << CS10); // Prescale na 1024
TCNT1 = 0xC2F7; // Nastavenie TCNT1 na hodnotu aby mi po 1s vyplo LED
uart_puts("Spravne heslo\n"); // Výpis na uart
lcd_clear();
lcd_print("Spravne heslo"); // Výpis na LCD
}
else
{
set_bit(PORTB, PB1); // Zasvietenie LED
TCCR1B |= (1 << CS12) | (1 << CS10); // Prescale na 1024
TCNT1 = 0x85EE; // Nastavenie TCNT1 na hodnotu aby mi po 2s vyplo LED
uart_puts("Nespravne heslo\n"); // Výpis na uart
lcd_clear();
lcd_print("Nespravne heslo"); // Výpis na LCD
}
}
else
{
// Ak je stlacene # pred tým nez sa zadá úplne heslo
set_bit(PORTB, PB1); // Zasvietenie LED
TCCR1B |= (1 << CS12) | (1 << CS10); // Prescale na 1024
TCNT1 = 0x85EE; // Nastavenie TCNT1 na hodnotu aby mi po 2s vyplo LED
uart_puts("Neuplne heslo\n"); // Výpis na uart
lcd_clear();
lcd_print("Neuplne heslo"); // Výpis na LCD
}
// Reset hádaného hesla
for (int i = 0; i < 5; i++)
guess[i] = '\0';
index = 0;
}
// Stlacene tlacitko 0-9
else if (index < 4 && key != '*' && key != '#')
{
guess[index++] = key;
guess[index] = '\0';
// Vypis na LCD display
lcd_clear();
lcd_print(guess);
// Vypis na uart
uart_puts(guess);
uart_putc('\n');
}
}
}
// Aby sa nám tlacitko nestlacilo viac ako 1 krat
last_key = k;
}
}
void keypad_init(void);
int keypad_getkey(void);
#define F_CPU 16000000UL
#define BAUD 115200
#include <avr/io.h>
#include <util/delay.h>
void keypad_init(void)
{
// Riadky ako výstupy
DDRA |= (1<<PA0)|(1<<PA1)|(1<<PA2)|(1<<PA3);
// Stĺpce ako vstupy
DDRA &= ~((1<<PA4)|(1<<PA5)|(1<<PA6));
// Pull-up na stĺpcoch
PORTA |= (1<<PA4)|(1<<PA5)|(1<<PA6);
// Riadky default HIGH
PORTA |= (1<<PA0)|(1<<PA1)|(1<<PA2)|(1<<PA3);
}
int keypad_getkey(void)
{
for (int row = 0; row < 4; row++)
{
// Všetky riadky HIGH
PORTA |= (1<<PA0)|(1<<PA1)|(1<<PA2)|(1<<PA3);
// Aktuálny riadok LOW
PORTA &= ~(1 << row);
// Stabilizácia bez tohto moze prestať funkovať prvý stĺpec prtože sa nestihnú nastaviť zmeny z PORTA &= ~(1 << row);
_delay_us(5);
// Čítanie stĺpcov
if (!(PINA & (1<<PA6))) return row*3 + 0;
if (!(PINA & (1<<PA5))) return row*3 + 1;
if (!(PINA & (1<<PA4))) return row*3 + 2;
}
return -1; // Ak je nič nestlačené
}
Zdrojový kód: zdrojaky.zip
Overenie
Funkčnosť systému bola overená praktickým testovaním jednotlivých stavov programu. Testovanie pozostávalo z overenia správneho načítania stlačených kláves, správneho zobrazovania údajov na LCD displeji a kontroly reakcie systému na rôzne vstupy používateľa.

Overované boli nasledovné scenáre (jednotlivé scenáre sú zdokumentované vo videu):
- Zadanie správneho hesla
- Zadanie nesprávneho hesla
- Zadanie neúplného hesla
- Správnosť výpisu zadávaných údajov a stavových hlásení na LCD displeji
- Automatické potvrdenie hesla po zadaní štvrtého znaku bez potreby stlačenia tlačidla #
- Funkčnosť LED signalizácie pri jednotlivých stavoch systému (správne heslo, nesprávne heslo a neúplné heslo)
- Testovanie funkcie tlačidla # pre potvrdenie hesla
- Testovanie funkcie tlačidla * pre mazanie zadaných znakov
- Overenie resetovania vstupu po vyhodnotení hesla
Video:
Čo by som urobil inak
Pri spätnom pohľade na riešenia projektu vidím viacero miest, ktoré by bolo možné zlepšiť. V programe sa opakuje väčšie množstvo rovnakého kódu pri zobrazovaní správ a ovládaní LED. V budúcnosti by bolo vhodné vytvoriť samostatnú funkciu, ktorá by zabezpečila výpis stavových správ a aktiváciu LED, čím by sa program stal prehľadnejší a jednoduchšie udržiavateľný.
Ďalším možným vylepšením by bolo oddelenie logiky programu do viacerých modulov, napríklad samostatný modul pre správu hesla, modul pre používateľské rozhranie a modul pre signalizáciu. Takéto rozdelenie by zjednodušilo rozširovanie projektu.
Vylepšiť by sa dala aj bezpečnosť systému, napríklad implementáciou možnosti meniť heslo počas behu programu alebo pridaním blokovania vstupu po viacerých nesprávnych pokusoch o zadanie hesla.
Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte.