Simon's Game: Rozdiel medzi revíziami
Zo stránky SensorWiki
Bez shrnutí editace |
Bez shrnutí editace |
||
(16 medziľahlých úprav od rovnakého používateľa nie je zobrazených.) | |||
Riadok 4: | Riadok 4: | ||
== Zadanie == | == Zadanie == | ||
Cieľom zadania bolo naprogramovať Simon's game. V skratke | 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:Arduinopinout.png|400px|thumb|center| | [[Obrázok:Arduinopinout.png|400px|thumb|center|Doska Arduino UNO R3.]] | ||
'''Literatúra:''' | '''Literatúra:''' | ||
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: | [[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> | ||
#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.