Spisu treści:

Średnia bieżąca dla Twoich projektów z mikrokontrolerem: 6 kroków
Średnia bieżąca dla Twoich projektów z mikrokontrolerem: 6 kroków

Wideo: Średnia bieżąca dla Twoich projektów z mikrokontrolerem: 6 kroków

Wideo: Średnia bieżąca dla Twoich projektów z mikrokontrolerem: 6 kroków
Wideo: Co można zbudować na Arduino? Sprawdź 5 ciekawych projektów DIY (robot-lodówka, WIELKI zegar... 2024, Listopad
Anonim
Średnia bieżąca dla Twoich projektów mikrokontrolerów
Średnia bieżąca dla Twoich projektów mikrokontrolerów

W tej instrukcji wyjaśnię, czym jest średnia ruchoma i dlaczego powinieneś się nią zajmować, a także pokażę, jak należy ją zaimplementować, aby uzyskać maksymalną wydajność obliczeniową (nie martw się złożonością, jest to bardzo proste do zrozumienia i będę zapewnij łatwą w użyciu bibliotekę dla twoich projektów arduino:)

Średnia ruchoma, powszechnie określana również jako średnia ruchoma, średnia ruchoma lub średnia ruchoma, to termin używany do opisywania średniej wartości ostatnich N wartości w seriach danych. Można go obliczyć jako normalną średnią lub użyć sztuczki, aby mieć minimalny wpływ na wydajność twojego kodu.

Krok 1: Przypadek użycia: wygładzanie pomiarów ADC

Przypadek użycia: wygładzanie pomiarów ADC
Przypadek użycia: wygładzanie pomiarów ADC

Arduino ma przyzwoity 10-bitowy ADC z bardzo niskim poziomem szumów. Podczas pomiaru wartości na czujniku, takim jak potencjometr, fotorezystor lub inne elementy o wysokim poziomie szumów, trudno ufać, że pomiar jest prawidłowy.

Jednym z rozwiązań jest wykonywanie wielu pomiarów za każdym razem, gdy chcesz odczytać dane z czujnika i uśrednić je. W niektórych przypadkach jest to realne rozwiązanie, ale nie zawsze. Jeśli chciałbyś czytać ADC 1000 razy na sekundę, musiałbyś do 10 000, jeśli wykonałeś średnio 10 pomiarów. Ogromna strata czasu obliczeniowego.

Proponowane przeze mnie rozwiązanie to wykonywanie pomiarów 1000 razy na sekundę, każdorazowe aktualizowanie średniej bieżącej i używanie jej jako wartości bieżącej. Ta metoda wprowadza pewne opóźnienia, ale zmniejsza złożoność obliczeniową aplikacji, dając znacznie więcej czasu na dodatkowe przetwarzanie.

Na powyższym obrazku użyłem średniej bieżącej z ostatnich 32 pomiarów. Zobaczysz, że ta metoda nie jest w 100% odporna na awarie, ale znacznie poprawia dokładność (nie jest gorsza niż uśrednianie za każdym razem 32 próbek). Jeśli chcesz obliczyć średnio 32 pomiary za każdym razem, zajęłoby to ponad 0,25 ms na Arduino UNO dla samych pomiarów!

Krok 2: Przypadek użycia: Pomiar składowej DC sygnału mikrofonu

Przypadek użycia: pomiar składowej prądu stałego sygnału mikrofonu
Przypadek użycia: pomiar składowej prądu stałego sygnału mikrofonu
Przypadek użycia: pomiar składowej prądu stałego sygnału mikrofonu
Przypadek użycia: pomiar składowej prądu stałego sygnału mikrofonu
Przypadek użycia: pomiar składowej prądu stałego sygnału mikrofonu
Przypadek użycia: pomiar składowej prądu stałego sygnału mikrofonu

Arduino może mierzyć napięcia od 0 do Vcc (zwykle 5 V). Sygnał audio jest całkowicie AC i jeśli chcesz go zmierzyć na mikrokontrolerze, musisz go nastawić na około 1/2 Vcc. W projekcie Arduino UNO oznaczałoby to z grubsza 2,5 V (DC) + sygnał audio (AC). W przypadku korzystania z 10-bitowego przetwornika ADC i zasilania 5 V, napięcie polaryzacji 2,5 V powinno być równe pomiarowi 512. Aby uzyskać wartość sygnału AC, należy odjąć 512 od pomiaru ADC i to wszystko, prawda?

W idealnym świecie byłaby to prawda. Niestety prawdziwe życie jest bardziej skomplikowane, a nasze nastawienie sygnału ma tendencję do dryfowania. Bardzo powszechny jest szum 50 Hz (60 Hz, jeśli mieszkasz w USA) z sieci elektrycznej. Zwykle nie jest to zbyt problematyczne, ale dobrze jest wiedzieć, że istnieje. Bardziej problematyczny jest dryf liniowy od nagrzewania elementów. Ostrożnie ustawiasz korekcję przesunięcia DC na początku i powoli oddala się ona w miarę działania aplikacji.

Zilustruję ten problem za pomocą (muzyki) detektora dudnień. Ustawiasz usuwanie stronniczości, a bity są wyraźne (zdjęcie 2). Po pewnym czasie przesunięcia prądu stałego i uderzenia są ledwo zauważalne dla mikrokontrolera (rysunek 3). Algorytm wykrywania uderzeń zostanie dogłębnie zbadany w przyszłości, ponieważ wykracza poza zakres tego artykułu.

Na szczęście istnieje sposób na ciągłe obliczanie przesunięcia DC dźwięku. Nie będzie zaskoczeniem, że średnia biegowa, temat tego instruktażowego, zapewnia rozwiązanie.

Wiemy, że średnia wartość dowolnego sygnału AC wynosi 0. Korzystając z tej wiedzy, możemy wywnioskować, że średnia wartość sygnału AC+DC to jego polaryzacja DC. Aby go usunąć, możemy wziąć średnią bieżącą z kilku ostatnich wartości i odjąć ją od bieżącego odczytu ADC. Pamiętaj, że musisz użyć wystarczająco długiej średniej bieżącej. W przypadku dźwięku jedna dziesiąta sekundy (liczba próbek zależy od częstotliwości próbkowania) powinna wystarczyć, ale wiedz, że dłuższe średnie działają lepiej. Na pierwszym rysunku widać przykład obliczenia rzeczywistej polaryzacji prądu stałego ze średnią kroczącą z 64 elementami przy częstotliwości próbkowania 1 kHz (mniej niż zalecałem, ale nadal działa).

Krok 3: Obliczanie

Obliczenie
Obliczenie

Możesz sobie wyobrazić średnią biegową jako średnią wagę osób w poczekalni lekarskiej. Lekarz kończy badanie jednego pacjenta i jednocześnie nowy wchodzi do poczekalni.

Aby poznać średnią wagę wszystkich pacjentów oczekujących w poczekalni, pielęgniarka może zapytać każdego pacjenta o jego wagę, zsumować te liczby i podzielić przez liczbę pacjentów. Za każdym razem, gdy lekarz przyjmuje nowego pacjenta, pielęgniarka powtarzała cały proces.

Być może myślisz: „To nie brzmi zbyt wydajnie… Musi być na to lepszy sposób”. I miałbyś rację.

Aby zoptymalizować ten proces, pielęgniarka mogłaby prowadzić ewidencję masy całkowitej aktualnej grupy pacjentów. Kiedy lekarz wzywa nowego pacjenta, pielęgniarka pytała go o jego wagę i odejmowała ją od sumy grupy i puszczała. Następnie pielęgniarka pytała pacjenta, który właśnie wszedł do poczekalni, o jego wagę i dodawała ją do sumy. Średnia waga pacjentów po każdej zmianie byłaby sumą wag podzieloną przez liczbę pacjentów (tak, jak wcześniej, ale teraz pielęgniarka pytała o wagę tylko dwie osoby, a nie wszystkie). Zdaję sobie sprawę, że ten akapit mógł być nieco mylący, więc zobacz powyższą ilustrację, aby uzyskać dodatkową jasność (lub zadawaj pytania w komentarzach).

Ale nawet jeśli ostatni akapit nie był dla ciebie zagmatwany, możesz mieć pytania, takie jak: co powinno być w akumulatorze na początku, jak umieścić to, co właśnie przeczytałem, w rzeczywistym kodzie C? Zostanie to omówione w następnym kroku, gdzie otrzymasz również mój kod źródłowy.

Krok 4: Kodeks

Kod
Kod

Aby obliczyć średnią bieżącą, najpierw potrzebujesz sposobu na przechowywanie ostatnich N wartości. możesz miećtablicę z N elementami i przesuwać całązawartośćo jedno miejsce za każdym razem, gdy dodajesz element (proszę nie rób tego) lub możesz nadpisaćjeden stary element i dostosować wskaźnik do następnego elementu, który ma byćwyrzucony (proszę zrób to:)

Akumulator powinien zacząć się inicjalizować na 0, to samo dotyczy wszystkich elementów w linii opóźniającej. W przeciwnym razie Twoja średnia biegowa będzie zawsze błędna. Zobaczysz, że delayLine_init zajmuje się inicjalizacją linii opóźniającej, powinieneś sam zająć się akumulatorem.

dodanie elementu do linii opóźniającej jest tak proste, jak zmniejszenie indeksu najnowszego elementu o 1, upewniając się, że nie wskazuje on strony tablicy linii opóźniających. po zmniejszeniu indeksu, gdy wynosi 0, zapętli się do 255 (ponieważ jest to 8-bitowa liczba całkowita bez znaku). Operator modulo (%) z rozmiarem tablicy linii opóźniających zapewni, że indeks będzie wskazywał prawidłowy element.

Obliczenie średniej kroczącej powinno być łatwe do zrozumienia, jeśli postępowałeś zgodnie z moją analogią z poprzedniego kroku. Odejmij najstarszy element od akumulatora, dodaj najnowszą wartość do akumulatora, wstaw najnowszą wartość do linii opóźnienia, zwróć akumulator podzielony przez liczbę elementów.

Łatwe, prawda?

Zachęcamy do eksperymentowania z użyciem załączonego kodu, aby lepiej zrozumieć, jak to wszystko działa. W obecnej formie arduino odczytuje wartość analogową na pinie analogowym A0 i drukuje „[wartość ADC], [średnia bieżąca]” na porcie szeregowym z prędkością 115200 bodów. Jeśli otworzysz szeregowy ploter arduino z prawidłową szybkością transmisji, zobaczysz dwie linie: wartość ADC (niebieska) i wartość wygładzona (czerwona).

Krok 5: Dodatki

Dodatki
Dodatki

Jest kilka rzeczy, o których niekoniecznie musisz wiedzieć, aby używać średniej kroczącej w swoim projekcie, ale nie zaszkodzi wiedzieć.

opóźnienie: zacznę od omówienia ilustracji tego kroku. Zauważysz, że średnia ruchoma z większej liczby elementów wprowadza większe opóźnienie. Jeśli czas reakcji na zmianę wartości jest krytyczny, możesz chcieć użyć krótszej średniej bieżącej lub zwiększyć częstotliwość próbkowania (częstsze pomiary).

Iść dalej.

inicjalizacja: Kiedy mówiłem o inicjalizacji akumulatora i elementów opóźniających, powiedziałem, że powinieneś zainicjować je wszystkie na 0. Alternatywnie możesz zainicjować linię opóźniającą do czegokolwiek chcesz, ale akumulator powinien zaczynać się jako suma najnowszych N elementów w linii opóźniającej (gdzie N to liczba elementów w średniej biegowej). Jeżeli akumulator wystartuje z dowolną inną wartością, wyliczona średnia będzie błędna - albo za niska, albo za wysoka, zawsze o tę samą wartość (przy założeniu tych samych warunków początkowych). Sugeruję, abyś spróbował dowiedzieć się, dlaczego tak jest, używając „symulacji pióra i papieru”.

rozmiar akumulatora: Należy również pamiętać, że akumulator powinien być wystarczająco duży, aby przechowywać sumę wszystkich elementów w linii opóźnienia, jeśli wszystkie są dodatnie lub ujemne max. W praktyce oznacza to, że akumulator powinien być o jeden typ danych większy niż elementy linii opóźniającej i być podpisany, jeśli elementy linii opóźniającej są podpisane.

sztuczka: Długie linie opóźniające zajmują dużo pamięci. To może szybko stać się problemem. Jeśli masz bardzo ograniczoną pamięć i nie zależy Ci zbytnio na dokładności, możesz przybliżyć średnią bieżącą, całkowicie pomijając opóźnienie i wykonując zamiast tego: odejmij 1/N * akumulator od akumulatora i dodaj nową wartość (na przykładzie 8 długich średnich: akumulator = akumulator * 7 / 8 + nowa wartość). Ta metoda daje zły wynik, ale jest to przyzwoita metoda obliczania średniej bieżącej, gdy brakuje Ci pamięci.

lingwistyka: „ruchoma średnia/średnia” jest zwykle używana w odniesieniu do uśredniania w czasie rzeczywistym, podczas gdy „ruchoma średnia/średnia” zwykle oznacza, że algorytm działa na statycznym zestawie danych, takim jak arkusz kalkulacyjny programu Excel.

Krok 6: Wniosek

Mam nadzieję, że ta instrukcja była wystarczająco łatwa do zrozumienia i pomoże ci w przyszłych projektach. Zachęcamy do publikowania pytań w komentarzach poniżej, jeśli jest coś niejasnego.

Zalecana: