Operácie

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

Zo stránky SensorWiki

StudentMIPS (diskusia | príspevky)
StudentMIPS (diskusia | príspevky)
Riadok 62: Riadok 62:
<tabs>
<tabs>
<tab name="AVR C-code"><syntaxhighlight  lang="c++" style="background: LightYellow;">
<tab name="AVR C-code"><syntaxhighlight  lang="c++" style="background: LightYellow;">
#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/io.h>
#include <util/delay.h>


int main(void)
#define C5 59
{
#define D5 52
  unsigned int measuredValue;
#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


  while (1)
// Melódie
  {
int s0_t[] = {G5, G5, A5, G5, C6, H5};
    /*  relax  */ 
int s0_c[] = {300, 300, 300, 300, 300, 500};
  }
int s0_len = 6;


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



Verzia z 08:43, 8. 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.

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.

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.

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.