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

Jak obliczyć: 'b'? Chodzi o aproksymację trygonometryczną.

TvWidget 12 Sie 2021 22:13 852 21
  • #1 19561710
    TvWidget
    Poziom 39  
    Posty: 4427
    Pomógł: 472
    Ocena: 700
    Załóżmy, że napięcie zmienia się okresowo w czasie można go opisać funkcją U(t)=a*sin(t+b) gdzie a i b to stałe wartości. Mam zbiór próbek pomiarowych tego napięcia (są to pary liczb U i t). Jak na ich podstawie obliczyć b ?
  • #2 19561766
    Konto nie istnieje
    Poziom 1  
  • #3 19561828
    krzysiek_krm
    Poziom 40  
    Posty: 4612
    Pomógł: 716
    Ocena: 599
    TvWidget napisał:
    Załóżmy, że napięcie zmienia się okresowo w czasie można go opisać funkcją U(t)=a*sin(t+b) gdzie a i b to stałe wartości. Mam zbiór próbek pomiarowych tego napięcia (są to pary liczb U i t). Jak na ich podstawie obliczyć b ?

    Ja bym kombinował z analizą miejsc zerowych.
  • #4 19561839
    Konto nie istnieje
    Poziom 1  
  • #5 19561848
    piotrek0207
    Poziom 20  
    Posty: 379
    Pomógł: 35
    Ocena: 70
    Jeszcze trzeba pamiętać, że argumentem sinusa nie jest tylko t, a omega*t - pulsacja*t. Musimy znać częstotliwość przebiegu. B to będzie jakieś przesunięcie fazowe.
  • #6 19561944
    Maciej Gonet
    Specjalista - VBA, Excel
    Posty: 2207
    Pomógł: 824
    Ocena: 481
    TvWidget, dlaczego nie dałeś przykładowych danych?
    Czy jesteś pewien, że w Twoim wzorze nie brakuje częstości ω?
    Generalnie jest to problem regresji nieliniowej i np. w Excelu można go rozwiązać za pomocą Solvera.
    Przykład w załączniku. Użyłem danych symulowanych, do których wprowadziłem losowe zaburzenie wartości U. Formuła z komórki B2 została użyta w kolumnie B, a następnie zamieniona na wartości.
    Do tego dopasowałem gładką krzywą w kol. C. Sumę kwadratów odchyleń zminimalizowałem Solverem, zmieniając wartości w komórkach I1:I2. Gdyby jednak była potrzebna też ω, to trzeba dodać trzeci parametr w analogiczny sposób.
    Na wykresie widać punkty użyte do symulacji (niebieskie) i dopasowaną linię (pomarańczową).
    Załączniki:
    • Model_sinusoidy.xlsx (15.96 KB) Musisz być zalogowany, aby pobrać ten załącznik.
  • #7 19561995
    TvWidget
    Poziom 39  
    Posty: 4427
    Pomógł: 472
    Ocena: 700
    Nie potrzebuję policzyć tego w Excelu tylko zaimplementować algorytm w uP.
    Częstotliwość ω to jedynie parametr. To czy we wzorze jest ωt czy samo t nie ma znaczenia.
    Zdaje się, że kiedyś rozwiązanie identycznego problemu znalazłem w książce "Metody numeryczne". Algorytm był dość prosty. Wartości próbek były jakoś mnożone przez cos(t) i sin(t). Coś było sumowane i uzyskiwało się wartości a i b.
    W transformacie Fouriera sygnał można przybliżyć sumą funkcji okresowych. W tym wypadku sprawa jest prostsza. Chodzi o przybliżenie tylko jedną funkcją okresową.
  • #8 19564985
    _jta_
    Specjalista elektronik
    Posty: 49148
    Pomógł: 3212
    Ocena: 4260
    TvWidget napisał:
    Wartości próbek były jakoś mnożone przez cos(t) i sin(t).

    Dokładnie. Potem to się sumuje (oddzielnie z mnożenia przez cos(t) i sin(t)), dostajesz dwie liczby - nazwijmy je Uc i Us. Dalsze dwie wyliczasz sumując kwadraty cos(t) i sin(t) dla tych samych 't' - one będą potrzebne do znormalizowania pierwszych dwu, nazwijmy je Nc i Ns. Na koniec liczysz a=sqrt((Uc/Nc)^2+(Us/Ns)^2), b=atan2(Us/Ns,Uc/Nc). Myślę, że to zadziała.

    Okazuje się, że to jest bardziej skomplikowane, i trzeba wyliczyć jeszcze jedną sumę: cos(t)*sin(t). Teraz sumy bez U nazwałem 'cc', 'cs', 'ss', i zamiast 'U' mam 'v'.
    Kod: Tcl
    Zaloguj się, aby zobaczyć kod

    Na końcu programu dla sprawdzenia policzyłem iloczyn macierzy - to wymaga odwracania macierzy:
    Kod: less
    Zaloguj się, aby zobaczyć kod
    (jest symetryczna 2x2, więc łatwo - poprzestawiać, zmienić znak 'cs' i podzielić przez wyznacznik)
  • #9 19565283
    Konto nie istnieje
    Poziom 1  
  • #10 19565286
    Maciej Gonet
    Specjalista - VBA, Excel
    Posty: 2207
    Pomógł: 824
    Ocena: 481
    Tej metody, którą podał _jta_, nie znałem. Daje ona dobre wyniki aproksymacji, choć nieco inne niż przy metodzie najmniejszych kwadratów. Widocznie tam zastosowano inne kryterium.
    Metodę najmniejszych kwadratów można też zastosować bezpośrednio, bez pomocy Solvera. Opiera się to na wykorzystaniu wzoru na sinus sumy:
    Kod: Text
    Zaloguj się, aby zobaczyć kod

    W Excelu trzeba utworzyć kolumny sin(t) i cos(t) i potraktować je jak zmienne niezależne w analizie regresji liniowej. Otrzymuje się wyniki takie same jak przy użyciu Solvera.
    Jest też jeszcze metoda przybliżona, w której amplitudę a szacuje się na podstawie różnicy między wartością maksymalną a minimalną, a wartość b na podstawie punktu przejścia funkcji przez 0. Ta metoda wymaga, żeby przebieg obejmował maksimum i minimum sinusoidy oraz żeby nie był mocno zakłócony.
    Trzeba też pamiętać, że b jest określone z dokładnością do stałej, bo funkcja sinus jest okresowa. Z reguły wybiera się przedział [-pi, +pi] albo [0, 2*pi]. Nie podałeś, który to ma być wariant.
    W pliku przykłady w Excelu. To musisz sobie przetłumaczyć na swój język.
    Załączniki:
    • Model_sinusoidy5.xlsx (21.07 KB) Musisz być zalogowany, aby pobrać ten załącznik.
  • #11 19565337
    StaryVirus_e_Wiarus
    Poziom 21  
    Posty: 329
    Pomógł: 48
    Ocena: 69
    Cześć
    Kompilator powinien mieć możliwość i udostępniać bibliotekę <math.h>. W niej jest zapewne udostępniona funkcja "arcsin(X)". Wzór z postu #4 miałby tu zastosowanie.
  • #12 19565343
    _jta_
    Specjalista elektronik
    Posty: 49148
    Pomógł: 3212
    Ocena: 4260
    khoam napisał:
    Ten soft to ma pracować na µP, a nie wielordzeniowym Intel czy AMD

    Zawsze można przetłumaczyć na C, np. set s [expr { sin($tpi*$t) }]; => s=sin(tpi*t);. Ale trzeba mieć funkcje trygonometryczne i pierwiastek kwadratowy.
  • #13 19565346
    Konto nie istnieje
    Poziom 1  
  • #16 19566919
    _jta_
    Specjalista elektronik
    Posty: 49148
    Pomógł: 3212
    Ocena: 4260
    W tym artykule pomiary napięcia wykonuje się w równych odstępach czasu ∆T - czy takie ma być założenie? Mój sposób działa bez takiego wymogu, odstępy czasu mogą być prawie dowolne (byle nie wielokrotności połowy okresu, bo wtedy wyznacznik macierzy wyjdzie 0, a trzeba wykonać dzielenie przez ten wyznacznik; a najlepiej, jakby były po ćwierć okresu, wtedy można prościej). Ale za to w tym artykule wyznacza się fazę i amplitudę zakłóceń, aby odjąć zakłócenia od sygnału użytecznego - tego z kolei nie daje mój sposób.
  • #17 19567029
    rb401
    Poziom 39  
    Posty: 3003
    Pomógł: 750
    Ocena: 984
    TvWidget napisał:
    W transformacie Fouriera sygnał można przybliżyć sumą funkcji okresowych. W tym wypadku sprawa jest prostsza. Chodzi o przybliżenie tylko jedną funkcją okresową.


    No to w sam raz do tego celu pasuje Ci algorytm Goertzela, taki właśnie "jednoprążkowy FFT". Tym bardziej że jest bardzo mało obciążający obliczeniowo, nie wymaga konieczności zbierania próbek w tablicy, ani innych operacji na tablicach, w sam raz nawet na słabe uC.

    Tu ładnie opisany algorytm i praktyczne wskazówki o dobraniu wielkości okna:

    https://www.embedded.com/the-goertzel-algorithm/

    a tu źródła do przykładu z tego artykułu:

    https://github.com/pramasoul/jrand/blob/master/goertzel.c

    Z ciekawości dodałem tam tylko instrukcję "angle = atan2(imag, real);" i miałem policzoną fazę.
    Z testów mi wyszło że regulując fazę w funkcji generacji próbek, z algorytmu dostaję w wyniku precyzyjnie (do trzeciego miejsca po przecinku dla kąta w radianach) fazę która zadaję.
    Jedyny problem jaki widzę to konieczność "skalibrowania" zera fazy względem początku bloku próbek (lub innego arbitralnie wybranego punktu bloku próbek).
    W tym przykładzie jeśli blok próbek zaczynał się od próbki sin(0), jak oryginalnie to robi funkcja Generate(), w wyniku pozyskanym z algorytmu pomierzona faza nie wychodziła zerowa. Akurat dla danych w tym przykładzie gdy dodałem do generacji sinusa stały offset równy 1.9544rad (nie wnikam dlaczego akurat tyle) to już wartości fazy zadane w generacji próbek i pomierzone przez algorytm były liczbowo identyczne.
  • #18 19567051
    StaryVirus_e_Wiarus
    Poziom 21  
    Posty: 329
    Pomógł: 48
    Ocena: 69
    Można też wartości kątów i sinusa (arcsin) ująć w tabelce dwuwymiarowej i prostą instrukcją przeszukiwać taką tabelę. A najbliższe wartości aproksymować lub uśrednić do najbliższej właściwego wartości. Trzeba to wykonać z założonym błędem obliczeń.
  • #19 19567279
    _jta_
    Specjalista elektronik
    Posty: 49148
    Pomógł: 3212
    Ocena: 4260
    Wciąż pozostaje otwarta sprawa: jakie są odstępy czasów pomiędzy próbkami? Jeśli można mieć stałe i dostosować je do potrzeby wyliczania, to jest prościej.

    Przykładowe wyniki dla mojego programu (częstotliwość jest 1, częstość 2pi): zadane a=12 b=0.123 t1=0.1 t2=0.4; wyliczone a=12.0 b=0.12300000000000001.

    Błąd na poziomie 10^(-17) - ale tak wychodzi, jak do wyliczania podaje się dokładne wygenerowane wartości, a różnica czasów jest bliska T/4.
    Przykładowy wynik dla "gorszych" parametrów: a=12 b=0.123 t1=0.06 t2=0.10 t3=0.55 => a=12.000000000000027 b=0.12300000000000019.

    Jest jeszcze kwestia, czy stablicowanie sin() i cos(), a potem interpolacja (albo użycie wzorów na sin() i cos() sumy kątów, dla małych kątów można przyjąć sin(x)=x, cos(x)=1-x^2/2) daje oszczędność czasu procesora przy wyliczaniu, czy nie. Dla kąta 30° znamy ze szkoły sin() i cos(); dla kąta 18° można je wyliczyć z konstrukcji pięciokąta foremnego; wykorzystując wzory na sin() i cos() sumy i różnicy kątów, oraz połowy kąta można je stablicować np. co 3°.
  • #20 19569361
    TvWidget
    Poziom 39  
    Posty: 4427
    Pomógł: 472
    Ocena: 700
    Chyba udało mi się znaleźć algorytm. Wydaje się jednak dziwnie prosty.
    Załóżmy, że mamy 20 próbek danych. W poniższym kodzie generuje te 20 próbek testowo zmieniając fazę o 0.1.
    Różnica pomiędzy przyjętą wartością fazy a obliczoną nie przekracza 0.01.
    for (fi=0;fi<3;fi=fi+0.1){
    a=0;
    b=0;
    for (i=1;i<20;i++){
    y=Math.sin(i+fi); //testowe próbki

    a=a+y*Math.cos(i)
    b=b+y*Math.sin(i)
    }
    console.log(fi-Math.atan2(a,b));
    }
    }
  • #21 19569712
    _jta_
    Specjalista elektronik
    Posty: 49148
    Pomógł: 3212
    Ocena: 4260
    To jest rzeczywiście za proste. Działa w miarę dobrze, jeśli sumy kwadratów sin(i) i cos(i) są zbliżone, a suma ich iloczynów jest bliska 0.

    Jak zrobisz próbkowanie sygnału co π/4, i weźmiesz parzystą liczbę próbek, to wynik będzie dokładny (na ile dokładne będą obliczenia).
  • #22 19571495
    rb401
    Poziom 39  
    Posty: 3003
    Pomógł: 750
    Ocena: 984
    TvWidget napisał:
    Chyba udało mi się znaleźć algorytm. Wydaje się jednak dziwnie prosty.


    Ok, działa, bo w zasadzie musi. Liczysz po prostu korelacje próbek z zadanym sinusem i kosinusem, tak z definicji.
    Ale jednak masz jeszcze dość ciężki obliczeniowo algorytm. Na każdą próbkę liczysz sinus i kosinus i masz dwa mnożenia.
    Co prawda sinus można wstępnie stablicować.
    Ale jeśli to ma chodzić na mniej wydajnym sprzęcie to jednak Twój algorytm mocno przegrywa z Goertzelem, który to samo wylicza ale na każdą próbkę jest potrzebne tylko jedno mnożenie a żadnej tablicy nie potrzeba. Wystarczą tylko trzy stałe jako kompletna nastawa pomiaru. No i też Goertzel jest opisany w pełni, sprawdzony przez lata i mnóstwo o nim informacji, i przykładów implementacji.

Podsumowanie tematu

LABEL_AI_GENERATED
W dyskusji poruszono problem obliczania przesunięcia fazowego 'b' w funkcji U(t)=a*sin(t+b) na podstawie próbek napięcia. Uczestnicy sugerowali różne metody, w tym analizę miejsc zerowych, wykorzystanie funkcji arcsin oraz metody regresji nieliniowej, takie jak metoda najmniejszych kwadratów. Podkreślono znaczenie częstotliwości sygnału oraz konieczność uwzględnienia pulsacji w obliczeniach. Wskazano na algorytm Goertzela jako efektywną metodę do obliczeń na mikrokontrolerach, ze względu na niskie wymagania obliczeniowe. Zwrócono uwagę na potrzebę kalibracji oraz na różnice w wynikach w zależności od metody aproksymacji.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA