Simon's Game: Rozdiel medzi revíziami
Z SensorWiki
(Vytvorená stránka „Záverečný projekt predmetu MIPS / LS2024 - '''Meno Priezvisko''' == Zadanie == Sem príde text zadania, ak bolo len voľne formulované, rozpíšte ho podrobnejši…“) |
|||
(25 medziľahlých úprav od rovnakého používateľa nie je zobrazených.) | |||
Riadok 1: | Riadok 1: | ||
− | Záverečný projekt predmetu MIPS / LS2024 - ''' | + | Záverečný projekt predmetu MIPS / LS2024 - '''Ondrej Tarcal''' |
== Zadanie == | == Zadanie == | ||
− | + | Cieľom zadania bolo naprogramovať minihru Simon's game. V skratke minihra by mala fungovať tak, že doska generuje náhodnú sekvenciu a my ju musíme následne zopakovať. | |
− | [[Obrázok: | + | [[Obrázok:Arduinopinout.png|400px|thumb|center|Doska Arduino UNO R3.]] |
'''Literatúra:''' | '''Literatúra:''' | ||
− | * [ | + | * [https://docs.arduino.cc/resources/datasheets/A000066-datasheet.pdf Dokumentácia k doske Arduino Uno R3] |
− | + | ||
Riadok 17: | Riadok 17: | ||
== Analýza a opis riešenia == | == Analýza a opis riešenia == | ||
− | + | Tento program som vytvoril na ovládanie štyroch LEDiek pomocou joysticku. Najprv sa navrhlo samotné ovládanie LEDiek joystickom. Následne som dokódoval aby sa najprv LEDky rozsvietili v náhodnej sekvencii. Nakoniec som dokódoval aby po doznení danej sekvencie uživateľ danú sekvenciu zopakoval a program vyhodnotí, či sa sekvencia rovná alebo nerovná roszvietením LEDiek. Joystick sa taktiež využil na zresetovanie a opakované spustenie novej sekvencie aby sa nemusel využívať reset button na doske Arduino. | |
+ | |||
+ | [[Súbor:Schemasimon.png|400px|thumb|center|Schéma zapojenia joysticku a LEDiek.]] | ||
+ | |||
− | |||
− | + | [[Súbor:Diagramfinalfinal.png|400px|thumb|center|Schéma zapojenia joysticku a LEDiek.]] | |
− | |||
+ | === Program === | ||
+ | 1. Definície a Inicializácie | ||
− | + | Naprv sa preddefinovali makrá pre LEDky a ich polohy a mŕtve zóny joysticka. Inicializácia ADC prevodníka, čítanie z ADC, inicializacia LEDiek, tlačidla na joysticku a kontrola stlačenia tlačidla | |
− | + | 2. Funkcie pre samotnú hru | |
+ | |||
+ | Zobrazenie LEDiek, generovanie náhodných sekvencií a následne zobrazenie sekvencií cez LEDky. Získanie sekvencie od uživateľa cez joystick, kontrola sekvencie a indikácia úspechu alebo neúspechu | ||
+ | |||
+ | 3. Main funkcie | ||
+ | |||
+ | V časti main sa program neustále opakuje, generuje náhodne sekvencie, zobrazuje ich pomocou LEDiek, získava od užívateľa sekvencie a porovnáva ich zhodnosť. Program čaká na stlačenie tlačidla na joysticku pre začatie novej sekvencie. | ||
Riadok 35: | Riadok 44: | ||
#include <avr/io.h> | #include <avr/io.h> | ||
− | int | + | #include <avr/io.h> |
− | { | + | #include <util/delay.h> |
− | + | #include <stdlib.h> | |
+ | #include <stdbool.h> | ||
+ | |||
+ | #define F_CPU 16000000UL | ||
+ | |||
+ | #define LED_LEFT PD2 | ||
+ | #define LED_RIGHT PD3 | ||
+ | #define LED_DOWN PD4 | ||
+ | #define LED_UP PD5 | ||
+ | |||
+ | #define BUTTON_PIN PD6 | ||
+ | |||
+ | #define THRESHOLD_X_MIN 300 | ||
+ | #define THRESHOLD_X_MAX 700 | ||
+ | #define THRESHOLD_Y_MIN 300 | ||
+ | #define THRESHOLD_Y_MAX 700 | ||
+ | |||
+ | void ADC_Init() { | ||
+ | ADMUX = (1 << REFS0); // Set ADC reference to AVCC | ||
+ | ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // Zapne ADC a nastavi predelicku na 128 | ||
+ | } | ||
+ | |||
+ | uint16_t ADC_Read(uint8_t channel) { | ||
+ | ADMUX = (ADMUX & 0xF0) | (channel & 0x0F); // Select ADC channel | ||
+ | ADCSRA |= (1 << ADSC); // zacne jednotkovu konverziu | ||
+ | while (ADCSRA & (1 << ADSC)); // caka na dokoncenie konverzie | ||
+ | return ADC; // vrati ADC hodnotu | ||
+ | } | ||
+ | |||
+ | void LED_Init() { | ||
+ | DDRD |= (1 << LED_LEFT) | (1 << LED_RIGHT) | (1 << LED_DOWN) | (1 << LED_UP); | ||
+ | PORTD &= ~((1 << LED_LEFT) | (1 << LED_RIGHT) | (1 << LED_DOWN) | (1 << LED_UP)); | ||
+ | } | ||
+ | |||
+ | void Button_Init() { | ||
+ | DDRD &= ~(1 << BUTTON_PIN); // tlacitko na joysticku input bude | ||
+ | PORTD |= (1 << BUTTON_PIN); // pull-up resistor | ||
+ | } | ||
+ | |||
+ | bool isButtonPressed() { | ||
+ | return !(PIND & (1 << BUTTON_PIN)); // Return true if button is pressed | ||
+ | } | ||
+ | |||
+ | void displayLED(int ledIndex) { | ||
+ | PORTD &= ~((1 << LED_LEFT) | (1 << LED_RIGHT) | (1 << LED_DOWN) | (1 << LED_UP)); | ||
+ | |||
+ | switch (ledIndex) { | ||
+ | case 1: | ||
+ | PORTD |= (1 << LED_LEFT); | ||
+ | break; | ||
+ | case 2: | ||
+ | PORTD |= (1 << LED_RIGHT); | ||
+ | break; | ||
+ | case 3: | ||
+ | PORTD |= (1 << LED_DOWN); | ||
+ | break; | ||
+ | case 4: | ||
+ | PORTD |= (1 << LED_UP); | ||
+ | break; | ||
+ | default: | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | void generateRandomSequence(int sequence[], int length) { | ||
+ | for (int i = 0; i < length; i++) { | ||
+ | sequence[i] = (rand() % 4) + 1; // Random cislo medzi 1 az 4 | ||
+ | } | ||
+ | } | ||
+ | |||
+ | void displayLEDSequence(int sequence[], int length) { | ||
+ | for (int i = 0; i < length; i++) { | ||
+ | displayLED(sequence[i]); | ||
+ | _delay_ms(5000); // kazdu led vysvieti na dany cas | ||
+ | displayLED(0); // vypne vsetky ledky | ||
+ | _delay_ms(2000); // medzera pred dalsou ledkou vysvietenou | ||
+ | } | ||
+ | } | ||
+ | |||
+ | void getUserInputSequence(int userSequence[], int length) { | ||
+ | for (int i = 0; i < length; i++) { | ||
+ | bool inputReceived = false; | ||
− | + | // Wait for a valid input from the joystick | |
− | + | while (!inputReceived) { | |
− | + | if (isButtonPressed()) return; // zresetuje sekvenciu ak sa zatlaci joystick | |
− | |||
− | + | uint16_t xAxisValue = ADC_Read(0); | |
+ | uint16_t yAxisValue = ADC_Read(1); | ||
+ | |||
+ | if (xAxisValue < THRESHOLD_X_MIN) { | ||
+ | userSequence[i] = 1; // Left | ||
+ | inputReceived = true; | ||
+ | } else if (xAxisValue > THRESHOLD_X_MAX) { | ||
+ | userSequence[i] = 2; // Right | ||
+ | inputReceived = true; | ||
+ | } else if (yAxisValue < THRESHOLD_Y_MIN) { | ||
+ | userSequence[i] = 3; // Down | ||
+ | inputReceived = true; | ||
+ | } else if (yAxisValue > THRESHOLD_Y_MAX) { | ||
+ | userSequence[i] = 4; // Up | ||
+ | inputReceived = true; | ||
+ | } | ||
+ | |||
+ | // rozsvieti tu LEDku ktoru ma podla inputu | ||
+ | if (inputReceived) { | ||
+ | displayLED(userSequence[i]); | ||
+ | _delay_ms(2000); // Small delay to show the LED | ||
+ | displayLED(0); // Turn off the LED | ||
+ | } | ||
+ | } | ||
+ | } | ||
} | } | ||
+ | |||
+ | bool checkUserInput(int sequence[], int userSequence[], int length) { | ||
+ | for (int i = 0; i < length; i++) { | ||
+ | if (sequence[i] != userSequence[i]) { | ||
+ | return false; // nespravny input | ||
+ | } | ||
+ | } | ||
+ | return true; // sekvencie sa zhoduju | ||
+ | } | ||
+ | |||
+ | void indicateSuccess() { | ||
+ | // ak sedi sekvencia rozsvieti ledky | ||
+ | PORTD |= ((1 << LED_LEFT) | (1 << LED_RIGHT) | (1 << LED_DOWN) | (1 << LED_UP)); | ||
+ | _delay_ms(1000); | ||
+ | PORTD &= ~((1 << LED_LEFT) | (1 << LED_RIGHT) | (1 << LED_DOWN) | (1 << LED_UP)); | ||
+ | } | ||
+ | |||
+ | void indicateFailure() { | ||
+ | // ak nesedi sekvencia rozsvieti inak rozsvieti ledky | ||
+ | for (int i = 0; i < 3; i++) { | ||
+ | PORTD |= ((1 << LED_LEFT) | (1 << LED_DOWN)); | ||
+ | _delay_ms(200); | ||
+ | PORTD &= ~((1 << LED_LEFT) | (1 << LED_DOWN)); | ||
+ | _delay_ms(200); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | int main(void) { | ||
+ | ADC_Init(); | ||
+ | LED_Init(); | ||
+ | Button_Init(); | ||
+ | |||
+ | srand(42); // Initialize random number generator | ||
+ | |||
+ | int sequenceLength = 4; | ||
+ | int sequence[sequenceLength]; | ||
+ | int userSequence[sequenceLength]; | ||
+ | |||
+ | while (1) { | ||
+ | generateRandomSequence(sequence, sequenceLength); | ||
+ | displayLEDSequence(sequence, sequenceLength); | ||
+ | |||
+ | getUserInputSequence(userSequence, sequenceLength); | ||
+ | |||
+ | if (isButtonPressed()) { | ||
+ | // zresetuje sekvenciu ak je stlaceny joystick | ||
+ | continue; | ||
+ | } | ||
+ | |||
+ | bool sequenceMatched = checkUserInput(sequence, userSequence, sequenceLength); | ||
+ | |||
+ | if (sequenceMatched) { | ||
+ | indicateSuccess(); | ||
+ | } else { | ||
+ | indicateFailure(); | ||
+ | } | ||
+ | |||
+ | // caka na resetu tlacitko pred zacatim novej sekvencie | ||
+ | while (!isButtonPressed()) { | ||
+ | _delay_ms(100); | ||
+ | } | ||
+ | |||
+ | // Small delay to debounce the button press | ||
+ | _delay_ms(200); | ||
+ | } | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | |||
</source></tab> | </source></tab> | ||
Riadok 57: | Riadok 239: | ||
</tabs> | </tabs> | ||
− | |||
− | Zdrojový kód: [[Médiá: | + | |
+ | Zdrojový kód: [[Médiá:OndrejTarcal_Simons_game.rar|OndrejTarcal_Simons_game]] | ||
=== Overenie === | === Overenie === | ||
+ | Na používanie nášho programu sa využíva joystick, postup používania tejto minihry je popísany v sekcii popis riešenia | ||
− | |||
− | |||
− | [[Súbor: | + | [[Súbor:aplikácia_simon.png|400px|thumb|center|Aplikácia.]] |
'''Video:''' | '''Video:''' | ||
− | <center><youtube> | + | <center><youtube>uQps6FER21o</youtube></center> |
Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte. | Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte. | ||
[[Category:AVR]] [[Category:MIPS]] | [[Category:AVR]] [[Category:MIPS]] |
Aktuálna revízia z 17:30, 7. jún 2024
Záverečný projekt predmetu MIPS / LS2024 - Ondrej Tarcal
Zadanie
Cieľom zadania bolo naprogramovať minihru Simon's game. V skratke minihra by mala fungovať tak, že doska generuje náhodnú sekvenciu a my ju musíme následne zopakovať.
Literatúra:
Analýza a opis riešenia
Tento program som vytvoril na ovládanie štyroch LEDiek pomocou joysticku. Najprv sa navrhlo samotné ovládanie LEDiek joystickom. Následne som dokódoval aby sa najprv LEDky rozsvietili v náhodnej sekvencii. Nakoniec som dokódoval aby po doznení danej sekvencie uživateľ danú sekvenciu zopakoval a program vyhodnotí, či sa sekvencia rovná alebo nerovná roszvietením LEDiek. Joystick sa taktiež využil na zresetovanie a opakované spustenie novej sekvencie aby sa nemusel využívať reset button na doske Arduino.
Program
1. Definície a Inicializácie
Naprv sa preddefinovali makrá pre LEDky a ich polohy a mŕtve zóny joysticka. Inicializácia ADC prevodníka, čítanie z ADC, inicializacia LEDiek, tlačidla na joysticku a kontrola stlačenia tlačidla
2. Funkcie pre samotnú hru
Zobrazenie LEDiek, generovanie náhodných sekvencií a následne zobrazenie sekvencií cez LEDky. Získanie sekvencie od uživateľa cez joystick, kontrola sekvencie a indikácia úspechu alebo neúspechu
3. Main funkcie
V časti main sa program neustále opakuje, generuje náhodne sekvencie, zobrazuje ich pomocou LEDiek, získava od užívateľa sekvencie a porovnáva ich zhodnosť. Program čaká na stlačenie tlačidla na joysticku pre začatie novej sekvencie.
#include <avr/io.h>
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <stdbool.h>
#define F_CPU 16000000UL
#define LED_LEFT PD2
#define LED_RIGHT PD3
#define LED_DOWN PD4
#define LED_UP PD5
#define BUTTON_PIN PD6
#define THRESHOLD_X_MIN 300
#define THRESHOLD_X_MAX 700
#define THRESHOLD_Y_MIN 300
#define THRESHOLD_Y_MAX 700
void ADC_Init() {
ADMUX = (1 << REFS0); // Set ADC reference to AVCC
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // Zapne ADC a nastavi predelicku na 128
}
uint16_t ADC_Read(uint8_t channel) {
ADMUX = (ADMUX & 0xF0) | (channel & 0x0F); // Select ADC channel
ADCSRA |= (1 << ADSC); // zacne jednotkovu konverziu
while (ADCSRA & (1 << ADSC)); // caka na dokoncenie konverzie
return ADC; // vrati ADC hodnotu
}
void LED_Init() {
DDRD |= (1 << LED_LEFT) | (1 << LED_RIGHT) | (1 << LED_DOWN) | (1 << LED_UP);
PORTD &= ~((1 << LED_LEFT) | (1 << LED_RIGHT) | (1 << LED_DOWN) | (1 << LED_UP));
}
void Button_Init() {
DDRD &= ~(1 << BUTTON_PIN); // tlacitko na joysticku input bude
PORTD |= (1 << BUTTON_PIN); // pull-up resistor
}
bool isButtonPressed() {
return !(PIND & (1 << BUTTON_PIN)); // Return true if button is pressed
}
void displayLED(int ledIndex) {
PORTD &= ~((1 << LED_LEFT) | (1 << LED_RIGHT) | (1 << LED_DOWN) | (1 << LED_UP));
switch (ledIndex) {
case 1:
PORTD |= (1 << LED_LEFT);
break;
case 2:
PORTD |= (1 << LED_RIGHT);
break;
case 3:
PORTD |= (1 << LED_DOWN);
break;
case 4:
PORTD |= (1 << LED_UP);
break;
default:
break;
}
}
void generateRandomSequence(int sequence[], int length) {
for (int i = 0; i < length; i++) {
sequence[i] = (rand() % 4) + 1; // Random cislo medzi 1 az 4
}
}
void displayLEDSequence(int sequence[], int length) {
for (int i = 0; i < length; i++) {
displayLED(sequence[i]);
_delay_ms(5000); // kazdu led vysvieti na dany cas
displayLED(0); // vypne vsetky ledky
_delay_ms(2000); // medzera pred dalsou ledkou vysvietenou
}
}
void getUserInputSequence(int userSequence[], int length) {
for (int i = 0; i < length; i++) {
bool inputReceived = false;
// Wait for a valid input from the joystick
while (!inputReceived) {
if (isButtonPressed()) return; // zresetuje sekvenciu ak sa zatlaci joystick
uint16_t xAxisValue = ADC_Read(0);
uint16_t yAxisValue = ADC_Read(1);
if (xAxisValue < THRESHOLD_X_MIN) {
userSequence[i] = 1; // Left
inputReceived = true;
} else if (xAxisValue > THRESHOLD_X_MAX) {
userSequence[i] = 2; // Right
inputReceived = true;
} else if (yAxisValue < THRESHOLD_Y_MIN) {
userSequence[i] = 3; // Down
inputReceived = true;
} else if (yAxisValue > THRESHOLD_Y_MAX) {
userSequence[i] = 4; // Up
inputReceived = true;
}
// rozsvieti tu LEDku ktoru ma podla inputu
if (inputReceived) {
displayLED(userSequence[i]);
_delay_ms(2000); // Small delay to show the LED
displayLED(0); // Turn off the LED
}
}
}
}
bool checkUserInput(int sequence[], int userSequence[], int length) {
for (int i = 0; i < length; i++) {
if (sequence[i] != userSequence[i]) {
return false; // nespravny input
}
}
return true; // sekvencie sa zhoduju
}
void indicateSuccess() {
// ak sedi sekvencia rozsvieti ledky
PORTD |= ((1 << LED_LEFT) | (1 << LED_RIGHT) | (1 << LED_DOWN) | (1 << LED_UP));
_delay_ms(1000);
PORTD &= ~((1 << LED_LEFT) | (1 << LED_RIGHT) | (1 << LED_DOWN) | (1 << LED_UP));
}
void indicateFailure() {
// ak nesedi sekvencia rozsvieti inak rozsvieti ledky
for (int i = 0; i < 3; i++) {
PORTD |= ((1 << LED_LEFT) | (1 << LED_DOWN));
_delay_ms(200);
PORTD &= ~((1 << LED_LEFT) | (1 << LED_DOWN));
_delay_ms(200);
}
}
int main(void) {
ADC_Init();
LED_Init();
Button_Init();
srand(42); // Initialize random number generator
int sequenceLength = 4;
int sequence[sequenceLength];
int userSequence[sequenceLength];
while (1) {
generateRandomSequence(sequence, sequenceLength);
displayLEDSequence(sequence, sequenceLength);
getUserInputSequence(userSequence, sequenceLength);
if (isButtonPressed()) {
// zresetuje sekvenciu ak je stlaceny joystick
continue;
}
bool sequenceMatched = checkUserInput(sequence, userSequence, sequenceLength);
if (sequenceMatched) {
indicateSuccess();
} else {
indicateFailure();
}
// caka na resetu tlacitko pred zacatim novej sekvencie
while (!isButtonPressed()) {
_delay_ms(100);
}
// Small delay to debounce the button press
_delay_ms(200);
}
return 0;
}
#include <avr/io.h>
void adc_init(void); // A/D converter initialization
unsigned int adc_read(char a_pin);
Zdrojový kód: OndrejTarcal_Simons_game
Overenie
Na používanie nášho programu sa využíva joystick, postup používania tejto minihry je popísany v sekcii popis riešenia
Video:
Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte.