Operácie

Simon's Game: Rozdiel medzi revíziami

Zo stránky SensorWiki

StudentMIPS (diskusia | príspevky)
Bez shrnutí editace
StudentMIPS (diskusia | príspevky)
Bez shrnutí editace
 
(14 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 hra by mala fungovať tak, že doska generuje náhodnú sekvenciu a my ju musíme následne zopakovať.
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|Doska Arduino UNO R3.]]
[[Obrázok:Arduinopinout.png|400px|thumb|center|Doska Arduino UNO R3.]]
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:ledRGB.jpg|400px|thumb|center|RGB LED.]]
[[Súbor:Schemasimon.png|400px|thumb|center|Schéma zapojenia joysticku a LEDiek.]]


Nezabudnite doplniť schému zapojenia!


[[Súbor:Diagramfinal.png|400px|thumb|center|Schéma zapojenia joysticku a LEDiek.]]


[[Súbor:Diagramfinalfinal.png|400px|thumb|center|Schéma zapojenia joysticku a LEDiek.]]


=== Algoritmus a program ===


Algoritmus programu je....
=== 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 main(void)
#include <avr/io.h>
{
#include <util/delay.h>
  unsigned int measuredValue;
#include <stdlib.h>
#include <stdbool.h>


  while (1)
#define F_CPU 16000000UL
  {
    /*  relax  */ 
  }


   return(0);
#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>


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:Fotkairlzapojenia.png|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.