Zámok na kód I.: Rozdiel medzi revíziami
Zo stránky SensorWiki
Bez shrnutí editace |
|||
| (9 medziľahlých úprav od rovnakého používateľa nie je zobrazených.) | |||
| Riadok 6: | Riadok 6: | ||
Sem príde text zadania, ak bolo len voľne formulované, rozpíšte ho podrobnejšie | Sem príde text zadania, ak bolo len voľne formulované, rozpíšte ho podrobnejšie | ||
[[Obrázok:KlonArduinoMega2560.jpg|400px|thumb|center|Vývojová doska | [[Obrázok:KlonArduinoMega2560.jpg|400px|thumb|center|Vývojová doska Arduino MEGA CH340.]] | ||
'''Literatúra:''' | '''Literatúra:''' | ||
| Riadok 19: | Riadok 19: | ||
Podrobne opíšte použité komponenty (okrem základnej dosky s ATmega328P procesorom), pridajte linky na datasheety alebo opis obvodu. | Podrobne opíšte použité komponenty (okrem základnej dosky s ATmega328P procesorom), pridajte linky na datasheety alebo opis obvodu. | ||
[[Súbor: | [[Súbor:AdamČulákCelkovýPohladNaZapojenie.jpg|400px|thumb|center|Celkový pohľad na zariadenie.]] | ||
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. | 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. | ||
[[Súbor: | [[Súbor:AdamČulákMIPSProjektShémaZapojenia.png|400px|thumb|center|Schéma zapojenia.]] | ||
=== Algoritmus a program === | === Algoritmus a program === | ||
Algoritmus programu využíva | 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: | |||
<ul> | |||
<li>k je výsledný identifikátor tlačidla</li> | |||
<li>r predstavuje index riadku</li> | |||
<li>c predstavuje index stĺpca</li> | |||
</ul> | |||
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. | |||
<tabs> | <tabs> | ||
<tab name="AVR C-code"><syntaxhighlight lang="c++" style="background: LightYellow;"> | <tab name="AVR C-code"><syntaxhighlight lang="c++" style="background: LightYellow;"> | ||
#define F_CPU 16000000UL | |||
#define BAUD 115200 | |||
#include <avr/io.h> | #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) | 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 stlacenného tlacitka | |||
// Inicializácia knižníc | |||
uart_init(); | |||
keypad_init(); | |||
lcd_init(); | |||
// Nastavenie pinou 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; | |||
} | |||
} | } | ||
</syntaxhighlight ></tab> | </syntaxhighlight ></tab> | ||
<tab name=" | <tab name="klavesnica.h"><syntaxhighlight lang="c++" style="background: LightYellow;"> | ||
void keypad_init(void); | |||
int keypad_getkey(void); | |||
</syntaxhighlight ></tab> | |||
<tab name="klavesnica.c"><syntaxhighlight lang="c++" style="background: LightYellow;"> | |||
#define F_CPU 16000000UL | |||
#define BAUD 115200 | |||
#include <avr/io.h> | #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é | |||
} | |||
</syntaxhighlight ></tab> | </syntaxhighlight ></tab> | ||
</tabs> | </tabs> | ||
Zdrojový kód: [[Médiá:projektMenoPriezvisko.zip|zdrojaky.zip]] | Zdrojový kód: [[Médiá:projektMenoPriezvisko.zip|zdrojaky.zip]] | ||
| Riadok 67: | Riadok 253: | ||
Na konci uvádzame fotku hotového zariadenia. | Na konci uvádzame fotku hotového zariadenia. | ||
[[Súbor: | [[Súbor:AdamČulákCelkovýPohladNaZapojenie.jpg|400px|thumb|center|Aplikácia.]] | ||
'''Video:''' | '''Video:''' | ||
<center><youtube>D0UnqGm_miA</youtube></center> | <center><youtube>D0UnqGm_miA</youtube></center> | ||
== Čo by som urobil inak == | == Čo by som urobil inak == | ||
Aktuálna revízia z 21:45, 10. máj 2026
Záverečný projekt predmetu MIPS / LS2026 - Adam Čulák
Zadanie
Sem príde text zadania, ak bolo len voľne formulované, rozpíšte ho podrobnejšie

Literatúra:
Analýza a opis riešenia
Opíšte sem čo a ako ste spravili, ak treba, doplňte obrázkami... Podrobne opíšte použité komponenty (okrem základnej dosky s ATmega328P procesorom), pridajte linky na datasheety alebo opis obvodu.

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 stlacenného tlacitka
// Inicializácia knižníc
uart_init();
keypad_init();
lcd_init();
// Nastavenie pinou 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
Ako ste overili funkciu, napríklad... Na používanie našej aplikácie stačia dve tlačítka a postup používania je opísaný v sekcii popis riešenia. Na konci uvádzame fotku hotového zariadenia.

Video:
Čo by som urobil inak
Zamyslite sa spätne nad problémom, ktorý ste riešili a napíšte, čo sa vám nepodarilo a nabudúce by ste spravili inak.
Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte.