logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[ATmega32] [C] PWM przydzwięk o niższej tonacji

maly_elektronik 21 Sie 2011 10:47 7670 74
  • #1 9846409
    maly_elektronik
    Poziom 23  
    Witam,
    to już drugi temat odnośnie dźwięku generowanego przy pomocy PWM'a :)
    Jako że pierwszy temat/problem został rozwiązany i zakończony to pojawił się inny problem chyba innej natury.

    Generowany dźwięk jest ładny płynny jednak pojawia się przygłos (jeśli tak to się fachowo nazywa). Mianowicie pojawia się identyczna melodia (nałożone na podstawową) która jest o znacznie innej wysokości (niższa). Co może być tego przyczyną :?: Niestety nie posiadam oscyloskopu i nie jestem w stanie sprawdzić czy wystarczy do tego jakiś filtr górnoprzepustowy :(

    Pozdrawiam maly_elektronik
  • #2 9846434
    gaskoin
    Poziom 38  
    a jakie masz filtry na wyjściu ?
  • #3 9846448
    maly_elektronik
    Poziom 23  
    Mam pasywny filtr dolnoprzepustowy R=470, C=100n :)
  • #5 9846662
    maly_elektronik
    Poziom 23  
    Nie bardzo rozumie o co chodzi z kodem blokującym i opartym na pollingu timera :( Możesz wyjaśnić :?:
  • Pomocny post
    #6 9846841
    LordBlick
    VIP Zasłużony dla elektroda
    W poprzednim temacie pisałeś o tym, ze sprawdzasz flagę timera, więc stąd moje stwierdzenie. Tamten kod jest zablokowany na poziomie ReadFile.
  • #8 9847357
    nsvinc
    Poziom 35  
    Podawanie kolejnych próbek do PWMa musi chodzić "jak w zegarku". Nie mozesz się mylić o kilkadziesiąt mikrosekund i myśleć że nic się nie stanie, a karmienie PWMa nie ma prawa być blokowane przez nic!
    Dobrym rozwiązaniem jest podwójne buforowanie. Jeden bufor jest właśnie czytany (w ISRrze timera co cykl!), drugi wlasnie jest zapisywany danymi z karty. Wtedy praktycznie eliminujesz możliwość czasowego rozjazdu między próbkami.
    Dodatkowo bardzo przyda się kontrola niedopełnienia bufora, tak, że w momencie gdy (z dowolnego powodu) brakuje następnej próbki, wstrzymujesz odtwarzanie, czekasz na ponowne zapełnienie obu buforów, po czym rozpoczynasz odtwarzanie ponownie. Uzyskany efekt będzie przypominał irytujące "przycinanie" podczas słuchania shoutcastów.

    Poza tym, twój filtr. Czemu gdy ja policzyłem jego częstotliwość graniczną, wyszło mi 3386Hz? Nie jest to troche... nie tak? Ile wynosi twój fs? Dobierałeś filtr czy raczyłeś wylosować wartości?...Jaka jest impedancja układu którym obciążasz filtr?
  • #9 9847929
    maly_elektronik
    Poziom 23  
    Racja elementy dobrane losowo z przypadkowych elementów (ale widziałem w sieci że i bez filtra było ok) :)

    Próbkowanie 44100Hz, nie robię buforowania ale jako że kartę odczytuje z prędkością 8MHz (sprzętowy spi) to z wyliczeń wyszło mi że trace max 500ns co mogłoby ewentualnie powodować lekkie bzyczenie po odczytaniu kolejnych sektorów :)

    Obciążeniem jest wzmacniacz (jakiś tani wzmacniacz komputerowy z głośnikami)

    Oto próbka:




    P.S Zwróćcie uwagę wyłącznie na te niskie tony (przydzwięk śpiewanych słów) w rzeczywistości reszty zakłuceń nie ma (są spowodowane słabym mikrofonem w telefonie).
  • #10 9849655
    nsvinc
    Poziom 35  
    Nie będzie jako takiego bzyczenia, będą zniekształcenia sygnału.

    Można sądzić, że twój wzmak ma za małą impedancję wejściową.

    Wez podwójny zmacniacz operacyjny typu LM324 czy MCP6002. Na jednym zrób filtr drugiego rzędu LP z częstotliwością graniczną 18kHz, na drugim zrób zwykły wtórnik. Podłącz w kolejności: [procek]->[pasywny_lp]->[wtórnik]->[aktywny_lp]->[wzmak].

    Dobierz rezystor z kondensatorem do pasywnego filtra według wzoru f=1/(2ΠRC). f ustal też w okolicy 18kHz. Dobieraj kondensator z zakresu 1nF..10nF, a nastepnie wylicz rezystor.

    Tak czy siak, wprowadź buforowanie. Nawet niewielkie bufory po kilkadziesiąt (np 64) bajtów, to niestety jest konieczne aby wszystko trzymało się kupy...
  • #12 9849687
    nsvinc
    Poziom 35  
    Moze sprecyzuj co to za głośnik ;] Głośnik "hi-fi" <=16R zupełnie się nie nada. Do badania tego od biedy nadadzą się słuchawki douszne lub głośniczek "prykacz" (taki jak z obudowy PC).

    Przecież nie wolno zapominać o impedancji wyjściowej pasywnego filtra, i problemach wynikających z niedopasowania tej impedancji do obciążenia...

    Użyteczną informacją było by widmo. Czyli procek generuje czyściutkiego sinusa 1kHz, za filtr jest podłączony oscyloskop z analizatorem widma. Potem procek ma generować czysciutki prostokąt, i też zbadać widmo...
  • #13 9849692
    dondu
    Moderator na urlopie...
    To mały głośniczek o średnicy 4-5cm z jakiejś zabawki. Na słuchawce także działa ok.
    Oczywiście to rozwiązanie do testu, by stwierdzić czy problemem jest program i uC, czy część analogowa (filtr i wzmacniacz).
  • Pomocny post
    #14 9849863
    Fredy
    Poziom 27  
    To co słychać to napewno nie jest przydźwięk. To są najnormalniejsze zniekształcenia.
    Zwiększ stałą czasową filtru zdecydowanie. Najwyżej utracisz wysokie dźwięki , ale napewno wtedy powinna poprawić się filtracja. Dla próby podłącz wzmacniacz przez rezystor szeregowy np 100K aby wyeliminować zjawisko małej impedancji wzmacniacza i jego wpływu na filtr. Najlepiej gdybyś pomiędzy wzmacniacz i filtr dał wtórnik emiterowy.
    Jeśli te zabiegi nie przyniosą rezultatu to musisz szukać błędów po stronie programowej. Program musi zapewnić płynny i szybki przesył do PWMa , także wyłącz wszystkie niepotrzebne przerwania itp.
  • #15 9851049
    maly_elektronik
    Poziom 23  
    Jak na razie zastosowałem filtr dolnoprzepustowy (pasywny R=880, C=10n) ->wtórnik(LM358)->wzmacniacz->głośnik(8Ω) i niestety nie słyszę poprawy :(

    Więc wina raczej leży w kodzie :(
    Oprócz buforowania ma może ktoś jakiś pomysł :?:
  • #16 9851135
    LordBlick
    VIP Zasłużony dla elektroda
    Mój pomysł jest taki - podaj więcej szczegółów, bo nie raczyłeś napisać jakiego µC używasz, całość kodu też jest supertajna (np. jak rozwiązałeś parsowanie pliku wav) - może dlatego nie działa ? ;)
    Próbowałeś w ogóle najpierw uruchomić te projekty ? :
    http://elm-chan.org/works/sd8p/sd8psrc.zip
    http://elm-chan.org/works/sd20p/sdsg.zip
  • #17 9851309
    maly_elektronik
    Poziom 23  
    Procesorem jest mega32 :)
    Kod podany jest w linku w pierwszym poście tak więc nie jest owiany żadną tajemnicą :)
    Nie parsowałem w żaden sposób pliku wav (tworze go przy pomocy audacity ->8bit PCM Windows Wav (przy pomocy exportu pliku)

    P.S Żaden z podanych linków nie działa (no chyba ze ma kierować na strone główną yahoo)
  • #18 9851512
    LordBlick
    VIP Zasłużony dla elektroda
    maly_elektronik napisał:
    Procesorem jest mega32 :)
    Kod podany jest w linku w pierwszym poście tak więc nie jest owiany żadną tajemnicą :)
    Nie parsowałem w żaden sposób pliku wav (tworze go przy pomocy audacity ->8bit PCM Windows Wav (przy pomocy exportu pliku)
    W takm razie zamiast waw, eksportuj jako Other uncompressed file/Opcje ->Nagłówek: RAW/Encoding : Unsigned 8 bit PCM

    maly_elektronik napisał:
    P.S Żaden z podanych linków nie działa (no chyba ze ma kierować na strone główną yahoo)
    Byc może elm-chan się tak zabezpiecza przed DoS. A te u Ciebie działają ? :
    http://elm-chan.org/works/sd20p/report.html
    http://elm-chan.org/works/sd8p/report.html
    zip-y były od nich.
  • #19 9851766
    Konto nie istnieje
    Poziom 1  
  • #20 9851998
    maly_elektronik
    Poziom 23  
    A w jaki sposób mogę zsynchronizować PWM'a z częstotliwością podawania próbek :?:
  • #21 9852098
    Konto nie istnieje
    Poziom 1  
  • #22 9852135
    dondu
    Moderator na urlopie...
    atom1477 napisał:
    No umieszczając kod zapodający próbki z przerwaniu od Timera który generuje PWMa.

    Hmmm, ale czy zawsze da się to zrobić?
    Mam na myśli różne częstotliwości próbkowania dźwięku.
    Jeżeli próbka ma 256 stanów, a częstotliwość próbkowania 44100 to nie bardzo jest to możliwe.

    No chyba, że źle myślę.
  • #23 9852467
    nsvinc
    Poziom 35  
    Nie rozumiem problemu. To, że PWM ma 256 stanów nie powinno miec nic wspolnego z częstotliwością próbkowania.

    Według mnie to wygląda tak:
    Zegar DPWM powinien wynosić f_samplowania*rozdzielczosc_pwm[*n], w tym przypadku 44100*256*1=11289600Hz. [n] - wielokrotność całkowita(1..ileś), tutaj 1 z racji ograniczonego zegara DPWM. Kazda inna częstotliwość pracy DPWMa potencjalnie da rozjazdy i wprowadzi zniekształcenia.
    Również, co ok. 22.68us (1/44100Hz) musi wystąpić przerwanie na "przewinięcie" timera (czyli koniec cyklu DPWM), w którym trzeba podać do komparatora nową próbkę. Jest gorzej, ponieważ gdy procek zacznie włazić w ISR, to równocześnie rozpocznie się nowy cykl DPWM idący do starej wartości komparatora - w efekcie otrzymasz dwa razy pod rząd to samo wypełnienie nawet przeładowując komparator (w przypadku buforowania SFRa komparatora) lub worst case wygenerujesz przekłamanie sygnału PWM.

    Jak juz pisałem wcześniej, to musi chodzić jak w zegarku.

    Ten procesor nie wyrobi się z przerwaniem co 22.68us, więc sensowne byłoby zjechanie tą częstotliwością do 8kHz. W końcu i tak masz rozdzielczość tylko 8 bitów, a zyskujesz sporo czasu, masz mozliwość w spokoju i bez nerwów zapanować nad odtwarzaniem dźwięku. To co masz teraz, będzie z definicji trudne do zrealizowania bez DMA, nawet na ARMie...
  • #24 9852475
    maly_elektronik
    Poziom 23  
    Nie jestem w stanie uzyskać takiej częstotliwości PWM gdyż mega pracuje na 16MHz czyli max może on wynosić ok 8MHz :(
    Co oznacza to DPWM :?:

    atom1447 ->
    W taki sposób podaję próbki:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Nie jestem w stanie tego zrobić w procedurze przerwania gdyż bufor do którego odczytuje wartości z karty sd posiada dane tyko wewnątrz funkcji read file (przekazywany jest wskaźnik do tablicy, przez to jest ona wypełnina danymi "wewnątrz tejże funkcji" - chyba że się myle :?: )
  • #25 9852715
    dondu
    Moderator na urlopie...
    nsvinc napisał:
    Nie rozumiem problemu. To, że PWM ma 256 stanów nie powinno miec nic wspolnego z częstotliwością próbkowania.

    Kol. atom1477 zaproponował zsynchronizowanie PWM i okresu podawania próbek.
    Synchronizacja polega na tym, iż coś się kończy i/lub zaczyna w tym samym momencie.

    Próbka ma 256 stanów czyli co najmniej 256 cykli zegara PWM (lub wielokrotność). Inaczej nie da się odtworzyć dokładnie wypełnienia od 0 do 256.

    Ale dźwięk był próbkowany z częstotliwością 44100, która nie jest podzielna przez 256, tzn. wynik nie jest liczbą całkowitą. Dlatego twierdzę (chyba, że się mylę) , iż nie da się zsynchronizować tych dwóch sygnałów.

    I tylko o to mi chodziło.
  • #26 9852885
    nsvinc
    Poziom 35  
    maly_elektronik napisał:
    Nie jestem w stanie tego zrobić w procedurze przerwania gdyż bufor do którego odczytuje wartości z karty sd posiada dane tyko wewnątrz funkcji read file (przekazywany jest wskaźnik do tablicy, przez to jest ona wypełnina danymi "wewnątrz tejże funkcji" - chyba że się myle )

    Mylisz się. Przecież do funkcji podajesz wskaźnik. Pod tym wskaznikiem masz konkretny ciąg bajtów w RAMie procesora! Jeśli do funkcji podajesz globalny wskaźnik (np. tablica unsigned char bufor[512]; ), to dane z tego bufora są widoczne gdziekolwiek, równie dobrze w przerwaniu, jak i w mainie.

    DPWM to Digital PWM czyli po prostu match/compare+licznik...

    dondu napisał:
    Próbka ma 256 stanów czyli co najmniej 256 cykli zegara PWM (lub wielokrotność). Inaczej nie da się odtworzyć dokładnie wypełnienia od 0 do 256.

    Mam wrażenie że coś jest nie tak z tym stwierdzeniem. Przecież dysponując odpowiednimi timingami w programie, da się uzyskać w czysto programowy sposób chociażby 2 cykle na próbkę. Bez udziwnień...
    No i nie zgodzę się co do synchronizowania stanów PWMa z częstotliwością próbkowania. Trochę to bez sensu, gdyż chociażby standard CD-Audio przewiduje 16 b x 44.1ksps, a 65536 i 44100 też się nijak do siebie mają - a gra; Kolejny standard to 8b x 8ksps; 256 do 8000 też nie mają raczej nic wspólnego, a też gra...
    Nigdy nie powiedziałbym, że częstotliwość próbkowania ma być w jakikolwiek zsynchronizowana z rozdzielczością bitową. Ja sobie mogę wymyślić "standard" 15469sps przy 13 bitach, i dokładnie tak samo będzie grać, o ile samo odtwarzanie jest zaimplementowane prawidłowo...
  • #27 9852898
    dondu
    Moderator na urlopie...
    nsvinc napisał:
    Kolejny standard to 8b x 8ksps; 256 do 8000 też nie mają raczej nic wspólnego, a też gra...

    Ależ oczywiście, że gra, ale nie jest zsychronizowane z PWM tak jak to proponował atom1447. Jeszcze raz podkreślam, że tylko o niemożliwość synchronizacji mi chodzi. A to o tyle istotne, że pytanie zadał autor tematu:

    maly_elektronik napisał:
    A w jaki sposób mogę zsynchronizować PWM'a z częstotliwością podawania próbek :?:


    No chyba, że się mylę. A drążę ten temat także dlatego, że wszystkie PWM jakie robiłem nigdy nie były zsynchronizowane według zaleceń kol. atom1477, i grają bardzo dobrze. Ale jeżeli da się to jakoś zsynchronizować, to z chęcią poznałbym jak to zrobić.
  • #28 9852911
    nsvinc
    Poziom 35  
    maly_elektronik napisał:
    A w jaki sposób mogę zsynchronizować PWM'a z częstotliwością podawania próbek

    Nijak, bo imho nie ma takiej potrzeby!
    Próbki do PWMa trzeba podawać RÓWNO. W przerwaniu. Łącznie z mechanizmem zapobiegającym ponowienie "starej" próbki w miejsce nowej z powodu opóźnień wprowadzanych przez kontroler przerwań i sam rdzeń. Czyli to co napisałem w #23.
    Koniecznie zwolnić samplowanie tak, aby procek miał czas na obsługę ISRa timera i odczyty z karty. 8ksps to max, co może z tego być.
  • #29 9852920
    dondu
    Moderator na urlopie...
    Nie musisz używać wykrzykników. Ja dobrze "słyszę" czytany tekst :)

    Czyli uważamy tak samo w zakresie braku konieczności synchronizowania. W takim układzie mam nadzieję, że kol. atmo1477 podpowie jak dokładnie to można zrobić.
  • #30 9853207
    maly_elektronik
    Poziom 23  
    Poniżej wklejam kod całego mojego testowego projektu (eclipse), jeżeli to możliwe proszę osoby zaangażowane o przejrzenie i ewentualne przetestowanie :)
REKLAMA