Friday 22 December 2017

Moving average filter in c code


Czy jest możliwe do wdrożenia średniej ruchomej w C bez potrzeby okna próbek Ive stwierdził, że można zoptymalizować nieco, wybierając rozmiar okna thats mocy dwóch, aby umożliwić przesunięcie bitów, zamiast dzielić, ale nie potrzebują bufor byłby miły. Czy jest jakiś sposób na wyrażenie nowego wyniku średniej ruchomej tylko w zależności od starego wyniku i nowej próbki Zdefiniuj przykładową średnią ruchu, w oknie 4 próbek: Dodać nową próbkę e: Średnia ruchoma może być realizowana rekurencyjnie , ale dokładne obliczanie średniej ruchomej należy pamiętać o najstarszej próbce wejściowej w sumie (tj. w przykładzie). Dla średniej długości ruchu N, którą obliczysz: gdzie yn jest sygnałem wyjściowym, a xn jest sygnałem wejściowym. Równanie (1) można zapisywać rekurencyjnie tak, więc zawsze trzeba pamiętać o próbce xn-N w celu obliczenia (2). Jak wskazał Conrad Turner, zamiast tego można użyć okna wykładniczego (nieskończenie długi), co pozwala na obliczenie wyjścia tylko z poprzedniego wyjścia i bieżącego wejścia: ale to nie jest standardowa (nieważona) średnia ruchoma, ale wykładnicza średniej ważonej średniej ruchomej, gdzie próbki w przeszłości otrzymują mniejszą masę, ale (co najmniej teoretycznie) nigdy się nie zapomni (ciężary po prostu maleją i mniejsze w przypadku próbek w przeszłości). Zaimplementowałem średnią ruchomą bez pojedynczej pamięci pozycji dla programu śledzenia GPS, który napisałem. Zacznij od 1 próbki i podzielić przez 1, aby uzyskać aktualną średnią. Następnie dodaj anody i podziel się przez 2 na obecną średnią. To trwa, aż dojdę do średniej. Za każdym razem dodaję nową próbkę do średniej i usuń tę średnią ze wszystkich. Nie jestem matematykiem, ale wydawało mi się to dobrym sposobem na to. Pomyślałem, że zamieniłby żołądek prawdziwego faceta matematyki, ale okazuje się, że jest to jeden ze sposobów na to. I to działa dobrze. Pamiętaj, że im większa długość, tym wolniej idzie za tym, co chcesz podążać. To może nie mieć znaczenia przez większość czasu, ale jeśli śledzisz satelity, jeśli jesteś wolny, szlak może być daleko od rzeczywistej pozycji i będzie wyglądał źle. Możesz mieć przerwę między siadami a końcowymi kropkami. Wybrałem długość 15 aktualizowanych 6 razy na minutę, aby uzyskać odpowiednie wygładzenie i nie za bardzo oddalać od rzeczywistej pozycji siedzącej z wygładzonymi punktami trasy. odpowiedź 16 listopada 16 w 23:03 zainicjalizować 0, count0 (za każdym razem widać nową wartość) Następnie jeden wpis (scanf), jeden add totalnewValue, jeden przyrost (liczba), jedna średnia przecina (totalcount) To byłaby średnia ruchoma wszystkie wejścia Aby obliczyć średnią z ostatnich ostatnich 4 wejść, trzeba było wprowadzić 4 zmienne wejściowe, kopiowanie każdego wejścia do starszej zmiennej wejściowej, a następnie obliczenie nowej średniej ruchomej jako sumy 4 zmiennych wejściowych, podzielonych przez 4 (przesunięcie w prawo2 dobrze, jeśli wszystkie dane wejściowe były pozytywne, aby obliczyć średnią obliczoną 15 lutego 15 w 4:06 To rzeczywiście obliczy całkowitą średnią, a nie średnią ruchoma. Jak liczyć się większy wpływ każdej nowej próbki wejściowej staje się znikomy mały ndash Hilmar Feb 3 15 at 13:53 Twoja odpowiedź 2017 Stack Exchange, Inc Wiem, że to jest osiągalne z pobudzenia jak na: Ale naprawdę chciałbym uniknąć przyśpieszenia. Mam googled i nie znaleziono żadnych odpowiednich lub czytelnych przykładów. Zasadniczo chcę śledzić w ruchu średnia z ciągłego strumienia strumienia liczb zmiennoprzecinkowych przy użyciu najnowszych 1000 numerów jako przykładu danych. Jaki jest najłatwiejszy sposób na to, eksperymentowałem z użyciem okrągłej tablicy, wykładniczej średniej ruchomej i bardziej prostej średniej ruchomej i stwierdziła, że ​​wyniki okrągłej tablicy odpowiadały moim potrzebom najlepiej. zapytał 12 czerwca 12 w 4:38 Jeśli Twoje potrzeby są proste, możesz spróbować użyć wykładniczej średniej ruchomej. Po prostu wprowadzasz zmienną akumulatora, a kod wygląda na każdą próbkę, kod aktualizuje akumulator o nową wartość. Wybierasz stałą wartość alfa, która wynosi od 0 do 1, i oblicz ją: Wystarczy, że znajdziesz wartość alfa, w której efekt danej próbki trwa tylko około 1000 próbek. Hmm, nie jestem pewien, że to jest dla ciebie odpowiednie, teraz, że to tutaj. Problem polega na tym, że 1000 jest dość długie okno dla wykładniczej średniej ruchomej Im nie wiesz, że istnieje alfa, która rozprzestrzenia się średniej w ciągu ostatnich 1000 numerów, bez underflow w obliczaniu zmiennoprzecinkowych. Ale jeśli chcesz mieć mniejsze średnie, jak 30 liczb, jest to bardzo łatwy i szybki sposób na to. odpowiedziało cze 12 12 w 4:44 1 na Twoim stanowisku. Wyższa średnia ruchoma może pozwolić na zmienną alfa. Pozwala to na obliczanie średnich baz czasu (na przykład bajtów na sekundę). Jeśli czas od ostatniej aktualizacji akumulatora przekracza 1 sekundę, to niech alpha wynosi 1.0. W przeciwnym razie możesz pozwolić alpha be (usecs od ostatniej aktualizacji1000000). ndash jxh Cze 12 12 at 6:21 Zasadniczo chcę śledzić średnią ruchu ciągłego strumienia strumienia liczb zmiennoprzecinkowych przy użyciu najnowszych 1000 numerów jako próbki danych. Należy zauważyć, że poniżej uaktualnia całkowitą wartość jako elementy dodawane, co pozwala uniknąć kosztownego przebiegu O (N) w celu obliczenia sumy potrzebnej na przeciętnie na żądanie. Razem uzyskuje się inny parametr od T do obsługi np. używając długiej długi podczas łączenia 1000 długich s, int dla char s lub double-total float. Jest to nieco błędne, że liczby czcionek mogą przechodzić przez INTMAX - jeśli zależy Ci na długich długach bez podpisu. lub użyj dodatkowego członka danych bool do nagrywania, gdy pojemnik jest najpierw napełniany, podczas cyklicznych numsamples wokół tablicy (najlepiej zamienić coś nieszkodliwego jak pos). odpowiedziało 12 czerwca 12 w 5:19 zakłada się, że operator kwotowania (przykład T) jest w rzeczywistości operatorem cudzysłowów (przykład T). ndash oPless 8 czerwca o godz. 11:52 oPless ahhh. dobrze spotykane. właściwie miałem na myśli operatora void () (przykład T), ale oczywiście można użyć dowolnej notacji, którą lubisz. Naprawdę, dzięki. ndash Tony D Cze 8 14 at 14: 27Może wspomniałem inni, powinniśmy rozważyć filtrowanie IIR (nieskończony impuls odpowiedzi), a nie filtr FIR (finite impulse response), którego używasz teraz. Jest więcej, ale na pierwszy rzut oka filtry FIR są implementowane jako wyraźne splify i filtry IIR z równaniami. Szczególny filtr IIR używam dużo w mikrokontrolerach jest jednym biegunowym filtrem dolnoprzepustowym. Jest to cyfrowy odpowiednik prostego filtra analogowego R-C. W większości zastosowań mają lepsze właściwości niż używany przez Ciebie filtr. Większość zastosowań filtru pudełkowego, który napotkam, jest wynikiem, że ktoś nie zwraca uwagi na klasę przetwarzania sygnału cyfrowego, a nie w wyniku potrzeby ich szczególnych cech. Jeśli chcesz złagodzić wysokie częstotliwości, które znasz są hałas, jeden biegun filtr dolnoprzepustowy jest lepszy. Najlepszym sposobem na implementację cyfrowo w mikrokontrolerze jest zwykle: FILT lt - FILT FF (NOWOŚĆ - FILT) FILT jest kawałkiem trwałego stanu. To jedyna trwała zmienna, którą musisz obliczyć. NEW to nowa wartość, którą filtr jest aktualizowany za pomocą tej iteracji. FF jest frakcją filtrującą. co poprawia ciężar filtra. Spójrz na ten algorytm i zobacz, że dla FF 0 filtr jest nieskończenie ciężki, ponieważ wyjście nigdy się nie zmienia. Dla FF 1, jego naprawdę żaden filtr w ogóle, ponieważ wyjście po prostu następuje na wejściu. Przydatne wartości są pomiędzy nimi. W małych systemach wybierasz FF na 12 N, dzięki czemu mnożenie przez FF może być dokonane jako poprawna zmiana przez N bitów. Na przykład, FF może być 116 i pomnożyć przez FF, a więc prawo przesunięcia 4 bity. W przeciwnym razie filtr ten wymaga tylko jednego odejmowania, a jeden zostanie dodany, chociaż numery muszą być szersze niż wartość wejściowa (więcej o dokładności numerycznej w oddzielnej sekcji poniżej). Zazwyczaj biorę odczyty AD znacznie szybciej niż są potrzebne i zastosuj dwa z tych filtrów kaskadowych. Jest to cyfrowy odpowiednik dwóch filtrów R-C w szeregu i tłumi o 12 dBoctave powyżej częstotliwości rolloff. Jednak w przypadku odczytów AD zwykle bardziej trafne jest przejrzenie filtru w dziedzinie czasu przez rozważenie odpowiedzi krokowej. To informuje, jak szybko Twój system będzie widzieć zmianę, gdy coś, co mierzysz, zmienia się. Aby ułatwić projektowanie tych filtrów (co oznacza jedynie pobranie FF i określenie, ile z nich jest kaskadowych), używam mojego programu FILTBITS. Można określić liczbę bitów przesuwnych dla każdego FF w kaskadowej serii filtrów, a także obliczyć odpowiedź kroku i inne wartości. Właściwie to zwykle uruchamiam to za pomocą mojego skryptu PLOTFILT. Spowoduje to uruchomienie FILTBITS, który tworzy plik CSV, a następnie rzutuje na plik CSV. Na przykład jest to wynik PLOTFILT 4 4: Dwa parametry PLOTFILT oznaczają, że będą dwa filtry kaskadowe typu opisanego powyżej. Wartości 4 wskazują liczbę bitów przesunięcia, aby zrealizować mnożenie przez FF. W tym przypadku dwie wartości FF są więc 116. Czerwony ślad jest odpowiedzią na jednostkę kroku i jest najważniejszą sprawą. Na przykład oznacza to, że jeśli dane wejściowe ulegną zmianie, wyjście połączonego filtra osiądzie do 90 nowej wartości w 60 iteracjach. Jeśli zależy Ci na około 95 czasach rozliczania, musisz poczekać około 73 iteracji, a dla 50 czasu rozliczania wystarczy tylko 26 iteracji. Zielony ślad wskazuje wynik z pojedynczego impulsu o pełnej amplitudzie. Daje to pewien pomysł na przypadkowe tłumienie hałasu. Wygląda na to, że żadna pojedyncza próbka nie spowoduje więcej niż 2,5 zmiany w produkcie. Niebieskim śladem jest subiektywne odczucie tego, co ten filtr działa z białym hałasem. Nie jest to rygorystyczny test, ponieważ nie ma gwarancji, jaka była zawartość liczb losowych wybranych jako białe szumy w tej rundzie PLOTFILT. To tylko daje poczucie, jak bardzo będzie zgnieciona i jaka jest gładka. PLOTFILT, być może FILTBITS i wiele innych użytecznych rzeczy, zwłaszcza w zakresie rozwoju oprogramowania PIC, jest dostępne w oprogramowaniu PIC Development Tools na stronie "Pobieranie oprogramowania". Dodano dokładność liczbową, którą widzę w komentarzach, a teraz nową odpowiedź, która interesuje się dyskusją na temat liczby bitów potrzebnych do wdrożenia tego filtra. Zauważ, że pomnożenie przez FF spowoduje utworzenie nowych bitów Log 2 (FF) poniżej punktu binarnego. W małych systemach, FF jest zwykle wybierany jako 12 N, dzięki czemu mnożenie jest faktycznie realizowane przez prawo przesunięcia N bitów. FILT jest więc zazwyczaj liczbą całkowitą o stałej liczbie punktów. Zauważ, że to nie zmienia żadnej matematyki z punktu widzenia procesorów. Na przykład, jeśli filtrujesz odczyty 10-bitowe AD i N 4 (FF 116), potrzebujesz 4 bitów ułamkowych poniżej 10-bitowych odczytów liczb całkowitych. Jedna większość procesorów, wykonujących 16-bitowe operacje całkowite z powodu odczytów 10-bitowych AD. W takim przypadku można nadal wykonywać dokładnie takie same 16-bitowe operacje całkowite, ale zaczynaj od odczytów AD przesuniętych o 4 bity. Procesor nie zna różnicy i nie musi. Wykonywanie matematyki na całych 16-bitowych liczb całkowitych działa niezależnie od tego, czy uważasz je za 12,4 punktu stałego czy prawdziwe 16-bitowe liczby całkowite (16,0 punkt stały). Ogólnie, musisz dodać N bity każdego bieguna filtra, jeśli nie chcesz dodawać hałasu z powodu liczby reprezentacji. W powyższym przykładzie drugi filtr dwóch musiałby mieć 1044 18 bitów, aby nie utracić informacji. W praktyce na 8-bitowej maszynie oznacza to, że używasz 24 bitowych wartości. Technicznie tylko drugi biegun dwóch wymagałby szerszej wartości, ale dla uproszczenia oprogramowania zwykle używam tej samej reprezentacji, a tym samym tego samego kodu, dla wszystkich biegunów filtra. Zwykle piszę podprogram lub makro, aby wykonać jedną operację słupa filtra, a następnie zastosować ją do każdego bieguna. Niezależnie od tego, czy podprocedura czy makra zależy od tego, czy cykle czy pamięć programu są ważniejsze w danym projekcie. Tak czy owak, używam pewnego stanu, aby przejść NEW do podprogramu, który aktualizuje plik FILT, ale ładuje się do tego samego stanu scratch NEW. To ułatwia stosowanie wielu biegunów, ponieważ aktualizacja FILT jednego bieguna jest NOWA następnego. Kiedy procedura podprogramu jest przydatna, gdy pojawi się wskaźnik po FILT, który zostanie zaktualizowany do chwili, gdy FILT wyjdzie. W ten sposób podprogram automatycznie uruchamia kolejne filtry w pamięci, jeśli jest wywołany wiele razy. Za pomocą makra nie potrzebujesz wskaźnika, ponieważ prześlesz adres, aby działał w każdej iteracji. Przykłady kodów Oto przykład makra opisanego powyżej dla PIC 18: A oto podobne makro dla PIC 24 lub dsPIC 30 lub 33: Obydwa przykłady są implementowane jako makra za pomocą mojego preprocesora assemblera PIC. który jest bardziej zdolny niż jeden z wbudowanych urządzeń makr. clabacchio: Innym problemem, o którym wspomniałem, jest implementacja oprogramowania. Możesz raz napisać pojedynczą podprogramę filtra dolnoprzepustowego, a następnie zastosować ją wielokrotnie. W zasadzie zwykle piszę taką podprogram, aby wziąć wskaźnik w pamięci do stanu filtra, a następnie go wyprzedzić wskaźnik, aby można było z łatwością zadzwonić w celu realizacji wielobiegunowych filtrów. ndash Olin Lathrop 20 kwietnia 12 w 15:03 1. bardzo dziękuję za odpowiedzi - wszystkie z nich. Zdecydowałem się korzystać z tego filtru IIR, ale ten filtr nie jest używany jako filtr standardowy LowPass, ponieważ muszę przeanalizować średnie wartości liczników i porównać je w celu wykrycia zmian w pewnym zakresie. ponieważ te Wartości mają bardzo różne wymiary, w zależności od sprzętu, które chciałem przeciętnie, aby móc automatycznie reagować na te specyficzne dla sprzętu zmiany. ndash sensslen May 21 12 at 12:06 Jeśli możesz żyć z ograniczeniem mocy dwóch liczb elementów do średniej (tj. 2,4,8,16,32 itd.), dzielenie można łatwo i skutecznie zrobić na niskiej wydajności mikro bez poświęconego podziału, ponieważ można to zrobić jako przesunięcie bitowe. Każde prawo zmiany jest jedną moc dwóch, np .: OP myśli, że miał dwa problemy, dzieląc się PIC16 i pamięci na jego pierścień buforu. Ta odpowiedź pokazuje, że dzielenie nie jest trudne. Trzeba przyznać, że nie rozwiązuje problemu pamięci, ale system SE pozwala na częściowe odpowiedzi, a użytkownicy mogą wziąć coś z każdej odpowiedzi na siebie, a nawet edytować i połączyć inne odpowiedzi. Ponieważ niektóre inne odpowiedzi wymagają operacji podziału, są one podobnie niekompletne, ponieważ nie pokazują, jak skutecznie osiągnąć to na PIC16. ndash Martin Kwiecień 20 12 w 13:01 Jest odpowiedź na prawdziwy średniometrażowy filtr (aka boxcar filter) z mniejszymi wymaganiami pamięci, jeśli nie masz ochoty pobierać próbkowania. Nazywa się on kaskadowym integratorem-filtr grzebieniowy (CIC). Chodzi o to, że masz integrator, który podejmujesz w różnych odstępach czasu, a kluczowym urządzeniem oszczędzającym pamięć jest to, że dzięki zmniejszeniu próbkowania nie trzeba przechowywać każdej wartości integratora. Może być zaimplementowana za pomocą następującej pseudokodów: Twoja efektywna średnia długość ruchu to decimationFactorstatesize, ale wystarczy zachować próbki z miaridowania. Oczywiście można uzyskać lepszą wydajność, jeśli twój stateize i decimationFactor są uprawnieniami 2, tak aby operatorzy dzielenia i pozostałych otrzymali zastąpienia zmianami i maskowaniem. Postscript: Zgadzam się z Olinem, że należy zawsze rozważyć proste filtry IIR przed średnim filtrem ruchomym. Jeśli nie potrzebujesz częstotliwości-nulls z filtrem bokserskim, 1-biegunowy lub 2-biegunowy filtr dolnoprzepustowy prawdopodobnie działa dobrze. Z drugiej strony, jeśli filtruje się do celów decymacji (pobieranie danych o wysokiej liczbie próbek i uśrednianie go do użycia przy użyciu procesu o niskim współczynniku szybkości), wówczas filtr CIC może być właśnie tym, czego szukasz. (zwłaszcza jeśli można użyć statesize1 i uniknąć ringbuffer razem z tylko jedną poprzednią wartością integratora) Istnieją pewne pogłębione analizy matematyki za pomocą pierwszego filtru IIR zamówienia, które Olin Lathrop już opisał w sprawie wymiany stosunków przetwarzania sygnałów cyfrowych (zawiera mnóstwo ładnych zdjęć). Równanie dla tego filtra IIR jest następujące: Można to wykonać za pomocą tylko liczb całkowitych i żadnego podziału, używając następującego kodu (może potrzebować trochę debugowania podczas pisania z pamięci). Ten filtr przybliża średnią ruchową ostatnie próbki K, ustawiając wartość alfa na 1K. Zrób to w poprzednim kodzie poprzez zdefiniowanie BITS na LOG2 (K), tj. Dla K 16 set BITS na 4, dla K 4 ustawić BITS na 2 itd. (Sprawdź kod podany tutaj, gdy tylko otrzymam zmianę i w razie potrzeby, zmień tę odpowiedź w razie potrzeby). Odpowiedź # 5 dnia: Październik 23, 2008, 04:04:38 am »Heres jeden-biegunowy filtr dolnoprzepustowy (średnia ruchoma, z cutoff częstotliwości CutoffFrequency). Bardzo prosty, bardzo szybki, działa świetnie i prawie nie ma pamięci. Uwaga: Wszystkie zmienne mają zakres poza funkcją filtru, z wyjątkiem przekazania w newInput Uwaga: Jest to filtr pojedynczego etapu. Wielokrotne etapy mogą być kaskadowe ze sobą w celu zwiększenia ostrości filtra. Jeśli używasz więcej niż jednego etapu, musisz wyregulować wartość DecayFactor (co dotyczy częstotliwości odcięcia), aby zrekompensować. I oczywiście wszystko, czego potrzebujesz to te dwie linie umieszczone w dowolnym miejscu, nie potrzebują własnej funkcji. Filtr ten ma czas pobudzenia, zanim średnia ruchoma odpowiada wartości sygnału wejściowego. Jeśli musisz obejść ten czas, możesz zainicjować MovingAverage tylko do pierwszej wartości newInput zamiast 0, i mam nadzieję, że pierwsza newInput nie jest lepsza. (CutoffFrequencySampleRate) ma zakres od 0 do 0.5. DecayFactor jest wartością od 0 do 1, zwykle blisko 1. Pojedyncze pływaki są wystarczająco dobre dla większości rzeczy, wolę tylko podwójnie. Jeśli musisz trzymać się liczb całkowitych, możesz przekonwertować DecayFactor i Amplitude Factor na ułamkowe liczby całkowite, w których licznik jest zapisany jako liczba całkowita, a mianownik jest liczbą całkowitą 2 (więc możesz przesunąć bit na prawo, mianownika, a nie dzielenia się podczas pętli filtracyjnej). Na przykład, jeśli DecayFactor 0.99 i chcesz używać liczb całkowitych, możesz ustawić wartość DecayFactor 0.99 65536 64881. A następnie w dowolnym momencie pomnożyć przez DecayFactor w pętli filtru, po prostu przesuń wynik 16. Aby uzyskać więcej informacji na ten temat, online, rozdział 19 na plikach rekursywnych: dspguidech19.htm PS Dla paradygmatu Moving Average, innego podejścia do ustawienia DecayFactor i AmplitudeFactor, które mogą być bardziej odpowiednie dla Twoich potrzeb, powiedzmy, że chcesz poprzednio, około 6 elementów uśrednio ze sobą, robi to dyskretnie, dodasz 6 pozycji i podzielisz przez 6, więc można ustawić AmplitudeFactor na 16 i DecayFactor na (1.0 - AmplitudeFactor). Odpowiedział 14 maja na 22:55. Wszyscy inni skomentowali dokładnie użyteczność IIR vs. FIR, i na władzę dwóch dywizji. Id tak, aby podać pewne szczegóły implementacji. Poniżej działa dobrze na małych mikrokontrolerach bez FPU. Nie ma mnożenia, a jeśli zachowasz N moc dwóch, cały podział jest jednorazowym cyklem przesuwania. Podstawowy bufor pierścieniowy FIR: zachowuje bieżący bufor z ostatnich wartości N i uruchomiony SUM wszystkich wartości w buforze. Za każdym razem, gdy pojawia się nowa próbka, odejmij najstarszą wartość w buforze z SUM, zastąp ją nową próbką, dodaj nową próbkę do SUMA i wydrukuj SUMN. Zmodyfikowany bufor pierścieniowy IIR: zachować bieżący SUM z ostatnich wartości N. Za każdym razem, gdy pojawia się nowa próbka, SUM - SUMN, dodaj nową próbkę i wyjdź SUMN. Odpowiedziałem 28 sierpnia 13 w 13:45 Jeśli przeczytam wam słusznie, to opisujesz filtr IIR pierwszego rzędu, którego wartość odejmujesz nie jest najstarszą wartością wypadającą, ale raczej średnią z poprzednich wartości. Filtry IIR z pierwszego rzędu mogą być użyteczne, ale nie jestem pewien, co masz na myśli, gdy sugerujesz, że wyjście jest takie samo we wszystkich okresowych sygnałach. Przy szybkości próbkowania 10 kHz, zasilanie falą kwadratową 100 Hz w 20-stopniowym filtrze pola, daje sygnał, który wzrasta równomiernie dla 20 próbek, siedzi na wysokościach 30, kropel równomiernie dla 20 próbek i siedzi na niskim poziomie 30. Pierwsze rzędy Filtr IIR. ndash supercat 28 sierpnia 13 w 15:31 przyniesie fali, która ostro zaczyna rosnąć i stopniowo wyrównywać blisko (ale nie na) maksimum wejściowe, a następnie gwałtownie zaczyna spadać i stopniowo wyrównać się blisko (ale nie na) minimalnego wejścia. Bardzo inne zachowania. ndash supercat 28 sierpnia 13 w 15:32 Jednym z problemów jest to, że prosta średnia ruchoma może być lub nie być użyteczna. Dzięki filtrowi IIR możesz uzyskać ładny filtr o stosunkowo niewielkiej liczbie calków. FIR, który opisujesz, może tylko dać prostokąt w czasie - szczerze freq - i nie możesz manipulować bocznymi płatkami. Być może warto rzucać kilka liczb całkowitych, aby uczynić to ładnym, symetrycznym tuningiem FIR, jeśli możesz oszczędzić zegary. ndash Scott Seidman 29 sierpnia 13 w 13:50 ScottSeidman: Nie ma potrzeby pomnożenia, jeśli jeden ma po prostu każdy etap FIR albo wyprowadzić średnio wejście na ten etap i jego poprzednią zapisaną wartość, a następnie zapisać dane wejściowe (jeśli ma w zakresie numerycznym, można by użyć sumy, a nie średniej). Niezależnie od tego, czy jest to lepsze od filtru pudełkowego zależy od aplikacji (odpowiedź krokowa filtru pudełkowego z całkowitym opóźnieniem 1ms, na przykład, będzie miała paskudny skok d2dt przy zmianie wejścia, a następnie o 1 ms później, ale będzie miał minimum możliwe dd dla filtra o całkowitym opóźnieniu 1ms). ndash supercat Jak mikeselectricstuff powiedział, jeśli naprawdę trzeba zmniejszyć potrzeby pamięci, a nie pamiętam, twój impuls odpowiedzi jest wykładniczy (zamiast prostokątnego impulsu), chciałbym przejść do wykładniczej średniej ruchomych filtr . Używam ich w znacznym stopniu. Przy takim typie filtra nie potrzebujesz żadnego buforu. Nie musisz przechowywać N ostatnich próbek. Tylko jeden. Tak więc, Twoje wymagania pamięci zostały obniżone przez czynnik N. Ponadto, nie potrzebujesz żadnego podziału na to. Tylko multiplikacje. Jeśli masz dostęp do arytmetyki zmiennoprzecinkowej, użyj multiplikacji zmiennoprzecinkowych. W przeciwnym razie wykonaj multiplikacje całkowite i przesuń w prawo. Jednak jesteśmy w 2017 roku i zalecam używanie kompilatorów (i MCU), które umożliwiają pracę z liczbami zmiennoprzecinkowymi. Poza tym, że więcej pamięci jest wydajniejsze i szybsze (nie trzeba aktualizować elementów w dowolnym okrągłym buforze), chciałbym powiedzieć, że jest to również bardziej naturalne. ponieważ odpowiedź impulsowa jest lepsza w zachowaniu charakteru, w większości przypadków. Odpowiedziała 20 kwietnia o godz. 9:59 Jeden problem z filtrem IIR niemal dotknięty przez olin i supercat, ale najwyraźniej zignorowany przez innych jest taki, że zaokrąglanie wprowadza pewną nieprecyzyjność (i potencjalnie biastruncation). przy założeniu, że N jest mocą dwóch, a tylko arytmetyka całkowita jest używany, prawo przesunięcia systematycznie eliminuje LSBs nowej próbki. Oznacza to, że jak długo serie mogłyby się pojawić, średnia nigdy ich nie uwzględnia. Załóżmy na przykład, że powoli zmniejszają się serie (8,8, 8, 7, 7, 7, 6, 6) i zakładają, że średnia na początku wynosi 8. Próbka 7 piórki przyniesie średnią do 7, niezależnie od siły filtra. Tylko na jedną próbkę. Ta sama historia dla 6 itd. Teraz myśl o tym przeciwnie. seria idzie w górę. Średnia pozostanie na 7 na zawsze, dopóki próbka nie jest wystarczająco duża, aby ją zmienić. Oczywiście można poprawić nastawienie dodając 12N2, ale to naprawdę nie rozwiązuje problemu dokładności. w tym przypadku malejące serie pozostaną na zawsze w temperaturze 8, aż próbka wynosi 8-12 (N2). Dla przykładu N4, każda próba powyżej zera utrzyma średnią na niezmienionym poziomie. Sądzę, że rozwiązanie to oznaczałoby utrzymanie akumulatora utraconych LSB. Ale nie zrobiłem tego na tyle, aby mieć gotowy kod, i nie jestem pewien, że nie zaszkodzi mocy IIR w innych przypadkach serii (na przykład czy 7,9,7,9 średnio do 8 następnie). Olin, twoja dwustopniowa kaskada również potrzebuje wyjaśnienia. Czy masz na myśli trzymanie dwóch średnich wartości w wyniku pierwszego podania do drugiej w każdej iteracji. Cóż to z korzyścią może obejmować od prostego uśredniania n wartości do filtra średniej wykładniczej do bardziej zaawansowanego filtra, który działa na częstotliwościach. Bardziej wyrafinowane wersje filtrów dolnoprzepustowych można tworzyć, konwertując elektroniczne filtry dolnoprzepustowe wykorzystywane w przetwarzaniu sygnału cyfrowego (np. Filtr Butterwortha itp.). Znalazłem tę witrynę zawierającą dużo zasobów na przetwarzanie sygnałów cyfrowych (The Scientist and Engineer0's Guide do przetwarzania sygnałów cyfrowych). Pierwszym przykładem jest ruchome średnie filtry, a następnie filtr rekurencyjny, a następnie przykład utworzenia filtra dolnoprzepustowego z częstotliwością odcięcia, z częstotliwością pobierania próbek i stałą filtru RC, motywowaną zachowaniem dolnoprzepustowym lub obwodem RC . Pamiętaj tylko: uśrednianie w domenie czasu bałagan z reprezentacją w domenie częstotliwości, a filtrowanie domenami częstotliwości bałagan z reprezentacją domeny czasu. Filtr, który pracuje w dziedzinie czasowej, skutkuje już nieużyteczną odpowiedzią na częstotliwość, ponieważ filtr039's własny 039signal039 został skomplikowany z rzeczywistym sygnałem. Z drugiej strony, jeśli usuniesz szumy wysokiej częstotliwości w domenie częstotliwości, nie spodziewaj się gładkiego sygnału w domenie czasu. PS: Nigdy nie robić obu. Nigdy nie robić cięcia częstotliwości, a następnie średnio w domenie czasu (i odwrotnie), chyba że. nie ma innej opcji (co zwykle jest) 14.7k Views middot Zobacz Upvotes middot Not for Reproduction

No comments:

Post a Comment