Elektroda.pl
Elektroda.pl
X
Elektroda.pl
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

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

maly_elektronik 21 Sie 2011 10:47 6758 74
  • #1 21 Sie 2011 10:47
    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

    0 29
  • #2 21 Sie 2011 10:55
    gaskoin
    Poziom 38  

    a jakie masz filtry na wyjściu ?

    0
  • #3 21 Sie 2011 10:59
    maly_elektronik
    Poziom 23  

    Mam pasywny filtr dolnoprzepustowy R=470, C=100n :)

    0
  • #4 21 Sie 2011 11:18
    LordBlick
    VIP Zasłużony dla elektroda

    Dużo też zależy od kodu, zwłaszcza jak jest blokujący i w dodatku oparty na polingu timera...

    0
  • #5 21 Sie 2011 11:59
    maly_elektronik
    Poziom 23  

    Nie bardzo rozumie o co chodzi z kodem blokującym i opartym na pollingu timera :( Możesz wyjaśnić :?:

    0
  • Pomocny post
    #6 21 Sie 2011 13:02
    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.

    0
  • #8 21 Sie 2011 15:17
    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?

    0
  • #9 21 Sie 2011 18:37
    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).

    0
  • #10 22 Sie 2011 09:41
    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...

    0
  • #12 22 Sie 2011 09:53
    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...

    0
  • #13 22 Sie 2011 09:55
    dondu
    Moderator Mikrokontrolery Projektowanie

    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).

    0
  • Pomocny post
    #14 22 Sie 2011 11:09
    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.

    0
  • #15 22 Sie 2011 17:32
    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ł :?:

    0
  • #17 22 Sie 2011 18:49
    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)

    0
  • #18 22 Sie 2011 19:46
    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.

    0
  • #19 22 Sie 2011 20:44
    atom1477
    Poziom 43  

    Znam te zakłócenia i pochodzą one wyłącznie od softu.
    Żadne filtry tutaj nie pomogą. Trzeba poprawić soft.
    Już dokładnie nie pamiętam bo dawno się tym bawiłem ale zdaje się że powstają one z powodu niezsynchronizowania częstotliwości odczytu próbek z częstotliwością PWMa. Powinny być one równe lub być swoimi całkowitymi wielokrotnościami.
    Nienadążanie programu z ładowaniem próbek do PWMa również spowoduje rozjechanie się tych częstotliwości i da podobny efekt.

    0
  • #20 22 Sie 2011 21:27
    maly_elektronik
    Poziom 23  

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

    0
  • #21 22 Sie 2011 21:45
    atom1477
    Poziom 43  

    No umieszczając kod zapodający próbki z przerwaniu od Timera który generuje PWMa.

    0
  • #22 22 Sie 2011 21:52
    dondu
    Moderator Mikrokontrolery Projektowanie

    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ę.

    0
  • #23 22 Sie 2011 22:42
    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...

    0
  • #24 22 Sie 2011 22:42
    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
    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 :?: )

    0
  • #25 22 Sie 2011 23:34
    dondu
    Moderator Mikrokontrolery Projektowanie

    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.

    0
  • #26 23 Sie 2011 00:33
    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...

    0
  • #27 23 Sie 2011 00:37
    dondu
    Moderator Mikrokontrolery Projektowanie

    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ć.

    0
  • #28 23 Sie 2011 00:43
    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ć.

    0
  • #29 23 Sie 2011 00:47
    dondu
    Moderator Mikrokontrolery Projektowanie

    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ć.

    0
  • #30 23 Sie 2011 08:49
    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 :)

    0