Rad sa zvukom Do sada smo u rubrici SK Labs obradili mnoštvo senzora i drugih korisnih hardverskih uređaja koji se povezuju sa platformom Arduino. Došlo je vreme da se pozabavimo i načinima za generisanje i reprodukciju zvuka, što je uvek spadalo u zanimljive teme kada su računari i elektronika u pitanju. Priču ćemo započeti od piezo elemenata koji predstavljaju najjeftiniji medij za emitovanje zvuka. Svoj rad zasnivaju na piezoelektričnom efektu, koji podrazumeva pojavu elektriciteta na kristalu kvarca (i još nekih materijala) izloženom pritisku. Nama je u konkretnom slučaju zanimljiviji obrnuti efekt koji se postiže dovođenjem struje, što za posledicu ima deformaciju kristala. U takvim okolnostima dolazi do polarizacije i jedna strana dobija pozitivno a druga negativno naelektrisanje. Pločica pod promenama napona počinje da oscilira i stvara zvuk.
Postoje dve vrste zvučnika zasnovanih na ovom efektu. Kod prve se sloj piezoelektrične keramike lepi za metalnu površinu koja prenosi vibracije, dok se u drugom slučaju radi o polimer membrani. U novije vreme se za izradu piezo sloja najčešće koristi takozvana PZT keramika, odnosno legura olovo-cirkonat-titanata. Piezo zvučnici rade u širokom rangu napona od 3 do 240 volti, dok se potrošnja struje najčešće kreće od par pa do nekih 30 miliampera.
Kada je u pitanju Arduino, postoje dve glavne podgrupe ovih zvučnika: aktivni i pasivni. Glavna razlika među njima jeste integrisani rezonator (sastoji se od tranzistora, otpornika, induktora i piezo elementa sa tri kontakta), tako da je dovoljno dovesti napon da bi se proizveo zvuk. Treća nožica sa zvučnika prenosi impuls povratne sprege na bazu tranzistora, što omogućuje generisanje oscilatornog signala bez upotrebe kondenzatora. Inače, na ovom pinu signal se pojavljuje kao posledica delovanja sile koju proizvodi pločica zvučnika na koju je doveden elektricitet, zato se i radi o povratnoj sprezi. Pomenuti sklop na prisustvo struje reaguje zvukom (najčešće 2,3-3 kiloherca mada zna biti i više) koji je dovoljno jak (da ne kažemo iritirajući) da privuče pažnju u radijusu od desetak metara. Piezo zvučnici emituju zvuk koji se najčešće kreće u granicama od 80 do 120 decibela. Aktivni biperi (ili bazeri) značajno pojednostavljuju rad sa projektima koji imaju potrebu da zvučnim signalom obaveštavaju korisnika o stanju sistema. Mogu se nabaviti i u obliku modula koji na sebi imaju tri kontakta. Dva su namenjena priključenju napona, dok treći služi za dovođenje signala. Kada se radi o aktivnim piezo elementima koje koristimo u svojstvu alarma, skeč za signalizaciju je krajnje jednostavan:
void setup () { pinMode (4, OUTPUT); //izlaz na D4 } void loop () { digitalWrite (4, HIGH); delay (1000); digitalWrite (4, LOW); delay (500); } Kao što vidimo, sve se svodi na određivanje dužine intervala zvuka i tišine koje podešavamo preko funkcije delay(), a koja dolazi iza digitalwrite(). Često je moguće pročitati da aktivni piezo zvučnici mogu da proizvedu ton samo na jednoj frekvenciji. Ovo je nešto što je i autor teksta prihvatio zdravo za gotovo i dugo ih koristio isključivo u svojstvu alarma sa fiksnom frekvencijom. Prethodna tvrdnja je istinita ukoliko se radi o priključivanju na izvor konstantne struje. Međutim, ukoliko na njihov „+” pin dovedemo kvadratni impuls, zvučnik će reagovati slično svom pasivnom rođaku, zapravo, proizvešće zvuk koji odgovara frekvenciji ulaznog signala.
Aktivni i pasivni piezo zvučnici su vizuelno dosta slični, ali se mogu razlikovati po tome što aktivni imaju za nijansu duže telo, nožica katode im je kraća, donja strana je optočena plastikom (kod pasivnih se vidi zelena štampa) i dolaze sa nalepnicom na vrhu. Nalepnica ima namenu da zaštiti uređaj od neželjenih posledica u toku proizvodnog procesa o čemu govori i natpis „Remove seal after washing”. Radi se o završnom pranju čiji je cilj da ukloni eventualno zaostale nečistoće. Jednostavan način da proverimo vrstu zvučnika jeste da ga priključimo na napon. Ukoliko budemo čuli zvuk, reč je o aktivnom piezo zvučniku. Zbog većeg broja ugrađenih delova, aktivni biperi su za nekoliko desetina procenata skuplji od pasivnih.
Princip upotrebe pasivnih zvučnika je sličan, ali postoje i određene razlike. I ovde imamo dve nožice na koje dovodimo napon i uzemljenje, ali u ovom slučaju moramo da koristimo procesorsku snagu mikrokontrolera (ili nekog drugog izvora signala) za dobijanje zvuka. Tačnije, da bi se proizveo zvuk, na anodu zvučnika je potrebno dovesti signal kvadratnog oblika sa određenom frekvencijom. Što viša frekvencija, to će i ton da bude viši.
Što se tiče gotovih pasivnih modula, mogli bismo da izdvojimo dve vrste koje se razlikuju po prisustvu ili izostanku tranzistora. Njegova funkcija je da pojačava zvuk, pa su moduli sa tranzistorom znatno bučniji od onih koji ga nemaju. Međutim, nije sve idealno, pošto pojačani zvuk na nižim frekvencijama ima izraženu distorziju. Istu stvar možemo da postignemo u sopstvenoj režiji i to tako što bazu tranzistora preko otpornika (2,2 kilooma ili nekog sličnog) povezujemo sa pinom Arduina, emiter na uzemljenje, kolektor na „-” pin zvučnika dok se njegov „+” ulaz povezuje na napon od pet volti. Ovo je najprostiji način korišćenja tranzistora u svojstvu pojačala, dok postoje i brojne druge (nekada i znatno kompleksnije) varijante povezivanja koje daju bolje rezultate. Još jedna korisna funkcija tranzistora se sastoji u zaštiti Arduina od prekomerne potrošnje struje. Kao što smo ranije govorili, povlačenje više od deklarisanih 20 (40 je apsolutni maksimum) miliampera preko pinova Atmega 328 (200 miliampera za Vcc/Gnd pin) može da dovede do njihovog trajnog oštećenja. Dodavanjem otpornika i tranzistora smanjujemo odliv struje preko izlaznog pina i nakon toga vršimo njeno pojačavanje. S obzirom na to da piezo zvučnici najčešće troše daleko ispod 20 miliampera, to u ovom slučaju nije neophodno (mada može poslužiti za smanjenje jačine zvuka). Isto tako, često se sreću sheme povezivanja bez tranzistora koje sadrže otpornik koji bi trebalo da smanji protok struje, što jeste dobra praksa, ali u slučaju piezo zvučnika možemo i bez njega.
Za generisanje zvuka se u standardnoj Arduino biblioteci koristi funkcija tone() koja ima sledeću sintaksu: tone(pin, frekvencija, trajanje) Dakle, pin je Arduino izlaz preko koga ćemo emitovati signal, frekvencija je broj oscilacija u hercima, dok trajanje označava dužinu u milisekundima (obe ove vrednosti su tipa unsigned int). Demonstrativni skeč bi mogao da izgleda ovako: int note[] = { 33,37,41,44,49,55,62,66, //druga oktava 66,74,82,88,98,110,124,132, 132,148,164,176,196,220,248,264, 264,296,328,352,392,440,496,523, 523,592,656,704,784,880,992,1046, 1046,1175,1318,1397,1568,1760,1975,2093, 2093,2349,2637,2794,3136,3520,3951,4186, //osma oktava }; void setup() { } void loop() { for (int nota = 0; nota < 56; nota++) { tone(9, note[nota], 250); delay(250); noTone(9); // zaustavi zvuk na D9 } delay (5000); } Primer će odsvirati četvrtinske note (250 milisekundi) od druge do osme klavirske oktave. Prva oktava je preskočena pošto hardver ne dozvoljava njeno izvođenje. Petlja For..Next prolazi kroz 56 nota čije smo frekvencije zadali u matrici note[]. Zanimljivo je da u okviru skeča funkcija tone() sa ukazanim parametrom trajanje (koji je inače moguće izostaviti) ne obavlja svoju namenu, već se dužina trajanja note određuje preko funkcije delay(). Da stvar bude zanimljivija, sve funkcioniše kako treba ukoliko se reprodukuje samo jedna nota. Smisao funkcije noTone() je da zaustavi reprodukciju na izlaznom pinu. Da smo je izostavili u gornjem primeru, poslednja nota bi trajala 5,25 sekundi zbog linije delay (5000).  | Klasični zvučnici svoj rad zasnivaju na protoku struje kroz žice kalema koji se nalazi unutar magnetnog polja. To izaziva pomeranje koje se prenosi na konus (najčešće se pravi od neke vrste kartona ili plastike), što stvara komešanje vazduha koje osećamo kao zvuk. Za razliku od piezo emitera zvuka, prilikom korišćenja klasičnih 8-omskih zvučnika upotreba otpornika je obavezna stvar. Ukoliko uzmemo prethodno pomenutu maksimalnu dozvoljenu jačinu struje od 20 miliampera, uz pomoć Omovog zakona saznajemo sledeće: R=U(5V)/I(20mA)=250 oma. Što je veći otpor, to je manji protok struje i posledično imamo tiši zvuk na izlazu. Tako bi korišćenjem otpornika od 500 oma dobili struju jačine deset miliampera, dok bi sa otpornikom od 1000 oma imali samo pet miliampera. U projektima na internetu je često moguće videti da se koristi i otpornik od 125 oma, što nam po Omovom zakonu daje jačinu struje od 40 miliampera koja odgovara apsolutnom dozvoljenom maksimumu platforme Arduino. Ipak, ne savetujemo ovakve poteze pošto nekoliko miliampera neće previše uticati na zvuk i, u slučaju da nam je važno da on bude što glasniji, možemo koristiti neki pojačivač signala, a u obzir dolazi i kombinacija otpornik-tranzistor koju smo prethodno demonstrirali. Ukoliko gornji primer sa oktavama izvršimo sa priključenim 8-omskim zvučnikom, videćemo veliku razliku u kvalitetu zvuka u odnosu na biper, što se naročito oseti u dve donje oktave koje su kod piezo zvučnika na granici upotrebljivosti.
Ovo igranje sa biperom ne može a da ne probudi nostalgiju kod nekadašnjih vlasnika ZX Spectruma, koji je generisao zvuk na sličan način. Svi oni koji su imali zadovoljstvo da ga koriste znaju da su igre za njega ponekad imale zvučnu podlogu koja je znatno prevazilazila osnovne mogućnosti hardvera. S obzirom na činjenicu da je Atmega328 na 16 megaherca ostvaruje 16 DMIPS-a, dok ta vrednost kod Z80 na 3,54 megaherca nije prelazila 0,8 DMIPS, jasno je da je to sasvim dovoljno da se proizvede pristojan zvuk. Biblioteka Playtune (goo.gl/PH42Gg) u svom radu intenzivno koristi interapte i u zavisnosti od modela Arduina može istovremeno da reprodukuje od tri do šest kanala zvuka. Još impresivniji rezultati se postižu korišćenjem biblioteke MusicWithoutDelay (goo.gl/cTu8Sd) koja omogućuje reprodukciju zvuka za vreme dok se Arduino bavi drugim poslovima. Njena upotreba je nešto složenija, ali korisnik na raspolaganju ima znatno veću kontrolu nad oblikom zvuka, kao i mogućnost stereo-reprodukcije. Rad sa mikrofonom Korišćenje mikrofona sa platformom Arduino Uno je prilično diskutabilno, pošto količina ugrađene SRAM memorije ne dozvoljava bilo kakvu ozbiljniju praktičnu primenu. Ukoliko bismo ga koristili za snimanje zvuka, onda bi se radilo o niskom nivou kvaliteta. Zato se mikrofoni sa Arduinom najčešće koriste za detekciju zvuka ili analizu njegove frekvencije. Što se tiče prvog zadatka, na tržištu se najčešće nalaze dve vrste modula od kojih je jedan plave, a drugi crvene boje. Oni su po konstrukciji vrlo slični, a osnovna razlika je u tome što kod crvenog pored digitalnog imamo i analogni izlaz. Prisustvo potenciometra i komparatora nam govore da im je princip rada jednak kao u slučaju brojnih drugih modula ranije obrađenih u ovoj rubrici. Dakle, čip LM393 prima signal sa mikrofona i upoređuje ga sa nivoom signala koji je određen potenciometrom, pa u slučaju da je prag prekoračen uključuje LE diodu i šalje signal na izlazni pin. Crveni modul dodatno prosleđuje analognu informaciju, ali nedostatak pojačivača loše utiče na kvalitet zvuka. Po tradiciji se ova vrsta modula najčešće koristi u sistemima protivprovalne zaštite, ali se mogu sresti i u projektima kontrole robota ili drugih uređaja koji reaguju na pljesak ruku ili na povišen glas. Pošto je kôd skeča banalan (očitava se stanje na ulaznom pinu i u slučaju prisustva HIGH signala preduzimamo akciju), izostavićemo ga u svrhu uštede prostora.
Po pitanju kvaliteta su znatno bolji moduli izrađeni na bazi čipa MAX4466 koji se često sreće u okviru telefona i drugih mobilnih uređaja. Sa donje strane modula je preko minijaturnog potenciometra moguće ručno podešavati nivo pojačanja zvuka (zahteva nežno postupanje). Osim naponskih linija, modul ima samo jednu izlaznu liniju i ona je analognog tipa. Primer analize zvuka bi mogao izgledati ovako:
void setup() { Serial.begin(9600); } void loop() { unsigned long pocetak= millis(); // zapocinjemo merenje unsigned int maks = 0; //startne min/maks vrednosti unsigned int min = 1024; while (millis() – pocetak < 50) // uzorak 50 ms (20 Hz) { unsigned int adc = analogRead(0); //trenutna vrednost if (adc < 1024) // samo vrednosti do 1023 { if (adc > maks) //vece od prethodnog maksimuma? { maks = adc; // cuvamo kao novi maksimum } else if (adc < min) { min = adc; // cuvamo kao novi minimum } } } double napon = ((maks – min)* 5.0) / 1024; // amplituda u voltima Serial.println(napon); // ispisujemo napon } Program čita ulazne vrednosti 20 puta u sekundi i upoređuje da li je u danom segmentu došlo do uspostavljanje minimalne i maksimalne tačke nivoa zvuka. Na kraju te podatke pretvaramo u naponske ekvivalente gde svaki korak analognog ulaza ima vrednost od 0,0048 volti (5/1024). Ti podaci se prikazuju u okviru serijskog monitora, a mogli smo ih naknadno ubaciti u neki program za tabelarne proračune i prikazati u obliku grafikona ili smo mogli upotrebiti neku vrstu displeja koja bi davala grafički prikaz u realnom vremenu.
Malo „prave” muzike A šta ako želimo da preko Arduina reprodukujemo pesme ili druge semplovane zvukove? Suštinski imamo dva izbora. Prvi je da koristimo adapter za SD kartice (SK 5/2018), a drugi podrazumeva čitanje semplovanih sadržaja iz fleš memorijskih čipova (SK 4/2018). Pošto je u pitanju procesorski zahtevan posao, prvo je potrebno da u nekom od programa (ili veb servisa kao što je, recimo, online-convert.com) fajlove pretvoriti u wav oblik sa nepredznačenom 8-bitnom PCM formom i rezolucijom sempla od 16 kiloherca. Ovakvi fajlovi troše manje procesorskog vremena, a i veličina u odnosu na MP3 im je manja za nekih 30-40 procenata. Naravno, žrtva je kvalitet zvuka koji će biti na nivou starih AM radio-prijemnika, ali je i to sasvim dovoljno za veliki deo namena.Dobra je stvar što je povezivanje jednostavno, pa možemo koristiti gornji primer sa tranzistorskim pojačivačem u kombinaciji sa čitačem SD kartica priključenim preko interfejsa SPI. Za demonstraciju ćemo koristiti najjednostavniji kod:#include „SD.h” #include „SPI.h” #include „TMRpcm.h” TMRpcm tmrpcm; void setup(){ tmrpcm.speakerPin = 8; //zvucni izlaz Serial.begin(9600); if (!SD.begin(10)) { //CS je povezan sa D10 Serial.println(„SD error”); // SD nije inicijalizovan return; } tmrpcm.setVolume(7); // jacina zvuka tmrpcm.play(„pesma.wav”); //izvodimo wav fajl } void loop (){} Dakle, koristimo standardne biblioteke za SD i SPI, dok je za reprodukciju zvuka potrebno dodati biblioteku TMRpcm (prisutna je u okviru menadžera biblioteka Arduino IDE). Čitač SD kartica priključujemo tako da nam je CS pin povezan sa D10, MOSI na D11, MISO na D12 i SCK na D13, dok zvučnik dobija izlaz sa pina D8. Primer zbog ograničenosti prostora reprodukuje samo jednu pesmu. Ukoliko želimo implementirati mogućnost reprodukcije različitih fajlova, potrebno je dodati kod koji će koristiti funkciju tmrpcm.isplaying(), a čiji je zadatak da nam da informaciju da li je u toku izvođenje nekog fajla. Na ovo je moguće dodati upravljanje preko serijskog monitora gde ćemo upisivati željene komande. Dodatne informacije o biblioteci se mogu pronaći na linku goo.gl/jMt726. Ukoliko nam je potrebna reprodukcija MP3 fajlova, rešenje je u korišćenju modula sa hardverskim dekoderom. S obzirom na to da im je cena niža od 1,5 dolara, jednostavno se nameću kao idealan izbor u svim projektima koji imaju vezu sa reprodukcijom muzike. Ovde govorimo o modulu koji na sebi najčešće ima oznaku DFPlayer Mini, ali nisu retki i oni kod kojih je oznaka MP3-TF-16p (osim naziva se još jedino razlikuju u boji LE diode koja je kod prvog plava, a kod drugog narandžasta). Srce sistema je integralno kolo YX5200-24SS koje ima 24-bitni DAC izlaz i podržava mikro SD kartice kapaciteta do 32 gigabajta sa fajl sistemom FAT32. Kartica može sadržati do 99 foldera, a ukupno je moguće smestiti do 3000 pesama. Važno je da nazivi fajlova moraju imati format: 0001.mp3, 0002.mp3... Iza početnih brojeva ime može da sadrži proizvoljan tekst. Čip omogućuje do trideset koraka jačine zvuka i ima šest podešavanja ekvilajzera. Što se tiče podrške za zvučne formate, tu su MP3, WAV i WMA sa frekvencijama semplovanja od 8, 11,025, 12, 16, 22,05, 24, 32, 44,1 i 48 kiloherca. Dinamički opseg iznosi 90 decibela, dok je SNR (signal-to-noise ratio) 85 decibela. Na pločici je još smešteno i integralno kolo 8002A, koje ima funkciju audio-pojačivača snage do dva vata.Navedeni modul može da funkcioniše autonomno ili da bude priključen na mikrokontroler preko serijskog interfejsa. U prvom slučaju se na pinove IO_1 i IO_2 priključuju push tasteri, koji nakon ostvarenog kontakta dovode signal logičke nule. Kraći pritisak na tastere dovodi do izdavanja naredbi za prelazak na prethodni ili sledeći fajl, dok dužim pridržavanjem utiču na jačinu zvuka. Jedini problem predstavlja činjenica da nakon svakog odsviranog fajla moramo dovoditi logičku nulu na pin IO_2 ili IO_1. Ukoliko nam je potreban veći stepen kontrole, koristićemo pinove 12 i 13 (ADKEY_1, ADKEY_2) preko kojih možemo priključiti tastere spojene paralelnom vezom otpornika, od kojih svaki sledeći ima dvostruko veću otpornost od prethodnika. Rezultat je analogna vrednost koja će odgovarati pritisku na neki od čak dvadeset tastera (2 x 10). Modul ima dva izvora signala od kojih onaj na pinovima 4 i 5 nije pojačavan, dok se na pinove 6 i 8 zvučnici priključuju direktno. Ovde treba reći da je jačina izlaznog zvuka dosta slaba, pa je upotreba pojačala praktično neizbežna. Pin BUSY je za vreme reprodukcije fajla u stanju logičke nule, dok je u suprotnom u stanju logičke jedinice. Tu su još i pinovi za priključivanje eksternog memorijskog skladišta preko USB interfejsa. Nakon povezivanja modula sa električnim kolom, signalna LE dioda će emitovati prigušeno svetlo, dok će nakon dovođenja logičke nule na pin IO_2 zasvetliti punim kapacitetom. Zvučnik se povezuju preko pinova SPK_1 i SPK_2 ili kombinovanjem uzemljenja sa jednim od njih. Za postizanje stereo-zvuka je potrebno koristiti signale pinova DAC_L i DAC_R.  | | Dosta je zanimljivija i tehnički naprednija upotreba serijskog interfejsa koji ostvarujemo povezivanjem na pinove 1 i 2 i preko kojega možemo slati naredbe i primati informacije od modula. Na ilustraciji smo koristili dva otpornika veličine jedan kiloom, mada je suštinski moguće izostaviti otpornik na liniji koja vodi signal od modula prema Arduinu. Standardna brzina serijskog porta iznosi 9600 boda u sekundi, ali je to moguće promeniti. Komunikacija se ostvaruje slanjem bloka bajtova koji sadrže kod naredbe, parametre i checksum za proveru ispravnosti prenesenih podataka. Strukturu naredbe je najlakše razumeti analizom sledećeg koda:void SendCommand(byte naredba, unsigned int param) { bajt[0] = 0x7E; // pocetni bajt bajt[1] = 0xFF; // verzija bajt[2] = 0x06; // duzina bajt[3] = naredba; // bajt komande bajt[4] = 0x00; // feedback bajt[5] = (unsigned byte)(param >> 8); // visi bajt parametra bajt[6] = (unsigned byte)(param); // nizi bajt parametra //negirani ceksum bajtova 1-7 unsigned int CSum = -(bajt[1] + bajt[2] + bajt[3] + bajt[4] + bajt[5] + bajt[6]); bajt[7] = (unsigned byte)(CSum >> 8); // visi bajt ceksuma bajt[8] = (unsigned byte)(CSum); // nizi bajt ceksuma bajt[9] = 0xEF; //zavrsetak bloka for (int i=0; i<10; i++) { // slanje na modul MP3.write(bajt[i]); } delay(100); }  Početni bajt strukture ima heksadecimalnu vrednost 0x7E, a njega sledi vrednost 0xFF koja se nikada ne menja i koja predstavlja verziju korišćenih naredbi. Bajt na poziciji 2 sadrži vrednost dužine naredbe i ona je uvek 6, pošto se značajni podaci nalaze u sledećih šest bajtova. Bajt naredbe se nalazi na poziciji 3, a njegova značenja imamo u pratećoj tabeli. Sledeća dva bajta predstavljaju vrednost parametra komande koju šaljemo plejeru. Recimo, ukoliko želimo jačinu zvuka postaviti na 15 (50%), viši bajt će dobiti vrednost 0x00, a drugi 0x0F, pa će sekvenca imati sledeći oblik: Poslednji bajt (0xEF) označava kraj sekvence dok su dva bajta ispred njega rezervisana za čuvanje vrednosti negiranog zbira bajtova od pozicije 1 do 6. U našem slučaju to bi izgledalo ovako: FF+06+06+00+00+0F = 0x011A-(0x011A) = FFFFFEE5
Iz rezultata uzimamo dva poslednja bajta (0xFE i 0xE5) i dodajemo ih u gornju strukturu. Iako je upravljanje plejerom moguće preko standardne Arduino naredbe za serijsku komunikaciju, dosta je praktičnije koristiti biblioteku DFPlayer Mini MP3 koja se nalazi na adresi goo.gl/NrgV4a, a može se instalirati i preko ugrađenog menadžera biblioteka. Ona sadrži tridesetak funkcija koje omogućavaju jednostavno upravljanje resursima MP3 plejera. Igor S. RUŽIĆ | | |