Generator przebiegów okresowych

0

Witam serdecznie.

Mam do utworzenia generator, generujący przebieg (sinusoidalny, trójkątny, prostokątny) z zakresu 1Hz do minimum 20kHz. W jaki sposób to zrobić? Bezsensownym wydaje mi się utworzenie tablicy 200 000 elementów(żeby przy najwyższej częstotliwości było 10 próbek na okres). Czy lepiej zrobić stałą liczbę próbek na okres, czy stałą tablicę, czy jeszcze inaczej? Chodzi o to, aby po przebiegi były czyste w pełnym paśmie częstotliwości.

Proszę o podpowiedzi, jakieś biblioteki lub przykładowy kod również jest mile widziany:)

0

Czy musisz coś zapisywać? Bo jak nie to wystarczy generować na bieżąco dane za pomocą prostej funkcji. W razie czego wyświetlasz tylko potrzebny zakres. Jeżeli chcesz zapisywać dane do np. pliku to też robisz to na bieżąco.

0

Witam.

Dane są następnie obrabiane jak w oscyloskopie, a więc zmiana amplitudy, częstotliwości itp. a potem wyświetlane na jWindowPanel.

Koziołek napisał(a)

W razie czego wyświetlasz tylko potrzebny zakres.

Co przez to rozumiesz? Możesz jaśniej wytłumaczyć? Nie bardzo wiem jak podejść do tego tematu. Nie chcę przy częstotliwości 20kHz mieć tablicy 200 000 elementów...

0

Jeżeli zakres masz ~1s. co przy 20kHz daje rzeczywiście 20k punktów. Rzecz w tym, że na ekranie wyświetlasz tylko około 1000 punktów. Rozdzielczość i te sprawy ;)

Co można zrobić. Mamy sobie funkcję f(x,y), gdzie x to dana chwila czasu, y częstość. Następnie tworzymy metodę, która zwróci tablicę wartości f(x, y) i jako parametry przyjmuje:

  1. czas początkowy
  2. czas końcowy
  3. częstość funkcji
  4. ilość przedziałów

Ostatni parametr powinien być równy długości wykresu w pikselach. Jeden piksel to jeden przedział

W tym momencie obliczasz ilość wszystkich próbek w przedziale (z częstości) i dzielisz uzyskany wynik na ilość przedziałów. Inaczej mówiąc określasz próbkowanie dla danej funkcji .
Przykład mamy funkcję prostokątną o przebiegu:
0,0.5sek = 0
0.5,1sek = 1.
(1Hz)

Długość wykresu wynosi 100 pikseli, a użytkownik określił, że chce widzieć przebieg w zakresie od 0 do 5 sekund.
Zatem potrzebujemy podzielić przedział 0-5 na 100 przedziałów, gdzie każdy z przedziałów odpowiada jednemu pikselowi długości wykresu. Można zatem łatwo określić, że przedział jest co 0,05 sek.
Zatem:

doubel values[] = new double[100];
for(double i =0.,int j =0; i< 5; i+=0.05, j++){
values[j] = funkcja(i);
}

Kod nie jest przetestowany i może nie działać poprawnie, ale to tylko pewna idea.

W efekcie otrzymasz tablicę 100 wartości odpowiadających kolejnym pikselom na wykresie.

0

Dalej mam problem. Może jutro po pracy "na świeżo" lepiej pójdzie.

Mam tablicę próbek sygnału (wygenerowaną w matlabie). Jest to wzorcowy przebieg sinusoidalny, a tablica ma 8192 elementy. W sumie jeden okres. Szerokość mojego Panelu to 384. Chcę z tej tablicy pobierać za każdym razem 384 próbki, niezależnie od częstotliwości jaką wygeneruję. Chcę generować sygnał od 1Hz do tych 2kHz (na razie - potem sobie ten zakres rozszerzę). Oto co stworzyłem:


    public void sinus(int czestotliwosc, int amplituda, int offset) {
        int j=0;
        double rozdzielczosc = ((sinTab1.length/czestotliwosc)/tablicaProbek.length);
        for(double i = 0.; i<8192;i=i+rozdzielczosc,j++)
        {
            tablicaProbek[j] = sinTab1[(int)i];
        }
    }

sinTab1 - tablica z wzorcowym przebiegiem sinusoidalnym. Tablica ma 8192 elementy.
tablicaProbek - tablica wyjściowa, którą później "obrabiam" i wyświetlam na Panelu.
czestotliwosc - jest to częstotliwość jaką ma mieć sygnał wyjściowy(ten w tablicyProbek)

Kod nie działa poprawnie. Zapewne rozdzielczość, i zakres(chodzi o liczbę 8192 w warunku i<8192) źle obliczyłem. Jak ktoś jest chętny, to poproszę o pomoc.

0

Witam!
Zapominasz o jednym kluczowym parametrze jakim jest częstotliwość próbkowania. Skoro masz docelowo wygenerować sygnał o częstotliwości 20kHz to minimalna częstotliwość próbkowania będzie wynosiła 40kHz. Ponadto nie można mówić o częstotliwości wygenerowanego sygnału jeśli nie poda się częstotliwości próbkowania. Np ten twój jeden okres sinusoidy zapisany w 8192-elementowej tablicy może być 1Hz dla częstotliwości próbkowania 8192 sample/s, albo 10kHz dla częstotliwości próbkowania 81920000 sampli/s.
Do generowania sygnału skorzystaj ze wzoru: y(n) = Asin(2PIfn/fp); gdzie f to częstotliwość sygnału generowanego, fp to częstotliwość próbkowania, n to numer kolejnej próbki.
Pozdrawiam.

0

ja na ADuC831 w C generowałem tak jak niżej (był bardzo wolny przetwornik D/A - patrz tylko na wartość DAC0L). Prostokątny możesz zrobić zmieniając próbki. Jeśli robisz to na szybszym procku to możesz próbki obliczać bezpośrednio.

unsigned char probki_sin[] =
{
   50,
   65,
   78,
   89,
   97,
   100,
   99,
   93,
   84,
   72,
   57,
   43,
   28,
   16,
    7,
    1,
    0,
    3,
   11,
   22,
   35
};

void sinus() // 2kHz
{
  static unsigned char st = 0;
  P3 &= ~(0xE0);
  while (P1>=0xF0) // wcisniete cokolwiek na klawiaturze
   {
    DAC0L = probki_sin[st];
    ++st; st%=21;
   }
}

void pila()
{
  static unsigned char st = 0;
  P3 &= ~(0xE0);
  while (P1>=0xF0)
   {
    DAC0L = st;
    st+=5; st%=115;
   }
}

unsigned char probki_troj[] =
{
    52,
    47,
    42,
    37,
    32,
    27,
    22,
    17,
    12,
     7,
     2,
     3,
     8,
    13,
    18,
    23,
    28,
    33,
    38,
    43,
    48
};

void trojkat()
{
  static unsigned char st = 0;
  P3 &= ~(0xE0);
  while (P1>=0xF0) // wcisniete cokolwiek na klawiaturze
   {
    DAC0L = probki_troj[st];
    ++st; st%=21;
   }
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0