To forum używa plików cookies
To forum wykorzystuje pliki cookies do przechowywania informacji o Twoim logowaniu, jeśli jesteś zarejestrowany, oraz informacji o Twojej ostatniej wizycie, jeśli nie jesteś zalogowany. Pliki cookies to niewielkie pliki tekstowe zapisywane na Twoim komputerze; cookies ustawiane przez to forum mogą być używane wyłącznie na tej stronie i nie stanowią zagrożenia dla bezpieczeństwa. Cookies na tym forum śledzą również, które tematy zostały przez Ciebie przeczytane oraz kiedy miało to miejsce. Prosimy o potwierdzenie, czy akceptujesz, czy odrzucasz zapisywanie tych plików cookies.

Niezależnie od wyboru w Twojej przeglądarce zostanie zapisany plik cookie, aby zapobiec ponownemu zadawaniu tego pytania. W każdej chwili będziesz mógł zmienić ustawienia cookies, korzystając z linku w stopce strony.

Ocena wątku:
  • 1 głosów - średnia: 5
  • 1
  • 2
  • 3
  • 4
  • 5
WALET – czyli jak buduję sobie transceiver SDR
#56
Mam postęp w zakresie modułu fft, który posłuży do budowy "wodospadu" lub innej formy obrazowania zawartości otoczenia odbieranego sygnału. 
Piszę o otoczeniu bo zakres analizy jest ograniczony twierdzeniem Nyquista-Shannon-a o próbkowaniu co w skrócie oznacza, że uda się "zauważyć" jedynie te składniki w sygnale, których częstotliwość jest dwukrotnie mniejsza niż częstotliwość próbkowania. 
W przypadku kodu Waleta, który działa z częstotliwością próbkowania 24kHz, fft dostarczy informacji o sygnałach co najwyżej 12kHz.
Nie wchodząc w szczegóły należy wstępnie zapewnić aby do członu cyfrowego przetwarzania nie docierały sygnały o częstotliwościach większych niż 12kHz co powinny zapewnić wzmacniacze w torze analogowym między mieszaczem Tayloe a procesorem lub należy użyć w części cyfrowej na wejściu odpowiedni, cyfrowy filtr dolnoprzepustowy. W przypadku Waleta zastosowany jest pierwszy z tych sposobów za pomocą R8/C8 i R9/C10 (płytka ha).
Dotychczasowe przetwarzanie sygnały działa według schematu:

Kod:
i2s -> FilteredStream -> VolumeMeter -> i2s


gdzie:
i2s z lewej to w uproszczeniu wejście a/d
FilteredStream to ciąg filtrów cyfrowych (Hilbert + lpf/bpf)
VolumeMeter to moduł pomiaru siły sygnału
i2s z prawej to w uproszczeniu wyjście d/a

a odpowiednie polecenia w kodzie programu są następujące:

Kod:
uint16_t sample_rate = 24000;
uint16_t channels = 2;
uint16_t bits_per_sample = 16;  // or try with 24 or 32
AudioInfo info(sample_rate, channels, bits_per_sample); //ogólne definicje przetwarzania cyfrowego
...............
I2SStream i2s;
FilteredStream<int16_t, float> inFiltered(i2s, channels); //uruchomienie filtrowania z danymi od konwertera a/d
VolumeMeter volumeMeter(inFiltered); //pomiar siły sygnału przefiltrowanych danych
StreamCopy copier(volumeMeter, i2s); //uruchomienie procesu transferu danych z wejścia a/d do sekcji filtrów cyfrowych
................
void setup(void) {
.......................
inFiltered.setFilter(0, new FilterChain<float, 2>({ new BiQuadDF2<float>(b_lpf24_36, a_lpf24_36), new FIR<float>(hilbert_24_81) })); //definicja filtrowania dla kanału 0
inFiltered.setFilter(1, new FilterChain<float, 2>({ new BiQuadDF2<float>(b_lpf24_36, a_lpf24_36), new FIR<float>(coeffs_delay_81) })); //definicja filtrowania dla kanału 1
volumeMeter.begin(info); //uruchomienie procesu pomiaru siły sygnału
.....................
}



Wprowadzenie fft wymaga rozdzielenia sygnału do czego w Arduino Audio Tools można wykorzystać klasę MultiOutput a odpowiedni schemat przetwarzania danych będzie wyglądał następująco:

 
Kod:
        fft
          .
i2s -> multiOutput
          .
          inFiltered -> volumeMeter -> i2s

         
Tak więc sygnał analogowy "wczytany" do procesora przez konwerter a/d (moduł i2s) zostaje podzielony na dwie kopie z których jedna służy wyłącznie do zasilania modułu fft a druga to opisany wcześniej przebieg związany z filtrowaniem (Hilbert + lpf/bpf), pomiarem siły sygnału (volumeMeter) oraz konwersji d/a do postaci analogowej (i2s).

Odpowiednie polecenia wraz z ich logicznym następstwem pokazuje poniżej:
       
Kod:
AudioRealFFT fft; //utworzenie instancji fft
I2SStream i2s;
MultiOutput multiOutput; //utworzenie instancji MultiOutput o nazwie multiOutput
StreamCopy copier; //utworzenie instancji kopiowania danych strumienia i2s
VolumeMeter volumeMeter; utworzenie instancji VolumeMeter o nazwie volumeMeter
FilteredStream<int16_t, float> inFiltered; //utworzenie instancji filtrów o nazwie inFiltered

void setup(void) {
.........

inFiltered.begin(info); //uruchomienie inFiltered
inFiltered.setFilter(0, new FilterChain<float, 2>({ new BiQuadDF2<float>(b_lpf24_36, a_lpf24_36), new FIR<float>(hilbert_24_81) })); //definicja filtrowania dla kanału 0
inFiltered.setFilter(1, new FilterChain<float, 2>({ new BiQuadDF2<float>(b_lpf24_36, a_lpf24_36), new FIR<float>(coeffs_delay_81) })); //definicja filtrowania dla kanału 1
inFiltered.setOutput(volumeMeter); //skierowanie danych z inFiltered do volumeMeter
volumeMeter.begin(info); //uruchomienie volumeMeter
volumeMeter.setOutput(i2s); //skierowanie danych z pomiaru do wyjścia d/a
multiOutput.add(fft); //połączenie pierwszego wyjścia multiOutput z modułem fft
multiOutput.add(inFiltered); //połączenie drugiego wyjście multiOutput z modułem filtrowania
multiOutput.begin(info); //uruchomienie podziału sygnału
copier.begin(multiOutput,i2s); /start transferu danych z wejścia i2s do dzielnika multiOutput
.......
}


Okazało się, że krytyczna jest kolejność poleceń szczególnie dla inFiltered. Aby filtrowanie działało od startu tego modułu należy go najpierw uruchomić poleceniem inFiltered.begin(info); a kolejno trzeba zdefiniować sposób filtrowania poleceniami inFiltered.setFilter(...);

cdn lj.

Github
Cytuj


Wiadomości w tym wątku
RE: WALET – czyli jak buduję sobie transceiver SDR - przez SP6FRE - 03-10-2026, 10:38

Skocz do:


Użytkownicy przeglądający ten wątek: 3 gości