Redă fișiere WAV de pe un card SD printr-o mufă pentru boxe, luminând matricea de 64 de LED-uri (speram ca un VUmetru). Se poate naviga prin cântece prin butoane.
Scopul ar fi fost să am un fel de iPod (destul de voluminos în final…) cu spectrul afișat pe matricea de LED-uri. Am vrut să fie multe ca să fie cât mai interactiv, dar în final microcontroller-ul n-a putut să și redea audio și să calculeze spectrul / să aprindă LED-urile simultan.
Așa că, în schimb, sunt aprinse LED-uri arbitrar și se controlează cântecul curent prin butoane de next și forward. Redarea audio se face pe ambele canale.
Pentru realizarea, am avut nevoie de:
Proiectul funcționează plecând de la redarea cântecelor din laboratorul 4. Am încercat înlocuirea codului cu altă bibliotecă FAT, dar deși am citit fișierele, n-am reușit să redau muzica. Surprinzător codul din labul 4, deși e remarcabil de greu de citit, funcționează și încercările mele de a reduce din variabilele aparent redundante (FifoCt de exemplu) au făcut să nu meargă.
Am adăugat suport și pentru celălalt canal (deși e doar mono) și există în cod suport pentru transformata Fourier și pentru aprinderea LED-urilor conform rezultatelor transformării (într-o rutină de tratare de întreruperi a timerului 2).
Din păcate, dacă fac vreunul din acele două lucruri (transformata sau aprinsul LED-urilor într-o întrerupere), microncontrollerul nu face față la sample rate-ul necesar și nu se mai aude nimic. Concluzia ar fi că ar fi fost necesar încă un microcontroller sau unul mai puternic pentru acest proiect.
Plăcuța pentru proiect are 3 părți importante: LED-urile, jack-ul și butoanele.
Pentru matrice, am folosit multiplexarea. Adică, LED-urile sunt aranjate într-o matrice, legând anodurile respectiv catodurile pe coloane respectiv linii împreună. Pentru p pini în total, ei trebuie distribuiți în x respectiv p - x pini pe linii și respectiv coloane în funcție de matricea dorită (se pot multiplexa x * (p - x) pini). Aranjarea cea mai bună este cu p/2 pini pe linii respectiv coloane (derivând numărul de pini).
Rezistențele sunt acolo pentru a nu trece prea mult curent printr-un LED. Trebuie ajustate să iasă 0.6V (sau tensiunea suportată de LED) știind că pe un pin ies 5V (aici am pus pur și simplu 1K și nu se prea văd aprinse LED-urile la mine).
Am folosit toți pinii de pe PORTA și PORTC pentru o matrice 8×8 de 64 de LED-uri.
Multiplexarea se implementează aprinzând cu un delay foarte mic LED-urile dorite (ceva gen 0.1 ms).
Jack-ul în sine este ușor de conectat, dar mi-a luat extrem de mult să găsesc componenta în Eagle. Am găsit-o în biblioteca con-lumberg în cele din urmă.
Are 2 pini pentru ieșirile stânga și dreapta, pe care i-am conectat la cele două canale ale timer-ului 1 (*OC1A* și *OC1B* din PORTD). Condensatoarele sunt acolo fiindcă vrem doar componenta variabilă a semnalului.
Pentru butoane, a rămas sa folosesc singurul port disponibil, PORTB și în plan erau 4 butoane: next, previous, volume up și volume down.
Transeele nerutate cu albastru au trebuit construite manual prin fire. Altfel, ar fi trebuit imprimată pe ambele fețe plăcuța.
Un sector pe un card SD formatat cu FAT este 512 octeți. Citirea este cel mai lung proces și de acceea pentru a avea sample-uri cât mai repede, se folosește double buffering. Există deci două buffere de câte 256 de octeți din care sunt luate sample-uri unul câte unul.
Sample-rate-ul necesar se citește din fișierul WAV și trebuie ca la acea frecvență să fie schimbat un sample. Am setat timer-ul 0 să se ocupe de asta și eșantionul e înlocuit pe ambele canale printr-o rutină de tratare de semnal.
Timer-ul 1 generează semnaul audio prin PWM (fast, pe 8 biți dacă de atât sunt eșantionalele). Fiindcă PWM-ul e dependent de eșantionul din registerele OCR1A/B, semnalul poate fi distorsionat/stricat complet dacă nu sunt actualizate suficient de repede bufferele.
Pentru redarea spectrului, se folosește Transformata Fourier, care trece din domeniul timp în domeniu frecvență. Adică, pentru cele 256 de eșantione dintr-un buffer, se obțin frecvențele semnalului (eșantioanele reprezintă de fapt funcția continuă a semnalului audio). Rezultatul transformatei este o valoare complexă, iar pentru spectru, trebuie să determin câte LED-uri trebuie luminate pe fiecare coloană. Deci, grupez cele 256 de valori din spectrul rezultat în 8 grupe de câte 32 și adun normele numerelor complexe rezultate din transformată pentru fiecare grup. În funcție de ce valoare obțin dintr-un maxim de 32 * 256, aprind proporțional de multe LED-uri pe acea coloană.
Am creat buffere pentru partea reală și cea imaginară a transformării, re și im pe care ideal ar fi trebuit să le aloc de 256 de octeți pe fiecare. Din păcate, cum deja sunt folosiți peste 512 octeți cu double buffering-ul și mai sunt alocate date pentru structurile de date ale sistemului de fișiere, aș fi depășit 1k de RAM. Am decis să fac bufferele mai mici și să calculez transformata pentru primele câteva eșantioane. Din păcate, asta încetinește prea mult funcția de citire a bufferelor și nu se mai aude semnalul.
Multiplexarea LED-urilor se face într-o rutină de tratare a întreruperilor pentru timer-ul 2, care să se declanșeze cât mai rar posibil (deci la overflow). Chiar și așa, tot a fost prea mult și nu s-a mai auzit nimic.
Așa că, am rămas la aprinderea câte unui LED aleator.
Descrierea codului aplicaţiei (firmware):
Nu lipiți niciodată matrici de LED-uri!
Asigurați-vă că microcontroller-ul chiar poate să facă ce e nevoie pentru proiect. Am descoperit prea târziu că un microcontroller nu e suficient. În plus, ar fi fost ideal mai mult RAM (peste 1K) și la un moment dat chiar am reușit să suprascriu bootloader-ul (încercam să fac să meargă suportul pentru carduri SDHC - carduri SD peste 2GB - și n-am realizat că e prea mare codul).
Cred c-ar fi fost de asemenea util să am un programator prin ISP. Mi s-a întâmplat de nenumărate ori să nu fie văzut dispozitivul din prima. Dar, concluzia asta intră într-o idee mai generală: asigurați-vă că aveți instrumentele necesare: pentru lipit (fludor, ledcon, componente de rezervă, pompă, fire, răbdare) și pentru programat (un ISP ideal, un debugger ar fi prins extrem de bine).
Totuși, pot să zic c-ar fi mers de 1000x mai rău dacă n-aș fi avut ajutorul echipei de PM! Am fost ajutat la lipitul inițial, la proiectarea și asamblarea plăcuței noi și cu un ISP când mi-am suprascris bootloader-ul… Mulțumesc! :)
Arhiva cu codul și schema proiectului.