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

Jak usunąć wartości skrajne przy pomiarze napięcia 24-bitowym przetwornikiem?

pawgo2606 20 Kwi 2012 18:04 2620 14
REKLAMA
  • #1 10815546
    pawgo2606
    Poziom 10  
    Witam. robię pomiar napięcia za pomocą przetwornika 24bitowego i mam problem z określeniem wartości maksymalnej i minimalnej dla 5 pomiarów (chcę uśrednić wynik)
    poniżej przedstawiam fragment kodu związany ze zliczaniem pomiarów
    Kod: text
    Zaloguj się, aby zobaczyć kod

    jak wyłuskać informację dotyczącą maksymalnej i minimalnej wartości i je usunąć z pomiaru??
  • REKLAMA
  • #2 10815614
    McMonster
    Poziom 32  
    Zadeklaruj sobie trzy zmienne zainicjowane zerem, jedną na sumę i dwie na element najmniejszy i największy. Przy każdym pomiarze dodawaj go do sumy i sprawdzaj, czy nie jest on największym lub najmniejszym elementem, jeśli tak, to podmień odpowiednią wartość zmiennej. Na końcu odejmujesz od sumy te dwie wartości i dzielisz przez 3 uzyskując średnią.
  • REKLAMA
  • #3 10815839
    tmf
    VIP Zasłużony dla elektroda
    Dla 5 pomiarów to prosto zrobić 5-elementową tablicę działającą jako bufor pierścieniowy. Uśredniając wynik odczytujesz wszystkie elementy, odrzucasz skrajne i voila. BTW. Do liczenia średniej nie potrzebujesz floatów, przecież wynik może być stałopozycyjny.
  • #4 10815856
    pawgo2606
    Poziom 10  
    a w jaki sposób to zrobić dokładnie?? bo za bardzo takich rzeczy nie robiłem...
  • #5 10816606
    hotdog
    Poziom 26  
    Dla tak małej liczby próbek to zrobić dosyć prosto i wydajnie można.

    Max i minium określasz w takich sposób:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Zawsze tylko i w ten sposób. W pierwsza wartość jest zawsze i max i min później sprawdzasz resztę.

    Dla większej liczby próbek do odcięcia zaczynają się schody i nie idzie ego już tak łatwo ogarnąć. Tym bardziej jak ma to być uaktualnione po każdym odczycie z ADC (czyli zawsze bierzesz pod uwagę N ostatnich pomiarów, a nie uaktualniasz wynik co N pomiarów). Poniżej jest mój kod, który jest implementacją średniej ściętej pisaną jakiś miesiąc temu. Napisałem go tak, bo chciałem mieć możliwość łatwej zmiany parametrów (ilość próbek i ilość do odrzucenia). Kod jest nieoptymalny, szczególnie to sortowanie można było by poprawić usuwając najstarszą wartość i wstawiając w posortowaną tablicę nową wartość. W uC starczyło MIPS'ów więc się tym zbytnio nie przejmowałem.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #6 10845807
    pawgo2606
    Poziom 10  
    nie bardzo rozumiem Twój kod..
    mam pierwszy pomiar który wpisuję do zmiennej data_ADS a następnie przypisuję go do max i min. Mam kolejny pomiar i do czego mam go porównać??

    Dodano po 18 [minuty]:

    mam coś takiego

    Kod: text
    Zaloguj się, aby zobaczyć kod
  • REKLAMA
  • #7 10847937
    Konto nie istnieje
    Konto nie istnieje  
  • #8 10848824
    pawgo2606
    Poziom 10  
    Ucinam ostatnie dwa bity bo mam straszne szumy. Pomiar idzie już w pojedyncze uV. mam również pytanie w jaki inny sposób to rozwiązać?? jak mam podzielić nie używając float?? skoro mam wynik który muszę podzielić na rozdzielczość?? (2^24) zakres napięcia wynosi 0 -2,5V. Czy mój zapis określania wartosci średniej jest poprawny??
  • #9 10849005
    mirekk36
    Poziom 42  
    pawgo2606 napisał:
    jak mam podzielić nie używając float?? skoro mam wynik który muszę podzielić na rozdzielczość?? (2^24) zakres napięcia wynosi 0 -2,5V.


    Pomyśl sobie - masz np rozdzielczość 10-bit czyli 1024 czyli

    2,5V / 1024 daje ci 0,002441406V na jeden krok ;) wyobraź sobie ile tracisz na zaokrąglaniu pracując na liczbach typu float. A czym się to będzie różniło jeśli te liczby przed obliczeniami pomnożysz np przez 1 000 000 (milion) albo i więcej - uzyskasz od razu piękną liczbę całkowitą: 2 441 (odrzucając dalszą część ułamkową)

    z tego wynika że można nawet spokojnie pomnożyć nie przez milion a chociażby przez 10 000 ... wtedy będziesz miał 24 albo 244 jeśli pomnożysz * sto tys ;)

    dalej rób dokładnie to samo co byś robił na floatach - ale teraz jak widzisz możesz robić operacje na liczbach bez przecinka ;)

    fakt wyjdzie ci ogromna wartość wyniku - no ale co za problem na końcu podzielić ten wynik z powrotem przez 1000000 albo po kolei przez coraz mniejsze wartości aby uzyskać to co miałeś na początku przed przecinkiem i po przecinku.

    Dostaniesz wtedy dwie liczby całkowite - jedna będzie wyrażała wartość do przecinka a druga po przecinku - jeśli będziesz to potrzebował wyświetlić gdzieś czy wysłać na UART to co za problem zamienić to na ASCII i dodać ręcznie przecinek/kropkę pomiędzy tymi dwoma liczbami

    a wszystkie obliczenia na liczbach całkowitych nie dość że wykonają się dużo szybciej, to jeszcze zaoszczędzisz miejsca w pamięci Flash na kod obsługi tego nie mówiąc o tym, że nadal będziesz miał wysoką precyzję obliczeń i nie będą ci nawet przeszkadzać te dwa ostatnie bity na których masz szumy jak piszesz.
  • REKLAMA
  • #10 10849238
    stanleysts
    Poziom 27  
    @pawgo2606

    "Czy mój zapis określania wartosci średniej jest poprawny?? "
    Nie podoba mi się Twój sposób, wydaje mi się ponadto, że działa źle.
    Czemu sumujesz: suma+=max; a nie np suma+=data_ADS;

    Ja bym to zrobił tak; tablica na wartości z ADC, wyznaczam max, min i wartość średnią, sortuje tablice wartości ( masz teraz max i min na obrzeżach tablicy (łatwo do nich się później odwołać i ewentualnie się pozbyć))

    oto przykładowy kod który na szybko napisałem ( można pewnie to ładniej zrobić ale obrazuje zasadę działania):

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    "jak wyłuskać informację dotyczącą maksymalnej i minimalnej wartości i je usunąć z pomiaru?? "

    jak już wiesz, gdzie znajdują się te wartości to możesz zrobić wartość średnią bez nich (ja zrobiłem z nimi, ale nie wiem jak Ty chcesz) a pozbyć się ich możesz w taki sposób, że bierzesz tylko trzy środkowe elementy posortowanej tablicy.
  • #11 10849648
    bubu2606
    Poziom 15  
    czyli najlepiej zrobić tak: 2,5V/2^24=0,0000001490116119384765625 V, czyli 149011,6119 pV czyli mnożę przez 1 000 000 000 000 000 aby uzyskać 149 011 611 a dalej to już w zależności od pomiaru realizuję operację dzielenia lub wykorzystuję funkcję dtostrf
  • #12 10849765
    stanleysts
    Poziom 27  
    pamiętaj o rozmiarze zmiennych: np int - 32b czyli 2^32 max, większe mnożenia trzeba zrobic np. na long long
  • #13 10850831
    gaskoin
    Poziom 38  
    Cytat:
    Data types:
    char is 8 bits, int is 16 bits, long is 32 bits, long long is 64 bits, float and double are 32 bits (this is the only supported floating point format), pointers are 16 bits (function pointers are word addresses, to allow addressing up to 128K program memory space). There is a -mint8 option (see Options for the C compiler avr-gcc) to make int 8 bits, but that is not supported by avr-libc and violates C standards (int must be at least 16 bits). It may be removed in a future release.


    pamiętaj o liczbach ujemnych ;)
  • #14 10850843
    stanleysts
    Poziom 27  
    Ok, sorry.
  • #15 10850871
    gaskoin
    Poziom 38  
    Nie

    Po pierwsze do 16 jak wynika z manuala do avr-libc
    Po drugie:

    $$-2^{15} \leq x \leq 2^{15} - 1$$
REKLAMA