Skocz do zawartości

Uśrednianie wyników pomiarów a typ zmiennej wyjściowej


NieMamKota

Pomocna odpowiedź

Cześć,

mając przetwornik A/C (np. MCP3426) na wyjściu otrzymuję liczbę stałoprzecinkową. Co, jeśli dodam do siebie 4 wyników pomiarów i podzielę ich sumę przez 4. Może się zdarzyć tak, że wynik będzie zmiennoprzecinkowy. Tu, już wchodzimy na arytmetykę zmiennoprzecinkową, często wolniejszą dla mikrokontrolera.

Gdy patrzę na ten problem, zastanawiam się, czy jest sens w ogóle uśredniać w takim wypadku. Jak to rozwiązujecie?

Link do komentarza
Share on other sites

@NieMamKota witam na forum 🙂 Najprościej w takiej sytuacji dzielić przez 4 (lub zrobić odpowiednie przesunięcie bitowe), część po przecinku możesz zwyczajnie pominąć. Nie wiem jakie pomiary będziesz robił i jak bardzo będą do siebie zbliżone, ale przy 16-bitowych danych to uśrednienie, bez części po przecinku też powinno wystarczyć. Oczywiście pomijam sytuację, w której Twoje kolejne pomiary różnią się o 1-2 jednostki i zależy Ci, aby wyciągnąć średnią z tak małych zmian. Wtedy warto spojrzeć na to całościowo, bo może się okazać, że machnięcie ręką nad przewodami wprowadzi większe zachwianie w tych pomiarach niż wszystko inne 😉 

Link do komentarza
Share on other sites

9 godzin temu, NieMamKota napisał:

Gdy patrzę na ten problem, zastanawiam się, czy jest sens w ogóle uśredniać w takim wypadku. Jak to rozwiązujecie?

Uhm... przesyłam dane do komputera, który ma mocniejszy procesor albo mnożę do liczb całkowitych.

Link do komentarza
Share on other sites

9 godzin temu, NieMamKota napisał:

wchodzimy na arytmetykę zmiennoprzecinkową

Niekoniecznie.

Przede wszystkim suma pomiarów musi mieścić się w zmiennej - przy 16-bitowym wyniku musiałbyś użyć 32-bitowej zmiennej.

Załóżmy że z typem sobie poradzisz i po prostu sumujesz wyniki n pomiarów. Możesz traktować to jako pomiar z przetwornika o n * większej rozdzielczości. Możesz np. dla czterech pomiarów zrobić coś takiego:
 

m = wynik >> 2;
n = wynik & 3;

Otrzymasz liczbę stałoprzecinkową z ułamkiem, czyli m + n/4.

Możliwości jest mnóstwo nie angażując floatów.

Jeszcze pytanie: jaki mikrokontroler? Niektóre (np. ESP32) mają sprzętowo rozwiązana arytmetykę float - lub są wystarczająco szybkie, aby czas pojedynczego dzielenia nie grał roli.

 

  • Lubię! 1
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

(edytowany)

Dzięki za odpowiedzi.

 

Mój mikrokontroler to ESP32 C3 (RISC-V).

Badam falę tętna ciśnienia tętniczego krwi. Może faktycznie, nie muszę bazować na floatach. Popróbuję, bo jeszcze dobieram wzmocnienie i zauważę, kiedy wyniki różną się o więcej jednostek.

image.png.291bc692e7b9fdcae59306d618d831fb.png

Z uwagii na wolny przetowrnik zmieniam rozdzielczość na 12 lub 14 bitów. Przy 12 bitach, przy tętnie 60BPM - 1Hz będę mieć 240 pomiarów.

@ethanak

Czy w Twojej metodzie, przy wystąpieniu liczby stałoprzecinkowej, a zastosowanym przesunięciu nie zmienię wartości tej liczby?

int main()
{
    float result;
    int zaokraglone;

    result = 1250.0/64;
    zaokraglone = (int)round(result);
    printf ("%d\n", zaokraglone);
    
    return 0;
}

Czy, żeby dokładniej zaokrąglić wynik, postępuję w następujący sposób?

Jestem ciekaw, dlaczego w tym przypadku nie mam sensownych wartośi po przecinku

int main()
{
    float result;

    result = 1250/64;
    printf ("%f\n", result);
    
    return 0;
}

 

 

Edytowano przez NieMamKota
Link do komentarza
Share on other sites

Bo dzielisz dwa inty, a wynikiem zawsze będzie int, dopiero potem zamieniony na float. Spróbuj np.

result = 1250/64.0;

Poza tym nie bawiłem się nigdy wersją risc, ale jest na tyle szybka że możesz olać czasy wykonania działań.

A w tym zastosowaniu potrzebne jest raczej odrzucanie błędnych pomiarów, a nie uśrednianie.

  • Lubię! 2
Link do komentarza
Share on other sites

A jeszcze jedno.

Jeśli chcesz obliczyć średnią jako int z n wyników, przy czym wszystkie pomiary są nieujemne, najszybsza metoda to

int result = ( suma + n/2)/n;

Jeśli n jest potęgą dwójki, dzielenie możesz zastąpić przesunięciem (chociaż kompilator powinien sam to wyczaić).

Tyle, że ja to robię przy syntezie mowy na 16 kHz i na floatach... i najtańszy lolin lite się trochę nudzi 🙂

  • Lubię! 2
Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.