Witam.
Ostatnio zainteresowałem się zrobieniem swojego analizatora widma. W necie jest schemat elm-chana z użyciem układu max293 oraz inny projekt na max297. Z dokumentacji wynika, że są to filtry dolnoprzepustowe obcinające przy 25KHz(max293) oraz 50KHz(max297) oraz stromym zboczem (ok. -80dB). Zdobyłem układzik: max293, ale chciałbym głębiej zapoznać się z zasadą jego działania.
Na stronie elm-chan jest implementacja takiego filtra i wykorzystane jest jedno wyjście rozumiem, że w takim wypadku filtr obcina przy 25KHz i cały sygnał w paśmie przepuszczania idzie na wejście przetwornika, czy tak?
Poco jest wejście CLK na tym filtrze? Myślałem, że do ADC uC idzie sygnał ciągły i próbkowany jest na przetworniku.
Schemat jest tu:
Jest też inny projekt. W tym dwa sygnały wyprowadzone są do przetwornika ADC uC. Są to inne częstotliwości ale po co? Dlaczego nie próbkować całej częstotliwości z jednego wejścia?
No i tu brakuje podłączenia CLK, czym to skutkuje?
Na próbkowanym sygnale w dalszej kolejności chce przeprowadzić FFT i gotowe prążki podać na LCD. Ale to później, jak poznam zasadę działania od strony hardwarowej.
Thx.
Cóż jeśli to jest filtr układowy ten max293, więc jest to zapewne filtr z przełączanymi pojemnościami - więc po to mu zegar. To taka analogowa(sprzętowa) implementacja filtru cyfrowego ze wszystkimi jego zaletami i wadami(aliasing) .
Jest też inny projekt. W tym dwa sygnały wyprowadzone są do przetwornika ADC uC. Są to inne częstotliwości ale po co? Dlaczego nie próbkować całej częstotliwości z jednego wejścia?
No i tu brakuje podłączenia CLK, czym to skutkuje?
W poście, w którym wrzuciłem ten schemat napisałem (a jak nie tam, to w innym, gdzie opisałem układ, powinien tam gdzieś być link), dlaczego dwa sygnały, a nie jeden.
Napiszę raz jeszcze.
Założeniem tego analizatora miało być przetwoarzanie częstotliwości do 16kHz, częstotliwość próbkowania wynosi więc 32kHz. Kolejne założenie jest take, że skala częstotliwości ma być logarytmiczna, więc niskie częstotliwości są dość dobrze widoczne. Jeżeli teraz chciałbym przedstawić na analizatorze sygnał o częstotliwości 31.5Hz zdaje się, czy coś w pobliżu, dla uproszczenia załóżmy, że 32Hz, to przy częstotliwości próbkowania trzeba było by zebrać 1000 próbek. ATmega ma na to za mało pamięci, bo raz, próbki przechowywane są jako szesnastobitowe, a dwa - nie starczyło by pamięci na inne rzeczy.
Stąd rozwiązanie takie, żeby zrobić dwa kanały i z jednego próbkować sygnały z pełną częstotliwością 32kHz, a z drugiego z częstotliwością 4kHz. Dla drugiego kanału trzeba oczywiście ograniczyć pasmo dość stromym filtrem. W pierwszym kanale też potrzebne jest oczywiście jakieś ograniczenie, ale juz nie tak "drastyczne" bo z natury muzyka nie zawiera zbyt dużo dźwięków o częstotliwościach powyżej 16kHz, a odrobina aliasingu nie ma większego znaczenia, to tylko wizualizacja, a nie pomiar. Drugi powód - przetwarzanie (FFT) dwóch buforów z próbkami trwa krócej niż jednego o rozmiarze dwa razy większym. Oczywiście takie podejście ma też swoje wady.
Brak podłączonej lini CLK skutkuje niedziałaniem układu.
Schemat części analogowej jest niekompletny, na etapie rysowania tego jeszcze nie wiedziałem, jak taktowany będzie filtr. MAX29x wyposażone są w wewnętrzny generator. Można je taktować sygnałem z zewnątrz, albo między CLK i masę podłączyc kondensator (wzór na częstotliwość w nocie). W układzie prototypowym jest to jeszcze inaczej zrobione, tam są dwa filtry, zasilanie symetryczne, MAXy pracują taktowane generatorem wewnętrznym. Druga opcja taktowania, którą rozważałem to użycie wyjścia timera procesora.
Dzięki za wyjaśnienia. Twoje wcześniejsze posty i ten w tym temacie bardzo mi pomogły.
Rozumiem, że w projekcie Chana było gorsze rozwiązanie, które pochłaniało całą pamięć Atmegi8. No to faktycznie lepiej to rozdzielić, chyba pomyślę nad tym, ale muszę jeszcze zrozumieć działanie tego filtra max29x.
W jaki sposób otrzymałeś konfigurację tego MAXa na częstotliwość 16KHz i 4KHz? Nie bardzo mogę to zrozumieć. Z początku myślałem, że to całe pasmo do 50KHz jest podawane na wyjście. Później że można je zmienić taktem, gdzie przełączają się pojemności. Ale skoro masz dwie częstotliwości z jednego układu przy stałym taktowaniu to o czym myślałem jest bez sensu.
Jak ustawia się te częstotliwości odcięcia, co ma na nią wpływ?
Wydaje mi się, że w Twoim projekcie można było zastosować max293 (przepuszcza do 25KHz) bo masz maksymalną częstotliwość 16MHz, czy to prawda?
Pytam bo też chcę tak zrobić a mam tylko ten układzik.
Rozumiem, że w projekcie Chana było gorsze rozwiązanie, które pochłaniało całą pamięć Atmegi8. No to faktycznie lepiej to rozdzielić, chyba pomyślę nad tym, ale muszę jeszcze zrozumieć działanie tego filtra max29x.
Wcale nie gorsze, tylko inne. Oba mają swoje zalety i wady, a to że zużywa całą pamięć, to w niczym nie przeszkadza, bo to co nie będzie zużyte będzie się zwyczajnie marnowało.
Podział pasma na dwie części daje jak na razie taki efekt, że układ potrafi czasem "zgubić" jakiś krótki dźwięk o wysokiej częstotliwości, który jest wyraźnie słyszalny. Przyczyną tego jest duży czas akwizycji w kanale niskich częstotliwości (32ms).
Myrek1 wrote:
W jaki sposób otrzymałeś konfigurację tego MAXa na częstotliwość 16KHz i 4KHz? Nie bardzo mogę to zrozumieć. Z początku myślałem, że to całe pasmo do 50KHz jest podawane na wyjście. Później że można je zmienić taktem, gdzie przełączają się pojemności. Ale skoro masz dwie częstotliwości z jednego układu przy stałym taktowaniu to o czym myślałem jest bez sensu.
Jak ustawia się te częstotliwości odcięcia, co ma na nią wpływ?
Częstotliwość odcięcia filtra ustala się częstotliwością taktowania, która dla MAX297 jest 50 razy większa od częstotliwości odcięcia, a dla pozostałych MAX29x 100 razy większa.
Dla 16kHz kondensator 25pF. Z obliczeń wychodzi większy (41.7pF), ale do tego dochodzą jeszcze pojemności wewnętrzne, indukcyjności ścieżek i końcówek oraz wszelkiej maści rozrzuty produkcyjne. Stanęło na tym, że jest 25pF, wartość dobrana eksperymentalnie i niekoniecznie powtarzalna. To już jest bardzo blisko skrajnych wartości częstotliwości taktowania i chyba nie bez powodu nie ma dla tak małych wartości pojemności stosownego wykresu w nocie katalogowej. Przy tych częstotliwościach raczej lepiej by było, gdyby układ był taktowany zewnętrznym generatorem.
Dla 2kHz (4kHz to częstotliwość próbkowania) chyba dałem taki, jak wyszedł ze wzoru i chyba nie trzeba było poprawiać, ale nie wiem, bo potrzebowałem układ do czegoś innego i tamten kondensator zmieniłem na inny.
Z jednego układu nie ma dwóch częstotliwości, albo inaczej, filtrowany sygnał trafia tu tylko na jedno wejście. Docelowo w analizatorze będzie tak, że na wejściu znajdzie się filtr dolnoprzepustowy w okolicy 16kHz (prawdopodobnie na wbudowanym w MAX297 wzmacniaczu) i z niego sygnał podawany będzie bezpośrednio na jedno z wejść przetwornika oraz na wejście filtra i dopiero z wyjścia filtra sygnał "okrojony" z wyższych częstotliwości trafi na drugie wejście ADC.
W układzie prototypowym zrobione to było tak, że były dwa układy MAX297, jedne dla 2kHz, drugi dla 16kHz, ale to tylko dlatego, że miałem gotową płytkę z zamontowanymi dwoma filtrami.
Chyba lepszą opcją będzie taktowanie tego z timera w procesorze, bo nie trzeba się bawić w dobór kondensatora na wejściu, a i potem w razie potrzeby w banalnie prosty sposób częstotliwość można zmienić. No i będzie o jeden element i dwa otwory mniej na płytce ;].
Myrek1 wrote:
Wydaje mi się, że w Twoim projekcie można było zastosować max293 (przepuszcza do 25KHz) bo masz maksymalną częstotliwość 16MHz, czy to prawda?
Chodziło Ci o 16kHz?
Tak, można zastosować MAX293. Jeszcze lepiej w roli filtra antyaliasingowego sprawdzi się MAX294 (bardziej strome opadanie charakterystyki). Użyłem MAX297, bo takie miałem.
Tak przy okazji, to żeby zlikwidować aliasing, pasmo powinno być ograniczone trochę bardziej niż połowa częstotliwości próbkowania. Dla MAX297 i MAX293 pasmo zaporowe zaczyna się od 1.5 * częstotliwość charakterystyczna filtra, a dla MAX294 współczynnik ten wynosi 1.2.
Co do zasady działania, to jest to ździebko skomplikowane. Rzecz sprowadza się do tego, że kondensator przełączany między wejściem a wyjściem zachowuje się jak rezystor. Tak jak przez rezystor przy różnicy napięć pomiędzy wejściem a wyjściem będzie płynął prąd. Tylko że tu prąd ten popłynie porcjami, na przemian z wejścia do kondensatora i z kondensatora do wyjścia. Zasada jest mniej więcej ta sama, tylko że tu mamy do czynienia z systemem z czasem dyskretnym. O ile w systemach z czasem ciągłym prąd (właściwie to natężenie prądu) to pochodna z przepływającego ładunku elektrycznego po czasie (i = dq / dt), do w systemie z czasem dyskretnym mamy już do czynienia ze skończonymi przyrostami i i=Δq/Δt. Δq to różnica ładunku zgromadzonego w kondensatorze, czyli ilości ładunku, który pobrał i który oddał w ciągu jednego okresu, Δt to czas trwania jednego okresu. (oczywiście równanie i = dq / dt wciąż obowiązuje, ale nas interesują wartości uśrednione w czasie).
Ładunek zgromadzony w kondensatorze Q = C * U, C to pojemność, U to napięcie.
W kompletnym cyklu ładowania i rozładowania ładunek który przepłynie przez kondensator będzie równy: Δq = C * (U1 - U2), gdzie U1 i U2 to napięcia odpowiednio na wejściu i na wyjściu (dowód tego sobie darowałem, jest to po prostu różnica ładunku zgromadzonego przy napięciu U1 i przy napięciu U2).
Stąd mamy, że przez taki układ popłynie prąd:
i = C * (U1 - U2) / Δt.
Prawo Ohma: R = U / I.
Prąd mamy, napięcie mamy (U1 - U2), to wstawiamy:
R = (U1 - U2) / (C * (U1 - U2) / Δt)
Po uproszczeniu:
R = Δt / C
Skoro:
Δt = 1 / f
Gdzie f jest częstotliwościa przełączania
To:
R = 1 / (f * C)
Oczywiście jak by oglądać na oscyloskopie przebieg na wyjściu takiego "rezystora" to zobaczymy "sieczkę", bo tutaj ważny jest średni prąd jaki przez niego płynie w jednym okresie, a nie wartość chwilowa w danym momencie okresu.
Żeby można było cokolwiek z takim "rezystorem" zrobić napięcie wyjściowe trzeba by jakoś "wygładzić". Włączając na wyjście kondensator dostaje się prosty filtr RC, który można już do czegoś wykorzystać.
Ogromna zaleta jest taka, że wartość "rezystancji" możemy sobie zmieniać bez użycia elementów mechanicznych, co umożliwia realizację przestrajanych filtrów w układach scalonych.
Taki przykład z symulacji:
Schemat:
Przebiegi na wejściu, wyjściu i sygnał przełączający klucze (dla częstotliwości przełączania: zielony - 10kHz, niebieski - 50kHz, czerwony - 100kHz):
Pojedyncze przebiegi dla częstotliwości przełączania kolejno; 10kHz, 50kHz i 100kHz:
Dla porównania przebieg z takiego filtra przy częstotliwości przełączania 10kHz. Dla C=1nF mamy R = 1 / (10k * 1n) = 100k i rzeczywistego filtra RC
W układach scalonych z takich symulowanych rezystorów i rzeczywistych kondensatorów (lub układów powielania pojemności(!)) składa się rozmaite topologie filtrów aktywnych, takie same jak składa się ze wzmacniaczy operacyjnych, rezystorów i kondensatorów. Można też podejść inaczej, tak jak jest to zrobione w MAX29x i stworzyć analog drabinkowego filtra LC. Indukcyjność uzyskuje się z pojemności w układzie żyratora.
Układy powielania pojemności pozwalają na zmianę wartości pojemności przy pomocy rezystorów, które oczywiście wykonane są jako przełączana pojemność.
Dzięki temu uzyskuje się filtr, który składa się z elementów o parametrach "dopasowujących" się do żądanej częstotliwości.
Ja chce zrobić to na Atmedze128, która od razu będzie sterowała komputerem pokładowym do auta (temperatura, prędkość, obroty, LCD 240x128 ) i nie wiem czy da radę to wszystko upchać, może być mało RAMu. Jak myślisz? Da jeszcze radę zaimplementować analizator widma?
Czy może dodać jeszcze Atmegę8 tylko do analizatora i zrobić komunikację na TWI między nimi?
Taktownie chciałbym rozwiązać trochę w inny sposób bo timer z procka jest mi potrzebny. A z tego co piszesz, nie jest za dobre dodawanie kondensatora. Zrobił bym generator na kwarcu i bramkach, taki standardowy jak do uC.
Rozumiem, że dla 16KHz taktowanie max293 musi wynosić 160kHz, czy tak?
Ja chciałbym odwzorować analizator taki jak ma winamp. Przy czym ten w winampie ma chyba częstotliwości do 20KHz (czy 25KHz) i nigdy te paski się nie podnoszą bo mało jest dźwięków w tym paśmie. Pewnie dlatego u Ciebie jest 16MHz, myślę że to dobry pomysł i też tak zrobię. Poco mam mieć prawie cały czas wygaszony ostatni pasek.
Jeszcze pytanka co do konstrukcji tych filtrów maxima. Bardziej chodzi mi o wytłumaczenie co jak wprowadzić na złącza tych kostek. W dokumentacji brak jest schematu blokowego tego układu co bardzo utrudnia mi zrozumienie jego działania. Mianowicie mam tu na myśli wejście i wyjścia wbudowanego komparatora.
Czym różnią się wejścia komparatora i wejścia in? Pytam bo trochę to dziwnie wygląda na schemacie. Tzn sygnał podany jest na wejście OPT in i wychodzi na OPT out, gdzie już jest obcięta częstotliwość do 16KHz i idzie do ADC oraz do wejścia in. Na tym wejściu częstotliwość obcinana jest do 2KHz i idzie do drugiego wejścia ADC. I to mnie trochę dziwi.
Pisałeś że ten sygnał wychodzący z OPT out (komparatora) jest już przepuszczony przez filtr itp. To w takim razie do czego jest wejście in i out? Myślałem że to jest wejście i wyjście filtra 8 rzędu, a OPT in i out to po prostu złącza wbudowanego, niezależnego komparatora.
Właśnie tego nie rozumiem. Bo z tego wynika, że chcąc np. mieć tylko obcięcie na poziomie 16KHz wystarczy przepuścić do przez komparator, później do ADC i ominąć wejścia in i wyjście out.
Ogólnie nie wiem jaka jest zależność wejścia in i komparatora. To przez brak schematu blokowego.
Ja chce zrobić to na Atmedze128, która od razu będzie sterowała komputerem pokładowym do auta (temperatura, prędkość, obroty, LCD 240x128 ) i nie wiem czy da radę to wszystko upchać, może być mało RAMu. Jak myślisz? Da jeszcze radę zaimplementować analizator widma?
Upchnąć da radę, ale może być na prawdę trudno, trzeba będzie pogodzić kilka zadań pracujących równolegle. Pamięci starczy.
Myrek1 wrote:
Czy może dodać jeszcze Atmegę8 tylko do analizatora i zrobić komunikację na TWI między nimi?
Tak by było dużo prościej, ale TWI jest dość powolne, lepszy było by SPI, albo nawet USART.
Myrek1 wrote:
Taktownie chciałbym rozwiązać trochę w inny sposób bo timer z procka jest mi potrzebny
Wyjść timera masz kilka.
Myrek1 wrote:
A z tego co piszesz, nie jest za dobre dodawanie kondensatora. Zrobił bym generator na kwarcu i bramkach, taki standardowy jak do uC.
Rozumiem, że dla 16KHz taktowanie max293 musi wynosić 160kHz, czy tak?
Kondensator jest dobry, o ile chcesz mieć stałą częstotliwość odcięcia. Tylko trochę paprania jest z dobraniem właściwej pojemności.
Dla MAX293 i 16kHz częstotliwość sygnału zegarowego powinna wynosić 1.6MHz (100 razy większa).
Myrek1 wrote:
Jeszcze pytanka co do konstrukcji tych filtrów maxima. Bardziej chodzi mi o wytłumaczenie co jak wprowadzić na złącza tych kostek.
W obudowie układu znajduje się filtr i całkowicie niezależny od niego wzmacniacz operacyjny (nie komparator!).
Wzmacniacz operacyjny posiada trzy końcóweki - wejścia '+' i '-' oraz wyjście. Wewnątrz układu wejście '+' połączone jest z końcówką GND, wejście '-' i wyjście wyprowadzone są normalnie na zewnątrz ("OP IN -" i "OP OUT"). Taki układ połączeń narzuca użycie tego wzmacniacza w konfiguracji odwracającej.
Filtr z przełączanymi pojemnościami to zupełnie osobna sprawa, ma tylko wejście ("IN") i wyjście ("OUT"), no i zegar.
Wzmacniacz w układzie jest po to, żeby mozna było go użyć jako... wzmacniacza, lub dodatkowego filtra aktywnego poprawiającego parametry sygnału przetwarzanego przez filtr z przełączanymi pojemnościami, oczywiście mozna też wykorzystać go w zupełnie innym celu, wedle uznania.
W nocie katalogowej jest narysowana przykładowa konfiguracja dolnoprzepustowego filtra aktywnego drugiego rzędu zbudowanego na tym wzmacniaczu.
Filtr taki mozna wykorzystać dwojako, albo jako filtr antyaliasingowy na wejściu filtra z przełączanymi pojemnościami (jak już kol. dex wspomniał występuje tu efekt aliasingu, objaw jest taki, że jak na wejście podasz częstotliwość większą od częstotliwości z jaką przełączają siępojemności wewnątrz, to okaże się że sygnał ten przedostanie sie na wyjście, mimo że powinien zostać odfiltrowany). Można też użyć go do tłumienia przesłuchów sygnału zegarowego na wyjściu filtra z przełączanymi pojemnościami, ale sam wzmacniacz też wykazuje przesłuchy i moze okazać się, że skutecznośćtakiej filtracji będzie kiepska. Ogólnie to ta pierwsza konfiguracja jest bardziej użyteczna.
Pisałem już, że mój schemat części analogowej jest niekompletny. Gdyby na tym wbudowanym wzmacniaczu zbudować filtr aktywny na 16kHz, to było by tak piszesz. Czyli: Sygnał zer źródła trafia na wejście filtra aktywnego (na wzmacniaczu operacyjnym), z wyjścia tego filtra rozgałęzia się, jedna gałąź trafai do przetwornika A/C w procesorze (sygnał o pasmie ograniczonym do 16kHz), a druga do filtra z przełączanymi pojemnościami, który ogranicza pasmo jeszcze bardziej, bo do 2kHz, a sygnał o tak ograniczonym pasmie z wyjścia filtra trafia do drugiego wejścia przetwornika A/C. U nie nie ma filtra aktywnego, jest po prostu wtórnik, czyli "wzmacniacz" o wzmocnieniu 1.
Upchnąć da radę, ale może być na prawdę trudno, trzeba będzie pogodzić kilka zadań pracujących równolegle. Pamięci starczy.
No właśnie chodzi mi o szybkość, po w analizatorze przerwanie wywoływane jest dość szybko (do próbkowania) będzie to zakłócać działanie różnych peryferii, a jest ich trochę (termometry na 1-wire, zegar PCF, komunikacja z ECU w aucie itp).
Pomyśle jeszcze nad tym.
shg wrote:
Tak by było dużo prościej, ale TWI jest dość powolne, lepszy było by SPI, albo nawet USART.
No też tak można, nawet będzie lepiej przy użyciu USART, to kwestia do dalszego uzgodnienia
shg wrote:
Wyjść timera masz kilka.
No tak, ale timery używam do precyzyjnego odmierzania czasu, PWM itp. Więc może tak być, że mi ich braknie (są tylko cztery). A niechce mi się pisać rozbudowanych funkcji dodających czasy policzone w każdym przerwaniu timera itp. A koszt zrobienia dodatkowego generatora nie jest duży, jeszcze zobaczę.
shg wrote:
Kondensator jest dobry, o ile chcesz mieć stałą częstotliwość odcięcia. Tylko trochę paprania jest z dobraniem właściwej pojemności.
Dla MAX293 i 16kHz częstotliwość sygnału zegarowego powinna wynosić 1.6MHz (100 razy większa).
No tak, mała pomyłka (chyba raczej duża ). Chodziło mi o 1.6MHz.
Myrek1 wrote:
W obudowie układu znajduje się filtr i całkowicie niezależny od niego wzmacniacz operacyjny (nie komparator!).
No tak pomyliłem nazewnictwo. Komparator to całkiem co innego jak sama nazwa wskazuje (za dużo pije piwa )
Czyli jest tak jak myślałem, jest wzmacniacz pracujący jako odwracający z wyprowadzanymi końcówkami.
Czyli jak ten sygnał wchodzi do tego wzmacniacza to na wyjściu jest odfiltrowane 16KHz, ale bez użycia filtra eliptycznego. Po prostu można na nim zbudować filtr 2 rzędu Butterworta. I nie jest tu groźne zjawisko aliasingu, więc może iść bezpośrednio do uC. A przy niższych częstotliwościach (2KHz) stosuje się filtr eliptyczny 8 rzędu, więc sygnał 16KHz wprowadza się do IN i na wyjściu mamy odfiltrowane 2KHz bez wystąpienia aliasingu.
Więc chcąc zrobić tak jak napisałem użyję taktowania 200KHz (bo na wyjściu filtra będzie 2KHz).
Jeśli to co napisałem się zgadza to już bardzo dużo rozumiem i ładnie układa mi się to w sensowną całość.
A czy wykorzystując Atmegę8 tylko do analizatora, nie lepiej będzie zastosować próbkowania jednego sygnału i działać na tych zmiennych. Napisałeś, że nie starczy pamięci, ale u Elm Chana przy 128 próbkach (tak jak u Ciebie) wystarcza.
To mnie tylko nurtuje. Jakbym wiedział jak najlepiej zrobić to bym brał się już za zaprojektowanie toru analogowego (oczywiście z pomocą ).
Dzięki.
Czyli jak ten sygnał wchodzi do tego wzmacniacza to na wyjściu jest odfiltrowane 16KHz, ale bez użycia filtra eliptycznego. Po prostu można na nim zbudować filtr 2 rzędu Butterworta.
Dokładnie tak.
Myrek1 wrote:
I nie jest tu groźne zjawisko aliasingu, więc może iść bezpośrednio do uC.
filtr drugiego rzędu dość słabo będzie tłumił "przeszkadzające" częstotliwości, więc potencjalnie aliasing może zachodzić, ale na szczęście muzyka zawiera skłądowych o tych częstotliwościach bardzo niewiele i w praktyce taki filtr w zupełności wystarcza. Nawet jak coś przejdzie to i tak nic wielkiego się nie stanie. jak to się mówi, "strzelać się z tego nie będzie", po prostu troszkę podbije Ci prążki o najwyższych częstotliwościach, ale i tak pewnie nawet tego nie zauważysz, bo najprawdopodobniej razem ze składowymi powodującymi aliasing wystąpią składowe o częstotliwościach niższych, a amplitudzie dużo wyższej. W muzyce (nie mówię tu o przypadkach rzadkich i ekstremalnych typu Venetian Snares ;] ) jak i w dźwiękach naturalnych widmowa gęstość mocy odpowiada mniej więcej szumowi różowemu, tzn. opada z szybkością 10dB/dekadę, Inaczej mówiąc, im wyższa częstotliwość tym niższa amplituda.
Taki filtr na wejściu jest jeszcze przydatny ze względu na zjawisko aliasingu występujące w filtrze z przełączanymi pojemnościami, ale nie jest konieczny, bo tu aliasing wystąpi przy dużo większych częstotliwościach, raczej mógł by być spowodowany obecnością "śmieci" w sygnale, do tego nawet prosty filtr RC wystarczy.
Myrek1 wrote:
A czy wykorzystując Atmegę8 tylko do analizatora, nie lepiej będzie zastosować próbkowania jednego sygnału i działać na tych zmiennych. Napisałeś, że nie starczy pamięci, ale u Elm Chana przy 128 próbkach (tak jak u Ciebie) wystarcza.
To mnie tylko nurtuje. Jakbym wiedział jak najlepiej zrobić to bym brał się już za zaprojektowanie toru analogowego (oczywiście z pomocą ).
Dzięki.
U niego jest liniowa skala częstotliwości, jeżeli to Cię zadowala, to w zupełności wystarczy jeden kanał, a filtr na MAX29x można sobie wówczas darować.
Dzięki krótszemu czasowi akwizycji widmo będzie odświeżane dużo szybciej, co jest bardzo pożądane (lepszy efekt wizualny). Wadą takiego rozwiązania jest mała rozdzielczość w zakresie niskich częstotliwości, a w muzyce tam "dzieje się" najwięcej.
Z liniową skalą częstotliwości i wyświetlaczem graficznym odpada Ci też konieczność "składania" prążków, możesz ot tak po prostu całe widmo "wrzucić" na wyświetlacz.
W Winampie (chyba, przynajmniej w <=2.9x) i Foobarze2000 jest właśnie liniowa skala częstotliwości na analizatorze.
Z 4kB RAMu mozesz zastosować też większy rozmiar transformaty, zwiększysz tym samym rozdzielczość. Przy 256 punktach i próbkowaniu 16kHz dostaniesz rozdzielczość 62.5Hz, zupełnie przyzwoicie. Możesz nawet zrobić z 512 punktów, nie wiem, czyja to procedura, nie chciało mi się zgłębiać, szukałem tylko wyników, w każdym razie prawie 30 odświeżeń na sekundę da się zrobić, a to oznacza prawie liczenie w czasie rzeczywistym:
http://www.mikrocontroller.net/topic/27001 (tabelka gdzieś w okolicach początku)
Zrobię to na 2 częstotliwości, tak jak Ty. To nie zaszkodzi. A czy skala będzie logarytmiczna czy liniowa zdecyduje pisząc program, może zrobię taką i taką.
Chyba, że zrobię tak, że przy wyborze logarytmicznej skali (np. w menu) próbkowanie będzie szło z 2 kanałów, a przy liniowej z jednego. Wtedy pasuje mieć 2 filtry, choć piszesz że przy liniowej można zrezygnować z maxa. Czy na pewno? W projekcie Elm Chana jednak jest, więc musi polepszać efekt końcowy.
Zrobię to osobno na Atmedze8, jakoś popłaczę oba procki. Tyle, że ona ma 1kB ramu, czyli starczy tego tylko na transformatę 128 punktów, czy tak? Ile trzeba ramu na 256 i 512? W cenie do 10zł chyba niema innego procka z większą ilością RAMu, będzie to musiało wystarczyć.
Chyba, że zrobię tak, że przy wyborze logarytmicznej skali (np. w menu) próbkowanie będzie szło z 2 kanałów, a przy liniowej z jednego.
Całkiem dobry pomysł.
Myrek1 wrote:
Wtedy pasuje mieć 2 filtry, choć piszesz że przy liniowej można zrezygnować z maxa. Czy na pewno? W projekcie Elm Chana jednak jest, więc musi polepszać efekt końcowy.
Dobrze by było, żeby w ogóle jakiś filtr był. Myślę, że w projekcie Chana znalazł się taki a nie inny, bo raz, nadaje się wręcz idealnie, a dwa, aplikacja jest banalnie prosta (skonstruowanie i uruchomienie filtra aktywnego ósmego rzędu samemu było by dość kosztowne / kłopotliwe / pracochłonne). Jeżeli będziesz robił dwie skale przełączane, to MAX może pracować na stałej częstotliwości (2kHz), a dla skali liniowej próbki zbierać z kanału o szerokości pasma 16kHz. Filtr aktywny drugiego rzędu powinien tam w zupełności wystarczyć. Na pewno nie będzie dużej różnicy w stosunku do tego, co dostał byś, gdybyś do filtrowania w tym pasmie użył MAXa.
Układ można jeszcze bardziej uprościć i nie stosować filtra aktywnego, tylko taktować MAXa z procka. Wtedy częstotliwość odcięcia MAXa będzie można wybierać samemu, a żeby zminimalizować efekty aliasingu w filtrze z przełączanymi pojemnościami wystarczy jakiś prosty filtr RC pierwszego rzędu na wejściu. Jedno co ważne w takim rozwiązaniu, to żeby po zmianie częstotliwości odczeać 100 taktów zegara (lub 50 w wypadku MAX297) żeby odrzucić "przejściowy" sygnał. W realizacji praktycznej sprowadza się to do odrzucenia pierwszej próbki.
Myrek1 wrote:
Zrobię to osobno na Atmedze8, jakoś popłaczę oba procki. Tyle, że ona ma 1kB ramu, czyli starczy tego tylko na transformatę 128 punktów, czy tak? Ile trzeba ramu na 256 i 512? W cenie do 10zł chyba niema innego procka z większą ilością RAMu, będzie to musiało wystarczyć.
Na 128 próbek wystarczy bez problemu (przy próbkach szesnastobitowych). Na 256 szesnastobitowych też da się zrobić z 1kB, tylko potrzebował byś implementacji FFT in-place (taką obecnie męczę).
Na 512 próbek szesnastobitowych potrzeba już więcej niż 1kB (tyle zajmą same próbki).
Można zrobić 512 próbek ośmiobitowych (z transformatą in-place), ale troszkę już będzie tak mała precyzja przeszkadzać. Trzeba by odpowiednio dobrać kolejność operacji w FFT w celu minimalizacji błędów, w takim wypadku szkoda zachodu, lepiej użyć większego procka.
Witam.
Pisze dopiero teraz bo mam chwilkę czasu na dalsze rozmyślania i pisanie programu.
Więc tak jak pisałem, skala będzie wybierana, albo logarytmiczna albo liniowa.
Dla skali logarytmicznej chcę zrobić tak, że będą zbierane 2 próbki, jedna do częstotliwości 2KHz, druga do 16KHz czyli tka jak jest u Ciebie. Oczywiście odcięcie będzie realizowane przez timer. Chyba będzie trzeba zrobić to tak, że pobierana jest jedna próbka, odrzucamy ją, następuje zmiana ustawień timera (na odcięcie MAXa 16KHz) znowu pierwsza próbka (odrzucamy), bierzemy drugą i znowu zmiana ustawień timera (powrót na 2KHz). I tak w kółko.
Czy tak będzie dobrze? Trochę martwi mnie to ciągłe odrzucanie próbek, nie będzie z tym problemu? Może lepiej zrobić to na 2 filtry, czyli tak jak u Ciebie? Początkowo chciałem tak zrobić, ale nie poradzę sobie z dobraniem wartości elementów do zrobienia takiego filtra
Do skali liniowej wystarczy normalna praca na jednej częstotliwości odcięcia, tu nie będzie problemów.
Więc chyba do takiej realizacji wystarczy żywcem skopiować cały tor analogowy z projektu Chana?
Co tam dają kondensatory na wejściu i wyjściu (ten przy ADC)?
Zrobię to na Atmedze8 i oba procki połączę jakimś USARTem.
Trochę martwi mnie to ciągłe odrzucanie próbek, nie będzie z tym problemu?
Nie będzie. Można nawet (przynajmniej na początek) spróbować nie odrzucać, różnica będzie prawie niezauważalna, bo początkowe i końcowe próbki są dość znacznie tłumione przez okienkowanie.
Tak właściwie to obsługa dwóch wejść ADC jest bardziej skomplikowana, niż próbkowanie ciągle z jednego i zmiana częstotliwości taktowania filtra.
Myrek1 wrote:
Co tam dają kondensatory na wejściu i wyjściu (ten przy ADC)?
Nie wiem które, szczerze mówiąc, nie chce mi się zaglądać, ale będę zgadywał, że chodzi o te, które służą do separacji składowej stałej. Na przykład tak, że sygnał wejściowy nie ma składowej stałej, MAX zasilany z 5V pracuje ze składową stałą 2.5V, a ADC z napięciem referencyjnym 2.5V i składową stałą 1.25V. Wszystko to po to, żeby można było przetwarzać zarówno napięcia dodatnie, jak i ujemne. Składowe stałe są różne, żeby zapewnić pracę MAXa i przetwornika A/C w optymalnych warunkach (największy możliwy zakres dynamiki).
Przeanalizowałem cały program i mam kilka pytań, ale najpierw część hardwerowa.
1. U Chana jest coś takiego, czy będzie to odpowiednie w moim wypadku?
Próbowałem coś zmienić, ale po pewnym czasie uznałem, że się na tym nie znam i chyba taka analogowa sekcja będzie ok i dla skali logarytmicznej i liniowej. Dlatego, że i tak MAXa będę taktował sygnałem z procka. I tu chodziło mi o te dwa kondensatory na wejściu i wyjściu. Czy w tym przypadku przejście sygnału przez wzmacniacz operacyjny działa jak filtr antyaliazingowy?
#define BARS_SPEED 24 /* bars falling down speed = BARS_FALL * 6 dB/s */
#define PEAK_DELAY 200 /* time after wich peaks start to fall down = PEAK_DELAY * 4.096ms*/
#define PEAK_SPEED 6 /* peaks falling down speed = PEAK_FALL * 6 dB/s */
#define F_DISPLAY_INT (F_CPU/64/256) /* display (timer0) interrupt frequency */
#define DIV_BFALL (F_DISPLAY_INT/BARS_SPEED)
#define DIV_PFALL (F_DISPLAY_INT/PEAK_SPEED)
#define DIV_PDEL (F_DISPLAY_INT/200)
volatile uint16_t bars[N_BANDS]; /* packed linear spectrum value */
volatile uint8_t bands[N_BANDS]; /* bands bar height */
volatile uint8_t peaks[N_BANDS]; /* peaks position */
volatile uint8_t peak_delay[N_BANDS]; /* peaks fall down delay */
volatile uint8_t leds[N_BANDS]; /* LED matrix image */
Z tego co obliczyłem to to przerwanie generowane jest co 1ms, co ono robi? Czy tylko podtrzymuje prążki w wartości szczytowej i powoduje powolne opadanie? Jeśli tak to czy można w ogóle zrezygnować z tego przerwania i tych deklaracji jak nie chce się mieć tej funkcji?
3. W funkcji main() masz zamianę wejścia przetwornika:
/* wait until buffer is filled completly */
while(flags & _BV(BUFF_FILL)) {};
Wg mnie coś tu jest nie tak. Bo próbkowanie wykonywane jest w przerwaniu. Powyższa funkcja czeka do zapełnienia bufora, a że zamiana kanałów jest niżej to cały czas następuje czytanie z tego samego kanału.
Wg mnie ta zamiana kanałów powinna być w przerwaniu a nie w main() po funkcji, która nic nie robi do czasu zebrania próbek.
Pewnie źle myślę, ale dlaczego?
4. Jak chcę skalę liniową to rozumiem, że nie muszą tablicy spectrum[] traktować funkcją pack_spectrum() i podobnymi?
Czy mając obliczoną tablicę spectrum[] po funkcji fft_output(); wystarczy "przelecieć" ją logarytmowaniem wspomnianym w przytoczonym na początku temacie?
Dodam, że mam wyświetlacz 240x128 pix, a chcę wyświetlać na powierzchni ok 128x64, czyli efektywnie gdzieś 120x60pix.
WIELKIE DZIĘKI za wyjaśnienia. Bardzo mi pomagają i wielę się uczę.
Oby takich ludzi jak Ty więcej na elektrodzie
1. U Chana jest coś takiego, czy będzie to odpowiednie w moim wypadku?
Będzie dobre.
Myrek1 wrote:
Czy w tym przypadku przejście sygnału przez wzmacniacz operacyjny działa jak filtr antyaliazingowy?
Dobre pytanie. Idealny wzmacniacz operacyjny nie będzie działał jak filtr. Rzeczywiste wzmacniacze natomiast mają to do siebie, że ich charakterystyka częstotliwościowa zaczyna opadać już od dość małej częstotliwości (rzędu kHz) i w pewnym punkcie osiąga 0dB (pasmo przenoszenia wzmacniacza), powyżej tej częstotliwości wzmacniacz jest już tłumikiem. W tym konkretnym przypadku częstotliwość ta leży jednak dużo powyżej połowy częstotliwości taktowania filtra (czyli tej, przy której zaczyna się aliasing), a to i tak jeszcze za mało, bo filtr antyaliasingowy powinien wykazywać tłumienie dość znaczne, najlepiej takie, żeby wszystkie sygnały leżące powyżej tej częstotliwości miały amplitudę poniżej poziomu szumów. Teoretycznie więc, sam wzmacniacz operacyjny nie jest wystarczający. Nie znaczy to jednak że taki filtr jest absolutną koniecznością. Nawet przy częstotliwości charakterystycznej filtra 2kHz MAX293 i 294 wymaga taktowania 200kHz, co oznacza, że aliasing będzie miał miejsce dla sygnałów na wejściu o częstotliwości powyżej 100kHz. Takich częstotliwości w sygnale audio raczej nie ma, chyba że coś nie działa tak jak powinno (np. wzmacniacz się wzbudza, albo jest niedostateczna filtracja na wyjściu DACa w karcie dźwiękowej / CD / czymkolwiek).
Myrek1 wrote:
2. W Twoim programie jest coś takiego:
(...)
Do tego:
(...)
Z tego co obliczyłem to to przerwanie generowane jest co 1ms, co ono robi? Czy tylko podtrzymuje prążki w wartości szczytowej i powoduje powolne opadanie? Jeśli tak to czy można w ogóle zrezygnować z tego przerwania i tych deklaracji jak nie chce się mieć tej funkcji?
Poza obsługą prążków na końcu przerwania znajduje się kod sterujący matrycą LED. Jeżeli tego nie potrzebujesz, to usuń.
Myrek1 wrote:
3. W funkcji main() masz zamianę wejścia przetwornika:
(...)
Wg mnie coś tu jest nie tak. Bo próbkowanie wykonywane jest w przerwaniu. Powyższa funkcja czeka do zapełnienia bufora, a że zamiana kanałów jest niżej to cały czas następuje czytanie z tego samego kanału.
Wg mnie ta zamiana kanałów powinna być w przerwaniu a nie w main() po funkcji, która nic nie robi do czasu zebrania próbek.
Pewnie źle myślę, ale dlaczego?
Procedura przerwania, która zajmuje się próbkowaniem skonstruowana jest tak, że po zapełnieniu bufora przestaje próbkować (próbki są odczytywane z ADC, ale są ignorowane):
/* restart buffer filling with other sample rate */
flags |= (uint8_t) _BV(BUFF_FILL);
Ustawiana jest flaga, która sygnalizuje procedurze w przerwaniu, że ta ma zacząć wypełniać bufor.
Tak to wygląda:
1. Wypełnianie bufora A w przerwaniach dopóki ten nie będzie pełny.
2. main() czeka na zapełnienie bufora.
3. przełączenie multipleksera na kanał B, procedura przerwania zaczyna próbkowanie z kanału B, ale próbki są ignorowane.
4. kopiowanie zawartości bufora A do bufora wejściowego FFT
5. Ustawienie flagi wypełniania bufora
6. procedura przerwania zaczyna wypełniać bufor próbkami z kanału B.
7. z kanału A liczona jest w tym czasie FFT.
8. Po policzeniu FFT pętla główna wraca na początek i czeka na zapełnienie bufora
Potem jak wyżej, tylko kanały odwrotnie.
Właściwie to nie do końca tak jest, bo w wypadku próbkowania z kanału o pasmie 16kHz jako pierwsze kończy się próbkowanie, a w wypadku próbkowania z kanału 2kHz jako pierwsze kończy się liczenie FFT. Chyba, w każdym razie próbkowanie z kanału 2kHz trwa dużo dłużej i w zasadzie jest wyznacznikiem szybkości działania analizatora. Z tej przyczyny widmo / obraz dla matrycy składany jest podczas próbkowania z kanału 2kHz, żeby procesor nie czekał bezproduktywnie na koniec próbkowania.
Myrek1 wrote:
4. Jak chcę skalę liniową to rozumiem, że nie muszą tablicy spectrum[] traktować funkcją pack_spectrum() i podobnymi?
Tak.
Myrek1 wrote:
Czy mając obliczoną tablicę spectrum[] po funkcji fft_output(); wystarczy "przelecieć" ją logarytmowaniem wspomnianym w przytoczonym na początku temacie?
Aha, czyli jak przełączy się na kanał B to dopiero co ósma próbka.
Czyli rozumiem, że przerwanie z timera 0 mogę olać. Zostaje mi tylko potraktowanie obliczonej tablicy logarytmem i wywalenie wszystkiego na LCD.
Jeszcze małe pytanko. Jakie mają być kondensatory w torze analogowym (te 1uF? Elektrolity czy może MKT? Jeśli elektrolity to jak powinna wyglądać ich polaryzacja przy wejściu i wyjściu MAXa?
EDIT:
Jeszcze to logarytmowanie. Zakładam, że słupek ma 64 piksele (wartość maksymalna).
Myrek1 wrote:
Czy mając obliczoną tablicę spectrum[] po funkcji fft_output(); wystarczy "przelecieć" ją logarytmowaniem wspomnianym w przytoczonym na początku temacie?
-Wystarczy.
Czy na pewno? Teraz doszedłem do tego, że chyba nie trzeba nic logarytmować. A więc:
Z tego co kiedyś napisałeś rozumiem, że w tablicy spectrum[] dostajemy wartości amplitudy (wysokości słupka) dla kolejnych 64 częstotliwości. Te kolejne amplitudy odpowiadają skoku od 0Hz do 32KHz, czyli jak jest ich 64 to skok pomiędzy wartościami wynosi 500Hz.
Czyli ostatecznie pierwszy element tablicy spectrum[] to wartość prążka dla 0Hz, druga wartość jest dla 500Hz, trzecia dla 1KHz itd, ostatnia 64 wartość jest dla 32KHz. I coś mi się tu nie zgadza. Ja bym powiedział, że prążki są od siebie oddzielone o 250Hz (16KHz/64)? Jeśli nie to czy użytecznych amplitud jest tylko 64/2 = 32 (do 16KHz)?
Zakładamy, że mam rację jeśli chodzi o organizację tablicy spectrum[]. Te amplitudy są w zakresie od 0 do 35314 (kolega @slawek55 to sprawdził). Więc 0 to 0, a 35314 to u mnie 64piksele na LCD.
Pisałem wcześniej o logarytmowaniu. Ale chyba jak chcę skalę liniową skalę to nie muszę tego robić, czy tak? Czy wystarczy tylko odpowiednie wartości z tablicy spectrum[] podzielić przez 551 (maks/maks, czyli 35314/64 = ~551) i wyświetlić dla danej częstotliwości (będzie wiadomo po pozycji wartości amplitudy w tablicy, czyli po spectrum[x] - częstotliwość = x*500, czy 250, zależy co ile są amplitudy) otrzymany wynik w postaci gotowego słupka?
Pytam bo na razie chcę zrozumieć to dla zwykłej skali. Jak to wykonam, pomyślę o skali logarytmicznej, w której na tablicy spectrum już trzeba przeprowadzić logarytmowanie.
Aha, jeszcze czysto techniczne pytanko. Jak dołączyć plik ffft.s do projektu? Rozumiem, że są tam funkcje liczące fft: fft_* w asm. Ale nie wiem jak to dołączyć, czy trzeba dopisać coś ręcznie w makefile?
Teraz nie mam tego dołączonego a program dobrze się kompiluje, dziwne. Dodam, że projekt tworzyłem sam, nie jest to Twój gotowy, więc na bank ffft.s nie jest nigdzie dołączony. Dlaczego dobrze się kompiluje mimo braku funkcji? Czy to dzięki wpisaniu prototypów tych funkcji?
Jeszcze małe pytanko. Jakie mają być kondensatory w torze analogowym (te 1uF? Elektrolity czy może MKT? Jeśli elektrolity to jak powinna wyglądać ich polaryzacja przy wejściu i wyjściu MAXa?
MKT w zasadzie są lepsze, ale praktycznie bez znaczenia większego. Nawet ceramiki SMD mogą być. Elektrolity plusem do większego potencjału, czyli wejście sygnału: minus, wejście MAX (wzmacniacza): +. Między MAXem a ATmegą bez różnicy, bo po obu stronach kondensatora jest mniej więcej ten sam potencjał (1/2 Vcc), a elektrolity do ~2V mogą pracować z odwrotną polaryzacją nie tracąc swoich właściwości i nie wybuchając.
Myrek1 wrote:
Jeszcze to logarytmowanie. Zakładam, że słupek ma 64 piksele (wartość maksymalna).
Myrek1 wrote:
Czy mając obliczoną tablicę spectrum[] po funkcji fft_output(); wystarczy "przelecieć" ją logarytmowaniem wspomnianym w przytoczonym na początku temacie?
-Wystarczy.
Czy na pewno? Teraz doszedłem do tego, że chyba nie trzeba nic logarytmować. A więc:
Z tego co kiedyś napisałeś rozumiem, że w tablicy spectrum[] dostajemy wartości amplitudy (wysokości słupka) dla kolejnych 64 częstotliwości. Te kolejne amplitudy odpowiadają skoku od 0Hz do 32KHz, czyli jak jest ich 64 to skok pomiędzy wartościami wynosi 500Hz.
Czyli ostatecznie pierwszy element tablicy spectrum[] to wartość prążka dla 0Hz, druga wartość jest dla 500Hz, trzecia dla 1KHz itd, ostatnia 64 wartość jest dla 32KHz. I coś mi się tu nie zgadza. Ja bym powiedział, że prążki są od siebie oddzielone o 250Hz (16KHz/64)? Jeśli nie to czy użytecznych amplitud jest tylko 64/2 = 32 (do 16KHz)?
Bo tak jest, różnica częstotliwości między prążkami wynosi 250Hz. Ma być do 16kHz.
Myrek1 wrote:
Zakładamy, że mam rację jeśli chodzi o organizację tablicy spectrum[]. Te amplitudy są w zakresie od 0 do 35314 (kolega @slawek55 to sprawdził). Więc 0 to 0, a 35314 to u mnie 64piksele na LCD.
Pisałem wcześniej o logarytmowaniu. Ale chyba jak chcę skalę liniową skalę to nie muszę tego robić, czy tak? Czy wystarczy tylko odpowiednie wartości z tablicy spectrum[] podzielić przez 551 (maks/maks, czyli 35314/64 = ~551) i wyświetlić dla danej częstotliwości (będzie wiadomo po pozycji wartości amplitudy w tablicy, czyli po spectrum[x] - częstotliwość = x*500, czy 250, zależy co ile są amplitudy) otrzymany wynik w postaci gotowego słupka?
Jak zrobisz tak, to dostaniesz liniową skalę amplitudy, Raczej nie będzie to wyglądało zbyt dobrze, ale sprawdź, bo jak by nie było, to możesz wyświetlić aż 64 poziomy, co daje ~36dB dynamiki. U mnie ze skalą logarytmiczną i zakresem dynamiki ~24dB wyglądało już nawet przyzwoicie.
Myrek1 wrote:
Aha, jeszcze czysto techniczne pytanko. Jak dołączyć plik ffft.s do projektu? Rozumiem, że są tam funkcje liczące fft: fft_* w asm. Ale nie wiem jak to dołączyć, czy trzeba dopisać coś ręcznie w makefile?
To zależy w jakim sensie. W Programmer's Notepad klikasz prawym klawiszem na projekcie w oknie Projects i z menu wybierasz Add Files. Żeby plik widziany był przez kompilator, to trzeba dopisać go do Makefile ręcznie. W standardowym Makefile dostarczanym z WinAVR jest od tego linia:
Tam wpisujesz oddzielone spacjami nazwy plików w asemblerze. Tak przy okazji, to nazwy tych plików powinny kończyć się wielką literą 'S', a nie małą. Windowsowi wszystko jedno, ale chyba make, albo gcc już je rozróżnia.
Myrek1 wrote:
Teraz nie mam tego dołączonego a program dobrze się kompiluje, dziwne. Dodam, że projekt tworzyłem sam, nie jest to Twój gotowy, więc na bank ffft.s nie jest nigdzie dołączony. Dlaczego dobrze się kompiluje mimo braku funkcji? Czy to dzięki wpisaniu prototypów tych funkcji?
Nie mam pojęcia. Ale jeżeli nigdzie nie wywołujesz tej funkcji w programie, to na pewno nie będzie błędu. Jeżeli jej używasz, to kompilacja powinna wyłożyć się na etapie linkowania, kiedy linker będzie "wiedział" w jaki sposób ma połączyć moduły i wywołać tą funkcję, ale nie znajdzie samej funkcji. Bez zdefiniowanej funkcji, ale z prototypem można kompilować do plików ".o".
Może w plikach "zalega" Ci plik ffft.o po poprzedniej kompilacji i linker łączy go z pozostałymi plikami. Jeżeli tak, to "make clean" powinno całą zabawę popsuć :>.
Na razie dzięki, teraz pozostaje wszystko polutować i zaprogramować.
Małe pytanko co do napięć referencyjnych przetwornika. Czy na Twoim schemacie jest wszystko ok? Bo chciałbym zrobić tak samo. Co to za element VR1? I czy rezystor R24 ma poprawną wartość?
Dzięki.
Zasilanie części analogowej jest OK. VR1 to TL431. R24 ma poprawną wartość (prąd ok. 10mA). Dławik nie powinien mieć zbyt dużej indukcyjności. Duża rezystancja szeregowa dławika w niczym nie przeszkadza, a nawet pomaga. W momencie włączenia napięcia mała rezystancja szeregowa może być przyczyną oscylacji o amplitudzie przekraczającej dopuszczalne napięcie na AVcc, chociaż teoretycznie wbudowane zabezpieczenie ESD (dioda do Vcc) powinno sobie z tym poradzić.
if(flags & _BV(RATE_LOW)) {
flags &= (uint8_t) (~(_BV(RATE_LOW)));
//ADMUX = ADMUX_SH;
// przelaczenie timera na 16KHz(timer na 1,6MHz)
TCCR2 |= _BV(WGM21) | _BV(COM20) | _BV(CS20); // usatawienie jako CTC, preskaler na 0
OCR2=0x0A;
} else {
flags |= (uint8_t) _BV(RATE_LOW);
//ADMUX = ADMUX_SL;
//przelaczenie timera na 2KHz (timer na 200KHz)
TCCR2 |= _BV(WGM21) | _BV(COM20) | _BV(CS21); // usatawienie jako CTC, preskaler na 8
OCR2=0x0A;
}
Przy czym ADMUH_SL=ADMUX_SH - ustawione na odpowiedni kanał wspólny. takt podłączony jest do końcówki OC2/OC1C, czyli taktowanie następuje z Timera2
Czy wystarczy takie zadeklarowanie taktu MAXa? Ten kodzik jest w funkcji main.
Jakie powinno być napięcie na końcówce Aref przetwornika? Ja mam coś ok 0.6V. Jak podłączyłem mp3 do układu to na wejściu AD1 przetwornika napięcie oscyluje w ok 0,1V (mierze jako zmienne), przy stałym wskazanie jest ok 5V. Czy to dobrze? Można jakoś sprawdzić bez oscyloskopu działanie hardwerowe układu?
W pewnym momencie wyświetlam na LCD wartość LED[1] (pierwszej kolumny). Wartość ta zawsze ma 255, czyli źle. Nie wiem czy to wina kodu i tego mojego dopisania taktowania czy może wina sprzętu (zła część analogowa).
// przelaczenie timera na 16KHz(timer na 1,6MHz)
TCCR2 |= _BV(WGM21) | _BV(COM20) | _BV(CS20); // usatawienie jako CTC, preskaler na 0
OCR2=0x04;
Timer zlicza od 0 do OCR2 (włącznie z wartością OCR2), dlatego aby odliczył n cykli zegara trzeba do OCR2 wpisać wartość n - 1. Po odliczeniu do tej wartości stan na wyjściu jest przełączany, więc ilość wpisanych cykli zegara, to jest czas trwania półokresu, a nie pełnego okresu. Wobec tego, aby otrzymać okres równy n cykli, należy dwukrotnie odliczyć n/2 cykli, a zatem wartość, którą trzeba wpisać, to (n / 2) - 1 W nocie katalogowej jest wzór:
f = f_clk / (2 * N * (OCR2 + 1))
f_clk - częstotliwość zegara I/O
N - preskaler
//przelaczenie timera na 2KHz (timer na 200KHz)
TCCR2 |= _BV(WGM21) | _BV(COM20) | _BV(CS21); // usatawienie jako CTC, preskaler na 8
OCR2=0x04;
Jak wyżej.
Myrek1 wrote:
Jakie powinno być napięcie na końcówce Aref przetwornika? Ja mam coś ok 0.6V.
Za mało. coś jest nie tak. Nie wiem jakie masz źródło napięcia odniesienia, ale na pewno nie powinno to być 0.6V. Jeżeli korzystasz z wewnętrznego źródła, to końcówka ta powinna być odsprzęgnięta kondensatorem do masy. Wybór źródła napięcia odniesienia dokonuje się przez odpowiedni zapis do rejestru ADMUX. W wypadku źródła wewnętrznego napięcie powinno wynosić 2.56V, w wypadku wyboru napięcia zasilania ADC (AVCC) jako napięcie odniesienia, takie powinno być właśnie napięcie na końcówce AREF. W wypadku stosowania zewnętrznego źródła powinno być takie, jakie daje to źródło. Stabilizator równoległy na TL431 nie powinien mieć na wyjściu kondensatora, bo się będzie wzbudzał, w nocie tegoż jest wykres to obrazujący.
Podejrzewam, że nie zapisałeś odpowiedniej wartości do ADMUX.
Myrek1 wrote:
Jak podłączyłem mp3 do układu to na wejściu AD1 przetwornika napięcie oscyluje w ok 0,1V (mierze jako zmienne), przy stałym wskazanie jest ok 5V. Czy to dobrze? Można jakoś sprawdzić bez oscyloskopu działanie hardwerowe układu?
Troszkę mało, no ale takie odtwarzacze niekoniecznie muszą zapewniać typowy poziom napięcia wyjściowego ~1V. Żeby temu zaradzić, można wykorzystać wzmacniacz z MAX29x. Z tym stałym napięciem to nie za bardzo rozumiem. Składowa stała nie powinna raczej przedostawać się na wejście przetwornika.
Bez oscyloskopu może być ciężko. Multimetry (tanie) zazwyczaj poprawnie mierzą tylko sinus 50Hz. Chociaż w zasadzie oscyloskop potrzebny jest tylko, jeżeli coś nie działa, do samego uruchomienia konieczny nie jest.
Myrek1 wrote:
W pewnym momencie wyświetlam na LCD wartość LED[1] (pierwszej kolumny). Wartość ta zawsze ma 255, czyli źle. Nie wiem czy to wina kodu i tego mojego dopisania taktowania czy może wina sprzętu (zła część analogowa).
Ciężko stwierdzić. No ale były błędy w kodzie, popraw i sprawdź jeszcze raz.
Panowie mam pytanie banalne odnośnie MAX 293.
Czy wspomniany MAX w układzie audio analogowo-cyfrowym powinien mieć masę analogową czy cyfrową aby uniknąć zakłóceń? Dodam że oscylator LTC6900 do napędzania maxa będzie masowany do cyfrowej.
Pytam bo podobne filtry z seri LTC powinny mieć 2 masy do poprawnej pracy.