Jaką prędkość transmisji mogę przejść (bez błędów)?

40

Standardowo wynosi 9600 bodów. To tylko standard . Używając Arduino Uno SMD R2, jaka jest najwyższa praktyczna prędkość transmisji, jaką mogę osiągnąć?

Punkty bonusowe dla zuchwałych: Jak byś zajął się stworzeniem mechanizmu sprawdzania błędów, a następnie zwiększeniem absurdalnie wysokiej prędkości transmisji, aby uzyskać wysokie prędkości transferu?

Anonimowy pingwin
źródło
1
Warto zauważyć, że płyty Arduino, które korzystają z szeregowych układów scalonych USB FTDI, mogą NAPRAWDĘ działać szybko. Zwykły FT232 może przejść do 3 megabajtów (to 3 000 000 bodów) bez problemów. Zastosowanie ATmega16U2 jest czynnikiem ograniczającym.
Connor Wolf,
Mój klon Arduino Nano, który otrzymałem z serwisu eBay, wyniósł maksymalnie 1 099 999. Poważnie. Tak się stało. Po osiągnięciu 1 100 000 wyników był zniekształcony. laqq`na`fca`fga`fga`bcngaah````iin`ha`a`a`bga`fga`bcqpahhqfq```fh`oopa`bca`fca. Wykorzystuje układ CH340 do komunikacji USB.
PNDA

Odpowiedzi:

59

Jest tu kilka czynników:

  • Jaką prędkość transmisji może osiągnąć MCU ATmega328P?
  • Jaką prędkość transmisji może osiągnąć interfejs szeregowy USB?
  • Jaka jest częstotliwość oscylatora w ATmega328P?
  • Jaka jest częstotliwość oscylatora na interfejsie szeregowym USB (jeśli taki posiada)?
  • Jak tolerowany jest szeregowy interfejs USB niezgodności szybkości transmisji?

Wszystkie te czynniki są istotne dla określenia maksymalnej możliwej do osiągnięcia prędkości transmisji. ATmega328P wykorzystuje dzielnik sprzętowy na podstawie częstotliwości taktowania do generowania zegara bazowego dla interfejsu szeregowego. Jeśli nie ma stosunku liczb całkowitych z głównego zegara do czasu bitów żądanej prędkości transmisji, MCU nie będzie w stanie dokładnie wytworzyć żądanej prędkości. Może to prowadzić do potencjalnych problemów, ponieważ niektóre urządzenia są znacznie bardziej wrażliwe na niedopasowanie prędkości transmisji niż inne.

Interfejsy oparte na FTDI są dość tolerancyjne dla niedopasowania szybkości transmisji, nawet do kilku procent błędu. Jednak współpracowałem ze specjalistycznymi wbudowanymi modułami GPS, które nie były w stanie obsłużyć nawet 0,5% błędu prędkości transmisji.

Ogólne interfejsy szeregowe tolerują błąd ~ 5% prędkości transmisji. Ponieważ jednak każdy koniec może być wyłączony, bardziej powszechną specyfikacją jest +2,5%. W ten sposób, jeśli jeden koniec jest szybki o 2,5%, a drugi jest wolny o 2,5%, całkowity błąd nadal wynosi tylko 5%.


Tak czy inaczej. Uno używa ATmega328P jako podstawowego MCU, a ATmega16U2 jako interfejsu szeregowego USB. Mamy również szczęście, że oba te MCU używają podobnego USART Harware, a także zegarów 16 MHz.

Ponieważ oba MCU mają to samo oprogramowanie sprzętowe i częstotliwość taktowania, oba będą miały ten sam błąd szybkości transmisji w tym samym kierunku, więc możemy funkcjonalnie zignorować problem błędu transmisji.

W każdym razie „właściwa” odpowiedź na to pytanie wymagałaby wykopania źródła ATmega16U2 i opracowania stamtąd możliwych szybkości transmisji, ale ponieważ jestem leniwy, wydaje mi się, że proste, testy empiryczne będą działać.

Rzut oka na arkusz danych ATmega328P daje następującą tabelę:
wprowadź opis zdjęcia tutaj

Biorąc pod uwagę maksymalną podaną prędkość transmisji 2 Mb / s, napisałem szybki program testowy:

void setup(){};

void loop()
{

  delay(1000);
  Serial.begin(57600);
  Serial.println("\r\rBaud-rate = 57600");
  delay(1000);
  Serial.begin(76800);
  Serial.println("\r\rBaud-rate = 76800");
  delay(1000);
  Serial.begin(115200);
  Serial.println("\r\rBaud-rate = 115200");
  delay(1000);
  Serial.begin(230400);
  Serial.println("\r\rBaud-rate = 230400");
  delay(1000);
  Serial.begin(250000);
  Serial.println("\r\rBaud-rate = 250000");
  delay(1000);
  Serial.begin(500000);
  Serial.println("\r\rBaud-rate = 500000");
  delay(1000);
  Serial.begin(1000000);
  Serial.println("\r\rBaud-rate = 1000000");
  delay(1000);
  Serial.begin(2000000);
  Serial.println("\r\rBaud-rate = 2000000");
};

A następnie patrząc na odpowiedni port szeregowy z terminalem szeregowym:

wprowadź opis zdjęcia tutaj

Wygląda więc na to, że sprzęt może działać bezproblemowo z prędkością 2 000 000 bodów.

Zauważ, że ta prędkość transmisji zapewnia MCU 64 80 cykli zegara na bajt, więc utrzymanie interfejsu szeregowego byłoby bardzo trudne. Podczas gdy poszczególne bajty mogą być przesyłane bardzo szybko, prawdopodobnie będzie dużo czasu, gdy interfejs będzie po prostu bezczynny.


Edycja: rzeczywiste testowanie!

2 Mb / s jest prawdziwe:
wprowadź opis zdjęcia tutaj
każdy czas bitów wynosi 500 ns, co odpowiada dokładnie oczekiwanemu.

Problemy z wydajnością! Całkowita długość pakietu:
500 Kbaud: wprowadź opis zdjęcia tutaj

1 Mbaud: wprowadź opis zdjęcia tutaj

2 Mbaud: wprowadź opis zdjęcia tutaj
Uwaga: Zauważalne przekroczenie wynika z niewłaściwych praktyk uziemienia sondy pomiarowej i prawdopodobnie nie jest rzeczywiste. Używam ołowianego zacisku, który jest częścią mojej sondy lunety, a indukcyjność ołowiu jest prawdopodobnie przyczyną większości przeregulowania.

Jak widać, całkowita długość transmisji jest taka sama dla 0,5, 1 i 2 Mbodów. Wynika to z tego, że kod umieszczający bajty w buforze szeregowym jest słabo zoptymalizowany. Jako takie, nigdy nie osiągniesz niczego lepszego niż efektywne 500 Kbaud, chyba że napiszesz własne biblioteki szeregowe. Biblioteki Arduino są bardzo słabo zoptymalizowane, więc prawdopodobnie nie byłoby zbyt trudno zdobyć odpowiednie 2 Mbaud, przynajmniej dla transmisji seryjnych, jeśli spędziłeś na tym trochę czasu.

Connor Wolf
źródło
4
Ładna ilustracja ograniczenia przepustowości!
jippie
1
@AnnonomusPerson - Jeśli przełączysz się na zegar 20 MHz, możesz osiągnąć 2,5 Mb / s.
Connor Wolf,
1
@AnnonomusPerson - Musisz zamienić oba elementy lub użyć interfejsu szeregowego USB FTDI z oscylatorem ATmega328P 20 MHz. ATmega328P nie może osiągać prędkości 2,5 Mbps bez kryształu / rezonatora 20 MHz. To samo dotyczy wszystkich interfejsów ATmega16U2.
Connor Wolf,
1
Świetna odpowiedź! Tylko jedna mała korekta: przy 2 Mb / s każda transmisja bajtów zajmuje 80 cykli procesora, a nie 64. Jest tak, ponieważ pod względem czasu każdy bajt jest wart 10 bitów (1 start, 8 danych, 1 stop).
Edgar Bonet
1
@ linhartr22 - Przewody naprawdę wchodzą w grę tylko wtedy, gdy są długie , jak w 12 "+. Myślę, że prawdopodobnie mało prawdopodobne jest, aby zbyt wiele osób używało zbyt długich kabli o długości 100 stóp. Poza tym pytanie brzmiało, jak wysoko arduino / ATmega prędkość transmisji może wzrosnąć, a nie jak wysoka może być dowolna grupa kabli
Connor Wolf,
7

Okno Arduino Serial Monitor ogranicza Cię do 115200, ale nie jest to najwyższa możliwa prędkość transmisji. Możesz odczytać arkusze danych Atmel i FT232 (lub cokolwiek, którego używasz), aby znaleźć maksimum, ale jestem w stanie z powodzeniem korzystać z 230400 (dwa razy szybciej niż największy monitor Arduino Serial Monitor) bez problemów.

Jeśli chcesz zobaczyć wyniki na swoim komputerze, potrzebujesz innego monitora szeregowego, który obsługuje inne opcje prędkości transmisji. Lubię CoolTerm i Termite .

Pamiętaj, że zależy to również od szybkości zegara.

Oto kalkulator, który pomoże ci obliczyć, co jest możliwe.

sachleen
źródło
Gdy zaczniesz jeździć coraz szybciej, ograniczeniem staje się biblioteka Serial - jej implementacja nie jest zbyt wydajna.
Cybergibbons,
strona z linkiem nie działa
Codebeat
3

Jest to prawdopodobnie jeden z niewielu aspektów, w których tablice el-Cheapo różnią się od oryginalnych. Maksymalna szybkość transmisji szeregowej jest właściwie ograniczona tylko jakością płyty i jej układem. Gdy dane szeregowe wejdą do układu interfejsu AVR lub USB, dane będą przetwarzane inaczej niż protokół szeregowy UART.

Należy jednak pamiętać, że mikrokontroler ma pewien podstawowy sprzęt do przenoszenia / wyprowadzania danych szeregowych do / z pinów IO, ale absolutna maksymalna szybkość jest ograniczona do zegara 16 MHz (dla AVR). Gdy bajt zostanie przeniesiony do bufora szeregowego, sprzęt UART przejmie kontrolę i sam wypchnie / wciągnie bity. AVR co najwyżej osiąga 16 mln instrukcji na sekundę, a przerwania użyte do zapełnienia bufora szeregowego mają pewne obciążenie (co najmniej 8 tyknięć zegara dla obsługi przerwań + instrukcje, aby zapisać aktualny stan + kilka instrukcji dotyczących faktycznego wypełnienia bufora). Przy danej szybkości transmisji protokół będzie działał z ogromną liczbą bitów na sekundę, ale kontroler potrzebuje więcej czasu na wypełnienie bufora szeregowego, niż musi faktycznie wyprowadzić dane, co skutkuje niższą średnią przepustowością niż się spodziewasz i UART pracuje na biegu jałowym przez stosunkowo długi czas.

Innym efektem, o którym należy pamiętać, jest to, że cały narzut wymagany do wypchnięcia danych do UART (lub wciągnięcia go) nie może zostać wydany na rzeczywisty program, co ponownie wpływa na średnią praktyczną wydajność. Każdego cyklu instrukcji można użyć tylko raz, albo do wypełnienia bufora, albo do obliczenia głównej pętli.

Maksymalna przepustowość zależy zatem od używanej aplikacji (jak szybko dane są generowane / obliczane / gotowe do przejścia do / z bufora szeregowego), a rzeczywista „fizyczna” przepływność to tylko niewielka część decyzji projektowej.

jippie
źródło
1
Naprawdę, NAPRAWDĘ wątpię, aby którakolwiek z płyt miała problemy z układem na tyle poważne, aby uniemożliwić poprawne działanie sygnału 2 MHz. 2 MHz nie jest dokładnie wysoką częstotliwością.
Connor Wolf,
@FakeName Przynajmniej jedna płyta na moim biurku zwiększyła BER, kiedy zwiększam prędkość szeregową. Zwykle używam 9600, to więcej niż wystarcza do większości aplikacji i jest solidny.
jippie
Bez żartów! Huh Zastanawiam się, jak zły musi być układ, aby tak się stało? Podejrzewam jednak, że nie jest to układ tak bardzo jak rezonatory / kryształy o niskiej tolerancji.
Connor Wolf,
1
Wysokie prędkości transmisji, szczególnie U2Xn = 1w USART, są dość zepsute w związku z niedopasowaniem.
Connor Wolf,
@FakeName Jestem dinozaurem, lubię "9600 8N1" ze wszystkich złych powodów, o których możesz myśleć; o)
jippie
2

Sprawdzanie błędów jest w rzeczywistości bardzo łatwe i istnieje biblioteka AVR, która robi to w jednym wierszu.

Czytaj dalej, util/crc16.ha dołączone przykłady powinny być szybkie.

CRC jest dość solidny i szybki do prostych aplikacji.

80HD
źródło