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:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
WALET – czyli jak buduję sobie transceiver SDR
#36
Większość procesorów esp32 ma 2 rdzenie (0 i 1) ale domyślnie programy dla Arduino działają na rdzeniu 1.
W przypadku programu obsługującego strumienie audio z wykorzystaniem protokołu I2S przetwarzanie danych odbywa się w czasie rzeczywistym z opóźnieniem czasowym związanym z próbkowaniem danych, ich filtracją oraz konwersją a a także manipulacjami.
Z tego względu korzystne jest przeniesienie całej obróbki audio na oddzielny rdzeń a nawet można powiedzieć, że próba uruchomienia wszystkiego na jednym rdzeniu na pewno zakończy się niepowodzeniem.

Dla bardziej dociekliwych wypisałem wcześniej adres w sieci skąd można otrzymać dodatkowe informacje na temat pracy zadań na oddzielnych rdzeniach. W kodzie Waleta są to następujące miejsca (z zachowaniem właściwej sekcji kodu Arduino):

linia 91 -> podstawowa komenta definiująca zadanie dla rdzenia 0
TaskHandle_t Task0;

linie 299-300 -> Szczegółowa definicja środowiska dla zadania w rdzeniu 0. Istotnym parametrem jest wielkości pamięci -> tu 100000 i z tą wartością można eksperymentować dobierając ją do zadania działającego na tym rdzeniu
//create a task that executes the Task0code() function, with priority 1 and executed on core 0
xTaskCreatePinnedToCore(Task0code, "Task0", 100000, NULL, 1, &Task0, 0);

linie 752-777 -> szczegółowa definicja poleceń działających w rdzeniu 0
//core 0 definition
void Task0code(void * pvParameters) {
  //Serial.print("Task0 running on core ");
  //Serial.println(xPortGetCoreID());
  for ( ; ; ) {
    //Serial.println("Core 0 processing");
    //delay((int)random(100, 1000));
    copier.copy();
    if (isFilterChanged == true){
      if (Filter_index == 0){
        inFiltered.setFilter(0, new FilterChain<float, 2>({new BiQuadDF2<float>(b_lpf24_36,a_lpf24_36), new FIR<float>(hilbert_24_81)}));
        inFiltered.setFilter(1, new FilterChain<float, 2>({new BiQuadDF2<float>(b_lpf24_36,a_lpf24_36), new FIR<float>(coeffs_delay_81)}));
      }
      else if (Filter_index == 1){
        inFiltered.setFilter(0, new FilterChain<float, 2>({new BiQuadDF2<float>(b_lpf24_24,a_lpf24_24), new FIR<float>(hilbert_24_81)}));
        inFiltered.setFilter(1, new FilterChain<float, 2>({new BiQuadDF2<float>(b_lpf24_24,a_lpf24_24), new FIR<float>(coeffs_delay_81)}));
      }
      else if (Filter_index == 2){
        inFiltered.setFilter(0, new FilterChain<float, 2>({new BiQuadDF2<float>(b_bpf24_8_6,a_bpf24_8_6), new FIR<float>(hilbert_24_81)}));
        inFiltered.setFilter(1, new FilterChain<float, 2>({new BiQuadDF2<float>(b_bpf24_8_6,a_bpf24_8_6), new FIR<float>(coeffs_delay_81)}));
      }
      isFilterChanged = false;
    }
    delay(1);
  }
}



Zadanie dla rdzenia 0 definiuje się jako pętla for (linia 756).W pętli działają w zasadzie trzy polecenia/funkcje:
copier.copy();
-> linia 759, wymienione wcześniej polecenie Audio Tools odpowiedzialne za organizację i przepływ danych audio
if (isFilterChanged == true) -> linia 760, polecenie spradzenia czy podczas odbiory zażądano zmiany filtra LPF lub BPF
delay(1); -> linia 775 czyli opóźnienie 1ms. Okazuje się, że bez tego polecenie całość nie działa. Opóźnienie rzędu 1ms nie ma wpływu na działanie copier.copy() ale mam zamiar przetestować inne, szczególnie mniejsze wartości opóźnienia.

Ze względu na wyjazd na kilka dni (będę dopiero po 20 sierpnia) starałem się zakończyć opis jeszcze przed wyjazdem aby umożliwić zrozumienie zarówno budowy jak i funcjonowania kodu konstrukcji Waleta.
Mam świadomość, że zadanie, choć mocno zaawansowane, ciągle jest w toku więc proszę o tym pamiętać podejmując np. krytykę pewnych rozwiązań. Na konstruktywną krytykę z resztą liczę, tym bardziej, że projest ma charakter otwarty, mocno eksperymatalny i jak wspominałem, do zrobienia jest co najmniej arw, odczyty swr i mocy, ewentualny "wodospad" a także kosmetyka całości kodu a wszczególności usunięcie niepożądanego zjawiska przenoszenia sygnału audio podczas przechodzenia z nadawania na odbiór. Ponieważ cyfrowy tor audio pracuje bez przerwy, niezależnie czy to odbiór czy nadawanie, a w systemie występuje opóźnienie związane z cyfrową obróbką sygnału to w momencie kiedy układ przechodzi elektrycznie (przekaźniki) z nadawania na odbiór podczas pracy ssb ma w buforze ostatnie kilkadziesiąt ms transmisji z nadawania i odbiornik najpierw odtwarza tą resztkę a następnie przechodzi do zwykłego odbioru korespondenta.
Mam co najmniej dwa pomysły jak to zlikwidować. Po pierwsze przez manipulację w kodzie programu narzędziami Audio Tools a po drugie w sprzęcie po prostu blokując wzmacniacz odbiornika na czas działania w torze opisanej resztki sygnału nadawania.

Opóźnienie cyfrowe przetwarzania sygnałów jest bardzo widoczne podczas odsłuchu własnego sygnału na zewnętrznym odbiorniku. W tradycyjnych transceiverach słyszy się własny głos w słuchawce odbiornika równocześnie z wypowiadanymi słowami. W urządzeniach z cyfrową obróbką może być słyszalne w odbiorniku opóżnienie własnego głosu co jest nieco irytujące dla mnie i zwykle łapię się na tym, że odruchowo spowalniam wymowę jakbym chciał doprowadzić do synchronizacji obo sygnałów co jest oczywiście niemożliwe ;-). Oczywiście z punktu widzenia korespondenta takie efekty nie mają znaczenia i nie będą widoczne a przy pracy cw nie występują.

Jak pisałem, podczas nieobecności będę mniej dostępny ale każdego wieczora postaram się tu zajrzeć więc jeśli pojawią się pytania lub jakaś dyskusja to włączę się w miarę możliwości. A jak zdążę to jeszcze dziś dopiszę w jaki sposób uzyskać w si5351 przesunięcie w fazie o 90 stopni dla sygnałów F0 i F1.

cdn.  lj

Github
Cytuj


Wiadomości w tym wątku
RE: WALET – czyli jak buduję sobie transceiver SDR - przez SP6FRE - Wczoraj, 13:48

Skocz do:


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