Operácie

Prehrávač melódie s ovládaním: Rozdiel medzi revíziami

Zo stránky SensorWiki

StudentMIPS (diskusia | príspevky)
Bez shrnutí editace
StudentMIPS (diskusia | príspevky)
Riadok 13: Riadok 13:
* [http://ap.urpi.fei.stuba.sk/sensorwiki/index.php/Acrob_technical_description Dokumentácia k doske Acrob]
* [http://ap.urpi.fei.stuba.sk/sensorwiki/index.php/Acrob_technical_description Dokumentácia k doske Acrob]
* [http://www.humanbenchmark.com/tests/reactiontime/index.php Vyskúšajte si zmerať reakciu on-line]
* [http://www.humanbenchmark.com/tests/reactiontime/index.php Vyskúšajte si zmerať reakciu on-line]
* [https://www.alldatasheet.com/datasheet-pdf/view/1506967/MURATA1/PKM22EPPH2001-B0.html Datasheet buzzer PKM22EPPH]





Verzia z 12:49, 10. máj 2026

Záverečný projekt predmetu MIPS / LS2026 - Miroslav Klein


Zadanie

Cieľom tohto zadania je realizácia mikropočítačového prehrávača melódií. Toto zadanie vyžaduje kontrolované prehrávanie melódií z poľa, čo znamená že k zariadeniu sú pripojené aj tri tlačidlá Play/Stop/Next pre obsluhu. Zadanie slúži na demonštráciu práce s časovačmi, generovanie signálu a spracovanie vstupov od používateľa.

[[Súbor:]]

Vývojová doska ACROB.

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.

Ako základ pre projekt bola použitá vývojová doska Arduino Uno s mikrokontrolérom ATmega328P. Táto doska poskytuje, napájanie 5V, USB rozhranie pre programovanie a konektory pre pripojenie externých komponentov.

Pre správnu funkciu je nutné použiť pasívny bzučiak (reproduktor bez vlastného oscilátora). Aktívny bzučiak obsahuje vlastný generátor frekvencie a neumožňuje riadenie výšky tónu z mikrokontroléra. Pasívny bzučiak vyžaduje sériový rezistor na obmedzenie prúdu cez výstupný pin mikrokontroléra. Bzučiak je pripojený na výstupný pin PD6 (OC0A) mikrokontroléra.

Pre ovládanie prehrávača slúžia tri spínače pripojené na piny PD2, PD3 a PD4 portu D mikrokontroléra. Použité sú štandardné tlačidlá, ktoré sú bežne dostupné v stavebniciach pre Arduino. Tieto tlačidlá sú zapojené tak, že jedna strana je pripojená na príslušný pin portu D (PD2, PD3, PD4) a druhá strana je pripojená na zem (GND). V programe sú na týchto pinoch aktivované interné pull-up rezistory mikrokontroléra. To znamená, že v kľudovom stave je na pine logická 1 a stlačením tlačidla sa pin prepojí na GND a zmení sa na logickú 0. Tieto interné pull-up rezistory zjednodušujú schému a znižujú počet komponentov.

Problém zákmitov kontaktov (bouncing): Mechanické tlačidlá pri stlačení a uvoľnení vytvárajú krátke zákmity kontaktov. Bez potlačenia by jedno stlačenie tlačidla bolo programom zaregistrované ako viacnásobné. V kóde je tento jav riešený softvérovým oneskorením (debouncing)

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.

Schéma zapojenia.


Algoritmus a program

Algoritmus programu využíva toto a toto, základné funkcie sú takéto a voláma ich tuto...

Projekt je realizovaný na vývojovej doske Arduino Uno s mikrokontrolérom ATmega328P. Mikrokontrolér pracuje s frekvenciou 16 MHz, čo je definované makrom F_CPU 16000000UL na začiatku programu. Táto hodnota je kľúčová pre všetky časové výpočty v projekte, najmä pre generovanie zvukových frekvencií a oneskorenia.

Pre generovanie hudobných tónov sa využíva 8-bitový časovač Timer0 v režime CTC. Tento režim je nastavený bitom WGM01 v registri TCCR0A (WGM01=1, WGM00=0). V CTC režime sa časovač TCNT0 zvyšuje každý takt hodinového signálu po aplikácii preddeličky. Keď hodnota časovača dosiahne hodnotu uloženú v registri OCR0A, dôjde k zhode, časovač sa automaticky vynuluje a zároveň sa môže vykonať akcia na výstupnom pine PD6.

Preddelička: V registri TCCR0B je nastavený bit CS02, čo znamená preddeličku 256. Timer0 sa teda zvyšuje každých 256 taktov CPU.

Výstupný pin a signál: Výstupný pin je PD6. Bit COM0A0 v registri TCCR0A zapína režim toggle – pri každej zhode sa logická úroveň pinu PD6 prepne (z 0 na 1 alebo z 1 na 0). Tým sa generuje obdĺžnikový signál s presnou frekvenciou určenou hodnotou OCR0A.

Štruktúra melódií Každá melódia je definovaná pomocou troch premenných – dvoch polí a jednej konštanty: Pole sX_t[] obsahuje hodnoty OCR0A, ktoré určujú výšku jednotlivých tónov Pole sX_c[] obsahuje trvanie jednotlivých tónov v milisekundách Premenná sX_len udáva celkový počet tónov v melódii Táto štruktúra umožňuje jednoduché pridávanie nových melódií bez nutnosti zásahu do hlavného algoritmu prehrávania. V projekte sú definované tri melódie: s0, s1 a s2.

Pre ovládanie prehrávača slúžia tri tlačidlá pripojené na port D mikrokontroléra. V programe sú zapnuté interné pull-up rezistory príkazom PORTD |= (1 << PD2) | (1 << PD3) | (1 << PD4). Bez stlačenia tlačidla sú piny vďaka pull-upu v stave HIGH (5V). Stlačením tlačidla sa pin pripojí k zemi (GND) a program detekuje stav LOW.

Funkcia hraj_ton(int hodnota, int trvanie) realizuje tri kľúčové úlohy. 1. Nastavenie frekvencie a zapnutie výstupu: Ak je parameter hodnota nenulový a prehrávanie je povolené, nastaví sa register OCR0A na požadovanú hodnotu a zapne sa toggle mód na pine PD6. Ak je hodnota nulová alebo prehrávanie je zastavené, výstup sa vypne. 2. Čakanie s kontrolou tlačidiel: Namiesto jedného dlhého oneskorenia sa používa cyklus s krokmi 10 ms. Celkové trvanie tónu sa rozdelí na intervaly po 10 ms, pričom v každom kroku sa skontroluje stav tlačidiel. 3. Debouncing a detekcia tlačidiel: V cykle sa kontroluje stav tlačidiel STOP, PLAY a NEXT. Pri detekcii stlačenia sa vykoná príslušná akcia Výpis kódu je nižšie...


#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>

#define C5 59
#define D5 52
#define E5 46
#define F5 44
#define G5 39
#define A5 35
#define H5 31
#define C6 29
#define D6 26
#define E6 23
#define G6 19

// Melódie
int s0_t[] = {G5, G5, A5, G5, C6, H5};
int s0_c[] = {300, 300, 300, 300, 300, 500};
int s0_len = 6;

int s1_t[] = {C6, D6, E6, G6, E6, D6, C6};
int s1_c[] = {200, 200, 200, 400, 200, 200, 400};
int s1_len = 7;

int s2_t[] = {E5, E5, E5, E5, E5, E5, E5, G5, C5, D5, E5};
int s2_c[] = {200, 200, 400, 200, 200, 400, 200, 200, 200, 200, 600};
int s2_len = 11;

// Premenné
int aktualna_pesnicka = 0; 
int aktualny_ton = 0;      // Index tónu, v ktorom sme prestali
int hra_sa = 1;             // Po zapnutí Arduina rovno hrá

void hraj_ton(int hodnota, int trvanie) {
    if (hodnota == 0 || hra_sa == 0) {
        TCCR0A &= ~(1 << COM0A0); 
    } else {
        OCR0A = hodnota;  
        TCCR0A |= (1 << COM0A0);   
    }

    // Čakanie s kontrolou tlačidiel
    for (int i = 0; i < trvanie / 10; i++) {
        _delay_ms(10);
        
        // Kontrola tlačidla STOP
        if (!(PIND & (1 << PD2))) { hra_sa = 0; break; }
        // Kontrola tlačidla PLAY
        if (!(PIND & (1 << PD3))) { hra_sa = 1; break; }
        // Kontrola tlačidla NEXT
        if (!(PIND & (1 << PD4))) {
            _delay_ms(200); // debounce
            aktualna_pesnicka = (aktualna_pesnicka + 1) % 3;
            aktualny_ton = 0; // Pri NEXT hráme novú melódiu od začiatku
            break;
        }
    }
    TCCR0A &= ~(1 << COM0A0); 
    _delay_ms(20);
}

int main(void) {
    DDRD |= (1 << PD6); 
    DDRD &= ~((1 << PD2) | (1 << PD3) | (1 << PD4)); 
    PORTD |= (1 << PD2) | (1 << PD3) | (1 << PD4);

    TCCR0A = (1 << WGM01); 
    TCCR0B = (1 << CS02); 

    while (1) {
        // Kontrola Play tlačidla, ak sme v stave STOP
        if (!(PIND & (1 << PD3))) {
            _delay_ms(50);
            hra_sa = 1;
        }

        if (hra_sa == 1) {
            // Výber pesničky a prehratie jedného tónu na pozícii 'aktualny_ton'
            if (aktualna_pesnicka == 0) {
                hraj_ton(s0_t[aktualny_ton], s0_c[aktualny_ton]);
                aktualny_ton = (aktualny_ton + 1) % s0_len; // Posun na ďalší tón
            } 
            else if (aktualna_pesnicka == 1) {
                hraj_ton(s1_t[aktualny_ton], s1_c[aktualny_ton]);
                aktualny_ton = (aktualny_ton + 1) % s1_len;
            }
            else if (aktualna_pesnicka == 2) {
                hraj_ton(s2_t[aktualny_ton], s2_c[aktualny_ton]);
                aktualny_ton = (aktualny_ton + 1) % s2_len;
            }
        } else {
            // Ak nehrá, odpojíme bzučiak a len čakáme na Play/Next
            TCCR0A &= ~(1 << COM0A0);
            
            // Aj v stop stave vieme prepnúť na Next melódiu
            if (!(PIND & (1 << PD4))) {
                _delay_ms(300);
                aktualna_pesnicka = (aktualna_pesnicka + 1) % 3;
                aktualny_ton = 0;
            }
        }
    }
}
#include <avr/io.h>

void adc_init(void);                                   // A/D converter initialization

unsigned int adc_read(char a_pin);

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

Aplikácia.

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.