Skocz do zawartości

Pomocna odpowiedź

4 godziny temu, ethanak napisał:

No - w ten sposób to na 100% nie osiągniesz takiej prędkości. Zamiast dwóch przesyłasz w porywach sześć bajtów na próbkę (bo przecież to robi println, prawda?).

 

 

Wow, dzięki. Tego akurat nie miałem pojęcia, że tak się dzieje

a) odpada, potrzebuję próbki 10bit

b) nie znałem tej funkcji, dzięki za pomoc

Robisz także jakies głupie rzeczy z synchronizacją produkcji i konsumpcji danych. Albo transmisja jest szybsza niż napływ danych i wtedy wystarczy bufor na kilka próbek (a w szczególnym przypadku na jedną), albo transmisja jest wolniejsza i wtedy żaden bufor, nawet 500- miejscowy nie pomoże bo i tak w końcu sie zapełni a system nigdy nie będzie nadążał za czasem rzeczywtstym. Tu akurat wystarczy zwykły semafor (znacznik 1-bitowy) ustawiany przez odczyt ADC a zerowany po wysłaniu danych przez UART oraz jeden wspólny uint16_t przechowujący ostatni odczyt ADC. Wtedy ISR() nie wpisuje tam nowych danych jeśli widzi, że poprzednie nie zostały odczytane i wysłane (próbka została stracona), a fukcja wysyłania nie wysyła dopóki ISR() nie umieścił nowej danej w umówionym miejscu. W takim przypadku nie potrzeba nawet operacji atomowych, choć warto o nich (i w ogóle o synchronizacji procesów) poczytać.

Przy prędkości 115200 przesyłasz jedynie 11520 bajtów danych na sekundę a jeśli zajmiesz dwa na jedną próbkę (to było jasne od początku, żadne tam transmisje znakowe w ASCII) to wychodzi 5760 próbek/s. To jest górne ograniczenie i wychodzi z tego, że jeśli niczego nie zmienisz to to jest sufit: musisz zejść z pasmem sygnału do 2.5kHz. Pewną poprawę możesz uzyskać jeśli wykorzystasz fakt, że próbki mają tylko 10 bitów. Zamiast przesyłać 4 bity "puste" w każdej 2-bajtowej próbce, możesz je upakować tak, by 4 kolejne próbki (czyli 40 bitów danych) zajmowały tylko 5 pełnych bajtów transmisji zamiast 8. Wtedy baudrate 115200 pozwalająca na przesłanie 92160 bitów/s zamienia się wprost na 9216 próbek 10-bitowych na sekundę a to już prawie Twój cel. Nie wiem tylko, czy tak skompresowane dane będą czytelne dla drugiej strony. Musiałbyś samodzielnie napisać kawałek kodu obsługujący port szeregowy i zamieniający kaszanę z niego przychodzącą na sensowne int-y udostępniane komuś dalej.

A co to za sygnał? Jakieś audio? Co chcesz z nim robić na PC? Może część obliczeń da się przenieść do Arduino i tym samym odciążyć kanał komunikacyjny? Możesz uchylić rąbka tajemnicy? A może wystarczy użyć innej aplikacji do odbioru i obróbki? Podniesienie prędkości do 250 lub 500k rozwiązuje chyba wszelkie problemy? Pomyśl może o zakupie Arduino w wersji z budowanym USB w procesor: jakieś Leonardo czy coś. Tam nigdzie po drodze między prockiem a PC nie ma rzeczywistego UARTa więc transmisja jest zawsze szybka, niezależnie od ustawień wirtualnego portu COM. Osiągne prędkości to kilkanaście kilobajtów/s więc też nie powalają choć jest szansa, że się zmieścisz.

BTW: Cóż, postawiłeś obie nierealne założenia: ilość danych trudna do przesłania w tych konkretnych warunkach. Może trzeba było wykonać proste obliczenia zanim się za to zabrałeś?

  • Lubię! 1
13 minut temu, marek1707 napisał:

Zamiast przesyłać 4 bity "puste" w każdej 2-bajtowej próbce, możesz je upakować tak, by 4 kolejne próbki (czyli 40 bitów danych) zajmowały tylko 5 pełnych bajtów transmisji zamiast 8

Teoretycznie - w praktyce będzie zawsze problem z rozpakowaniem po stronie odbiorcy (synchronizacja). Natomiast umieszczenie dwóch próbek w trzech bajtach z autosynchronizacją już jest całkowicie realne (najstarczy bit służy do synchronizacji, 3x7 daje 21 czyli zostaje jeszcze jeden bit wolny - np. na sumę kontrolną).

 

  • Lubię! 1

Oczywiście, zapełnienie kanału na 100% danymi binarnymi bez szans na resynchronizację to zły pomysł. Chciałem pokazać opcję "push to the limit". Każda poprawa funkcjonalności będzie wymagała zejścia z pasmem danych. Tak samo jest z samą prędkością. Jeżeli mamy nawet i te 115200, ale z niezerowym błędem to wypadałoby liczyć się z marginesem kilku procent. Te moje wyliczone 11520 bajtów/s jest raczej teoretyczne a z kolei ADC nie może być ustawiony "na styk" z produkcją próbek.

BTW: Regulację prędkości ADC nie musisz robić jedynie przez zmianę jego podzielnika lub (co gorsza) pomijanie co którejś próbki. Zegar ADC wyznacza raczej szybkość samej konwersji i jakość pracy tego bloku i wg. rekomendacji producenta powinien być w zakresie 100 do 200kHz (jeśli chcesz utrzymać dokładności 10-bitowe, bo ADC działa także i na 1MHz). Puszczanie ADC w trybie free_run to bardzo prymitywna metoda. Rzeczywisty sample rate w takich wypadkach bardzo prezycyjnie ustalasz wyzwalając start konwersji sprzętowo np. przepełnieniem lub komparacją któregoś timera (patrz bity ADTS w rejestrze ADCSRB).

  • Lubię! 1

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...