. : New eShop! - Mobilní verze - Pandatron.cz - Pandatron.sk - Diskuzní fórum - Zakázkový vývoj : .
 
Generování zvuku pomocí mikrokontroléru
21. července 2010 - 8:15 | Matej Gálus | Generování zvuku pomocí mikrokontroléru | Komentářů: 0  

Generování zvuku pomocí mikrokontroléru

Přiblížení možnosti generování zvuku pomocí mikrokontroléru, včetně kompletní hardwarové a softwarové realizace.

Mikrokontroléry nalézají uplatnění ve velkém rozsahu aplikací. Každý mikrokontrolér však musí nějak komunikovat s okolím. Pokud je mikrokontrolér použit jako součást komplexnějšího číslicového systému, tak se pro komunikaci používají různé druhy číslicových zběrnic a protokolů - Pro připojení k jinému mikrokontroléru resp. k číslicové periferii se používají sběrnice. IIC, SPI apod. Pro připojení k PC dominují zběrnice USART a nověji také USB. Naproti tomu při komunikaci s reálným světem - člověkem musí být signály z číslicového mikrokontroléru převedeny do analogové formy, vnímatelné člověkem. K tomu se velmi často používají LED resp. LCD displeje, LED diody - tedy prvky převádějící digitální signál z mikrokontroléru na signál optický. Tato metoda je velmi rozšířená i u jednoduchých aplikací s mikrokontroléry. Někdy je ovšem potřeba signál z mikrokontroléru převést na signál akustický. Příkladem mohou být různé automatické telefonní služby, např. odkazová služba provozována telefonním operátorem. Zde je jedinou možností sdělovat informace pomocí akustického - řečového signálu.

Popis možností generování zvuku mikrokontrolérem
Pro generování zvuku mikrokontrolérem existují v podstatě tři základní možnosti. První je použít specializovaný Č/A převodník. Tento může být připojen k mikrokontroléru např. pomocí IIC anebo SPI sběrnice. Digitální data jsou mikrokontrolérem přenášena do převodníku, který je převádí na akustický signál. Tato varianta je vhodná v případě, že požadujeme akustický výstup o vyšší kvalitě, např. pro jakostní poslech hudby. Používá se např. u zvukových karet PC.

Další možností je využít pro generování zvuku přímo několik výstupních pinů mikrokontroléru. Po doplnění rezistorovou sítí R-2R získáme jednoduchý paralelní Č/A převodník. Na příslušné výstupní piny mikrokontroléru program posílá přímo jednotlivé bity postupně každého přehrávaného vzorku. Odporová síť je zapojena jako binární dělič napětí. Většinou se používá síť složena z 8 párů rezistorů, poskytující rozlišení 8 bitů, což pro jednoduchou akustickou signalizaci většinou postačuje. Metoda je poměrně rozšířená, nicméně vyžaduje síť 16-ti rezistorů o potřebné přesnosti. Příklad takového zapojení je na následujícím obrázku.


Obr. 1: Použití rezistorové sítě R-2R

Nejjednodušší možností je využít možnost pulsně-šířkové modulace. Moderní mikrokontroléry často disponují několika PWM výstupy, jejichž střídu lze řídit softwarově pomocí příslušných registrů. Střída je pak zachována až do následující změny registru. Jedná se v podstatě o speciální případ využití čítače/časovače, kdy tento běží na hodinovém kmitočtu vyšším, než je maximální frekvence v požadovaném audiosignálu. Střída každého pulsu je úměrná okamžité amplitudě vzorku. V nejjednodušším případě je možné příslušný výstupní pin čítače/časovače připojit (přes rezistor) na malý reproduktor. Díky jeho indukčnosti a setrvačnosti membrány je převod na akustický signál zajištěn přímo reprodutorem bez nutnosti další filtrace. Tato metoda, oproti výše zmíněným, poskytuje vzhledem k principu činnosti akustický signál o nejmenší jakosti. Nicméně i tato jakost, při použití 8-bitového čítače/časovače je pro většinu aplikací dostačující.

Hardwarová část
Vzhledem k výše popsanému, byla pro tento projekt vybrána varianta s využitím pulsně-šířkové modulace. Jako zdroj dat pro akustický signál byla zvolena možnost použití SD paměťové karty a čtení souborů v RAW formátu. Tento je prakticky nejjednodušším audioformátem. Oproti např. WAV formátu neobsahuje hlavičku specifikující atributy datového toku - vzorkovací frekvenci, bitovou hloubku, počet kanálů apod. Proto je při použití RAW formátu pro jeho přehrání nutné tyto parametry znát. Pro jednoduché aplikace, kdy jsou použity vzorky (RAW soubory) o stejných parametrech, to nepředstavuje problém. Pro tento projekt byly zvoleny monofonní soubory s hloubkou 8 bitů a vzorkovací frekvenci 8 kHz (umožňující maximální frekvenci audiosignálu 4 kHz, což je pro telefonní služby s horním mezním kmitočtem asi 3400 Hz postačující).

Pro čtení z SD karty byl vzhledem k rozsáhlosti programu použit hotový projekt [1]. Jedná se o ukázku přístupu na SD/SDHC kartu se souborovým systémem FAT32 pomocí mikrokontroléru ATMega32 anebo ATMega16. Karta je k mikrokontroléru připojena sběrnicí SPI. Uživatelská komunikace je přes PC prostřednictvím rozhraní USART (RS232) a aplikací Hyperterminál, která je standardně součástí MS Windows. Mikrokontrolér poskytuje funkce jako vytvoření a mazání souboru, čtení souboru (výpis jeho obsahu do okna terminálu), mazání souboru. V případě nenaformátované SD karty (bez FAT32) je možnost číst a zapisovat data na kartě jako surové bloky. Schéma zapojení dle [1] je na následujícím obrázku.


Obr. 2: Schéma z projektu SD/SDHC Card Interfacing with ATmega8 /32 (FAT32 implementation)

Projekt [1] však neuvažuje s možností generování zvukového signálu pomocí souboru na SD kartě, omezuje se pouze na přenos přes rozhraní USART. Pro náš účel bylo tedy nutné v zdrojovém kódu a v hardwarovém zapojení provést několik změn a doplnění. Hardwarově bylo zapojení především doplněno o zesilující stupeň s tranzistorem T1 a rekonstrukčním filtrem typu dolní propust, složeným z R10 a C10. Mezní frekvence filtru je (při zanedbání vlivu impedance reproduktoru) zhruba 7,2 kHz, což je dostatečně nízko pod frekvenci PWM signálu, která je zhruba 33 kHz. Zároveň je mezní frekvence dostatečně vysoko, aby neovlivňovala přenos v akustickém pásmu do 4 kHz. Je nutno poznamenat, že tento jednoduchý filtr je pouze 1. řádu a tedy filtrace vzorkovacího kmitočtu nebude zdaleka dokonalá. Nicméně, na jakosti zvuku se to prakticky neprojeví. Filtr je zařazen prakticky pouze pro zjednodušení sledování výstupu osciloskopem.
Zapojení bylo doplněno rovněž o další LED diodu pro možnost nezávislé indikace aktivity rozhraní USART a aktivity SD karty. Další úpravy (tlačítka, analogové vstupy, obvod RTC) byly doplněny s výhledem na možné budoucí experimentální využití desky.

Schéma zapojení:


Obr. 3: Schéma zapojení

Osazovací plány a fotografie osazené desky:


Obr. 4: Rozmístění součástek - top
 
Obr. 5: Rozmístění součástek - bottom

Obr. 6: Fotografie osazené desky - top
 
Obr. 7: Fotografie osazené desky - bottom

Softwarová část
Po připojení kabelem RS232 a zapnutí přípravku se tedy v okně hyperterminálu objeví menu s možností výběru akce. Aby bylo možné přes hyperterminál ovládat přehrávání souboru, bylo menu programu doplněno o další možnost: Stisknutím klávesy "p" je uživatel dotázán na jméno jednoho souboru, který má být přehrán. Volbou "c" program vejde do smyčky, kdy každá přijatá číslice vyvolá přehrání příslušného souboru .raw.


Obr. 8: Hlavní menu

Strukturu menu popisuje soubor SD_main.c.

Při zvolení možnosti "c" program vejde do cyklu, kdy každý přijatý znak doplní o příponu ".raw" a soubor s tímto názvem přehraje. Po přehrání pak čeká na další znak. Návrat do menu je možný klávesou ESC.

case 'c':
  TX_NEWLINE;
  TX_NEWLINE;
  transmitString_F(PSTR("Pro navrat do menu slouzi klavesa ESC."));
  TX_NEWLINE;
  transmitString_F(PSTR("Zadavej cislice: "));

  for(i=0; i<13; i++)
    fileName[i] = 0x00;	//smazani pripadneho predchoziho nazvu
  i=0;

  InitPWM();				//inicializace citacu/casovacu
  while(1) {
    data = receiveByte(); // cekej na prijeti znaku

    if(data == 0x1B)		// zmacknuto ESC?
      break;				// ukonceni while cyklu

    if(data <0x30 || data > 0x39) { // pokud byl zadan jiny znak nez cislo 0-9
      TX_NEWLINE;
      transmitString_F(PSTR("Byl zadan jiny znak nez je povoleno!")); //chybove hlaseni
      continue;  // pokud znak neni cislo tak skonci
    }

    transmitByte(data); // vypis zpatky do terminalu

                        // vytvoreni jmena souboru:
    fileName[0] = data; // cislo
    fileName[1] = 0x2e; // .
    fileName[2] = 0x72; // r
    fileName[3] = 0x61; // a
    fileName[4] = 0x77; // w

    readFile( PLAY, fileName);	//volani funkce pro prehrani souboru
  }

break; 	//navrat do menu (po zmacknuti ESC)

Kód pro volbu "p" je jednodušší, v podstatě jenom inicializuje PWM a volá funkci pro přehrání.

if(option == 'p') {
  InitPWM();                    //inicializace citacu/casovacu
  readFile( PLAY, fileName);    //volani funkce pro prehravani souboru
}

Funkce InitPWM() inicializuje příslušné čítače/časovače:

void InitPWM(void) {

//TIMER/COUNTER0 ridi primo PWM vystup
  TCCR0|=(1‹‹WGM00)|(1<<WGM01)|(1<<COM01)|(1<<CS00); // bez preddelicky, rezim Fast PWM, neinvertovany

//TIMER/COUNTER2 ridi vzorkovaci periodu (rychlost toku vzorku na PWM)
  TCCR2|=(1<<WGM21)|(1<<CS21);	// preddelicka fclkio/8, rezim CTC
  OCR2=125;						// vzorkovaci perioda pro 8 MHz krystal a 8 kHz fvz

}

Funkce readFile je v původním programu použita pro čtení sektorů z SD karty a posílání jednotlivých bitů na rozhraní USART. Pro přehrávání jsme funkci upravili - bity nejsou posílány na USART ale volá se funkce playByte:

if(flag == PLAY) {

  TX_NEWLINE;
  TX_NEWLINE;
  transmitString_F(PSTR("Prehravam..."));   //posli informaci na USART

  while(1) { // "nekonecna" smycka
    firstSector = getFirstSector (cluster); // volani funkce pro zjisteni prvniho sektoru v clusteru

    for(j=0; j<sectorPerCluster; j++) {  // pro kazdy sektor v clusteru
      SD_readSingleBlock(firstSector + j);  // volani funkce pro precteni jednoho bloku

      for(k=0; k<512; k++) {             // pro kazdy byte v bloku
        playByte(buffer[k]);                // volani funkce pro prehravani
        if ((byteCounter++) >= fileSize ) return 0;	// pokud jsme dosahli konec souboru, skoncit
      }
    }
    cluster = getSetNextCluster (cluster, GET, 0);	// zjisteni dalsiho clusteru
    if(cluster == 0) {transmitString_F(PSTR("Error in getting cluster")); return 0;}	//hlaseni pri chybe
  }
  return 0;
}

Samotná funkce playByte posílá jednotlivé bity na PWM výstup se správnou rychlostí - vždy při shodě čítače/časovače2 s hodnotou nastavenou v OCR2:

void playByte( unsigned char data ) {
  while (bit_is_clear(TIFR,OCF2)) {   // cekej na signal z citace/casovace2
    OCR0=data;                        // posli hodnotu vzorku na PWM vystup (do citace/casovace0)
    TIFR|=(0<<OCF2);            // vynuluj flag shody TCNT2, abychom poznali dalsi signal z citace/casovace2
  }
  return;
}

Závěr
Výšeuvedené softwarové řešení zajistí přehrávání vzorků souboru z SD karty s téměř správnou rychlostí. Je zde totiž jeden malý problém: Jakmile se při přehrávání dosáhle konec bloku a zásobník (buffer[k]) se vyprázdní, funkci SD_readSingleBlock trvá určitý čas, než načte další blok dat do bufferu. Čtení z SD karty totiž funguje tak, že se na kartu pošle adresa požadovaného bloku a karta pošle celý blok o 512 bytech. Ukázalo se, že tato operace trvá v našem případě přibližně 3 ms. To při vzorkovací frekvenci 8 kHz (vzorkovací perioda 125 us) způsobí, že přehrávání se pozastaví na 24-násobek vzorkovací periody. Každých 512 bytů se tedy pozastaví přehrávání "na 24 bytů". Subjektivně to způsobuje, že zvuk je přehráván se správnou výškou tónu, ale je v něm slyšitelné pravidelné "lupání" každých přibližně 60 ms. Přehrávání se tedy zpomalí na 0,955-násobek správné rychlosti. Tento jev dobře ilustruje následující oscilogram. Žlutý průběh je napětí na reproduktoru (PWM signál po nedokonalé filtraci) a zelený průběh je signál na kontrolním pinu resp. na LED, která se rozsvítí při práci s SD kartou:


Obr. 9: Napětí na reproduktoru a průběh signálu na kontrolním pinu

Z oscilogramu je vidět, že po dobu práce s SD kartou je PWM výstup neměnný (mírná setrvačnost je způsobena výstupním filtrem).
Teoreticky by tento problém bylo možné vyřešit použitím delšího zásobníku, resp. dvou zásobníků místo jednoho a přehrávání vzorků řešit pomocí přerušení čítače/časovače2. Nicméně, při zvyšování velikosti zásobníku jsme limitováni velikostí SRAM paměti mikrokontroléru, která u ATmega16 činí 1 kB. S nynějším bufferem (512 B) celý program využívá 593 B SRAM. Pro vyřešení tohoto problému by bylo nutné použít jiný typ mikrokontroléru, např. ATMega128, který disponuje 4 kB SRAM.

Seznam součástek je zde ke stažení.

Použitá literatura:
1. CC Dharmani: SD/SDHC Card Interfacing with ATmega8 /32 (FAT32 implementation)
2. Atmel: ATMega16 datasheet
3. FEDRA, Z. Mikropočítače pro přístrojové aplikace. Přednášky. FEKT VUT Brno 2010

Autoři:
Matej Gálus, xgalus02@stud.feec.vutbr.cz
Lenka Zelinová, xzelin13@stud.feec.vutbr.cz

Odkazy & Download:
Ústav radioelektroniky
Generování zvuku pomocí mikrokontroléru
Projekt ke stažení
Motiv desky s plošnými spoji







GooglePlus1 FaceBook Twitter del.icio.us DiGG Google StumbleUpon Google Buzz Email RSS PDF Tisk

Komentáře:
Název příspěvku: Vaše jméno: host
                 
  Zakázat formátování [Zakáže kódování a nahrazování smajlíky.]
Připojit soubory
reklama:
PU232S - Převodník USB/RS232
Převodník USB / RS232 s obvody FTDI a plným sériovým portem RS232 Full.
Skladem od 395 Kč

Informace uvedené v článcích jsou platné v době jejich vydání a samotné články jsou určeny pouze jako zdroj informací. Autor článku ani správce webu nenesou žádnou zodpovědnost za případné újmy na majetku a zdraví. Názvy společností a výrobků, loga a další multimediální materiál mohou být ochrannými známkami příslušných společností.
RSS kanály: | |
+420 723 846 377
info@pandatron.cz
Všechna práva vyhrazena | mobilní verze | © Copyright 2000 - 2016 ISSN 1803-6007