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

[ATMega168][C] Uśrednianie wyniku z ADC

cobi_69 16 Wrz 2011 17:15 5058 11
  • #1 9933276
    cobi_69
    Poziom 21  
    Witam bawię się przetwornikiem ADC i mam problem.
    Ale żeby nie przechowywać w tablicy zbyt dużo danych to zastosowałem wzór:
    (wzór otrzymany po przekształceniu standardowego wzoru na średnią, sprawdzony)

    średnia(k) = (N-1)/N * średnia(k-1) + 1/N * pomiar

    i tu jest problem, bo jak uruchomię program:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    To wszystko działa, ale jak zamiast ustawienia "na sztywno" proporcji we wzorze, dam:

    N=2;
    srednia = ((((N-1)/N) * srednia_p) + (pomiar_x / N));

    To już nie działa, a przecież to to samo
  • #2 9933336
    tadzik85
    Poziom 38  
    Trochę dziwne to uśrednianie, Jaki jest tego cel?

    Typy zmiennych, kolejność obliczeń.
  • #3 9933361
    cobi_69
    Poziom 21  
    Uśrednianie to ma na celu zniwelowanie efektu skakania wyniku pomiaru na LCD.

    Czemu dziwne? To jest zwykły wzór na średnią z N pomiarów tylko przekształcony po to, aby przechowywać tylko jedną wartość a nie wszystkie poprzednie pomiary które bierzemy do średniej.
    Zaczerpnięte z EP 5/2007, artykuł "Jak zbudować kompas elektroniczny z czujnikiem magnetycznym, część 2"
  • #4 9933399
    krru
    Poziom 33  
    Jak rozumiem to ma być taka 'płynąca średnia'
    Liczysz na intach - (1/N) da zero.
    Pamiętaj nie średnią, a sumę N pomiarów. Będzie znacznie większa liczba, i jeszcze całkowita.
    Jak masz kolejny wynik to wykonaj coś takiego.

    suma -= suma/N; // odejmujemy jeden średni wynik
    suma += pomiar;

    Oczywiście lepiej byłoby pamiętać te N ostatnich wyników i zamiast odejmować wartość średnią, odjąć
    najstarszy wynik, ale skoro nie chcesz/nie masz pamieci...


    Edit:
    Kiedyś miałem problem z wynikami z ADC. Chyba były jakieś zakłócenia impulsowe, bo
    co jakiś czas (kilkadziesiąt pomiarów) wychodziła wartość znacznie odbiegająca od pozostałych. Zastosowałem uśrednianie 'sportowe' - 10 pomiarów, odrzucałem 2 skrajne wartości, pozostałe uśredniałem (dzielenie przez 8 jest proste).
  • #5 9933408
    tmf
    VIP Zasłużony dla elektroda
    Problem bierze się stąd, że operujesz na zmiennych całkowitych i to co jest problemem to błędy zaokrągleń, zauważ, że dla kompilatora N jest zmienną całkowitą, efekt operacji 1/2 to wcale nie jest 0.5 tylko 0. Natomiast jeśli ręcznie wpiszesz 0.5 to kompilator już inaczej to traktuje.
  • #6 9933409
    tadzik85
    Poziom 38  
    Primo takie działanie przy małej ilości próbek jest nieopłacalne. Porównaj wielkości kody wynikowego, Fakt kosztem pamięci, ale dla 2 próbek?

    Błędne są typy zmiennych oraz kolejność działań. Obliczenia w twoim przypadku po prostu się ucinają przepełniają.

    a to "0.5" przy liczbach całkowitych to już totalna pomyłka.

    Piszę całkowitych bo nawet stałoprzecinkowych obliczeń nie zaimplementowałeś.
  • #7 9933721
    drzasiek
    Specjalista CNC
    Ja też jakoś ze zdumieniem patrzę po co ty to robisz ale dobra, niech Ci będzie :)
    tmf Ci dokładnie napisał czemu tak się dzieje.
    Masz liczny całkowite więc wynik z każdego działania, czyli u ciebie tutaj te w nawiasie zaokrągla do liczby całkowitej więc Ci się te ułamki potem nie zgadzają jak je zsumujesz, bo ich nie ma po prostu.
    A może gdybyś zrobił taki myk, i przesunął przecinek o 1 miejsce w prawo a po wszystkim powrót?
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #8 9935215
    cobi_69
    Poziom 21  
    Hmmm no dobra zmienię to.
    Co do faktu że lepiej przechowywać poprzednie wartości w tablicy to powiem tak, musiałyby to być wg. mnie co najmniej 4-5 wartości, mam w sumie 4 sygnały z ADC więc razem daje to 20 ostatnich pomiarów a to już jest dużo. Chyba że inny wzór na uśrednianie.
  • #9 9935396
    tmf
    VIP Zasłużony dla elektroda
    Wzór jest bardzo dobry, tylko ilość uśrednień dostosuj do arytmetyki binarnej. Czyli np. 16 próbek, każda po 1/16. Zresztą zamiast dzielenia, na którym tracisz bity, lepiej wynik przemnożyć, uśredniając liczbę o kilka bitów dłuższą, a następnie podzielić całą średnią. W ten sposób unikasz problemu dzielenia wyniku ADC i związanych z tym błędów zaokrągleń.
  • #10 9936096
    cobi_69
    Poziom 21  
    Jeśli dobrze zrozumiałem to chodzi o zmodyfikowanie wzoru w ten sposób:

    srednia = ((N-1) * srednia_p + pomiar_x ) / N

    Nie do końca natomiast zrozumiałem o co chodzi z "16 próbek, każda po 1/16"
  • #11 9936594
    tadzik85
    Poziom 38  
    Chodzi o to by ilość próbek podlegających uśrednianiu była potęgą liczby 2. Dzięki czemu dzielenie przez N można zrealizować przesunięciami bitowymi. AVR nie ma instrukcji dzielenia.
  • #12 10025807
    cobi_69
    Poziom 21  
    Zrobiłem to wg. wyżej zamieszczonych wskazówek i w sumie działa fajnie, ale jest mały minus:
    dla akcelerometru (zakres danych od -90st do +90st) niezależnie do liczby N, dzieje się coś takiego, że jak urządzenie stoi nieruchomo, to co jakiś czas wskakuje 2/3, a myślałem że będzie to na tyle dobre uśrednianie że wskazywane będzie cały czas 0 jak stoi nieruchomo.
REKLAMA