Operácie

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 - '''Meno Priezvisko'''
+
Záverečný projekt predmetu MIPS / LS2024 - '''Ondrej Tarcal'''
  
  
 
== Zadanie ==
 
== Zadanie ==
  
Sem príde text zadania, ak bolo len voľne formulované, rozpíšte ho podrobnejšie
+
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:ard.jpg|400px|thumb|center|Vývojová doska ACROB.]]
+
[[Obrázok:Arduinopinout.png|400px|thumb|center|Doska Arduino UNO R3.]]
  
 
'''Literatúra:'''  
 
'''Literatúra:'''  
* [http://ap.urpi.fei.stuba.sk/sensorwiki/index.php/Acrob_technical_description Dokumentácia k doske Acrob]
+
* [https://docs.arduino.cc/resources/datasheets/A000066-datasheet.pdf Dokumentácia k doske Arduino Uno R3]
* [http://www.humanbenchmark.com/tests/reactiontime/index.php Vyskúšajte si zmerať reakciu on-line]
+
 
  
  
Riadok 17: Riadok 17:
 
== Analýza  a opis riešenia ==
 
== Analýza  a opis riešenia ==
  
Opíšte sem čo a ako ste spravili, ak treba, doplňte obrázkami...
+
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:ledRGB.jpg|400px|thumb|center|RGB LED.]]
 
  
Nezabudnite doplniť schému zapojenia!
+
[[Súbor:Diagramfinalfinal.png|400px|thumb|center|Schéma zapojenia joysticku a LEDiek.]]
  
[[Súbor:schd.png|400px|thumb|center|Schéma zapojenia LCD displeja.]]
 
  
 +
=== Program ===
 +
1. Definície a Inicializácie
  
=== Algoritmus a program ===
+
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
  
Algoritmus programu je....
+
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 main(void)
+
#include <avr/io.h>
{
+
#include <util/delay.h>
  unsigned int measuredValue;
+
#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;
  
  while (1)
+
        // Wait for a valid input from the joystick
  {
+
        while (!inputReceived) {
    /*  relax  */
+
            if (isButtonPressed()) return; // zresetuje sekvenciu ak sa zatlaci joystick
  }
 
  
  return(0);
+
            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>
  
Pridajte sem aj zbalený kompletný projekt, napríklad takto (použite jednoznačné pomenovanie, nemôžeme mať na serveri 10x ''zdrojaky.zip'':
 
  
Zdrojový kód: [[Médiá:projektMenoPriezvisko.zip|zdrojaky.zip]]
+
 
 +
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
  
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 záverečnej obrazovky pred resetom. Vypísaný je tu priemerný čas a najlepší čas.
 
  
[[Súbor:fotka.jpg|400px|thumb|center|Aplikácia.]]
+
[[Súbor:aplikácia_simon.png|400px|thumb|center|Aplikácia.]]
  
 
'''Video:'''
 
'''Video:'''
<center><youtube>_l02MBu41n0</youtube></center>
+
<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ť.

Doska Arduino UNO R3.

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.

Schéma zapojenia joysticku a LEDiek.


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.


#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


Aplikácia.

Video:

Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte.