Qual é a taxa de transmissão alta (sem erros)?


40

O padrão é 9600 baud. Esse é apenas o padrão . Usando um SMD R2 do Arduino Uno, qual é a maior taxa de transmissão prática possível?

Pontos de bônus para os audaciosos: como você criaria um mecanismo de verificação de erros e aumentaria a taxa de transmissão ridiculamente alta para obter altas taxas de transferência?


2
Vale a pena notar que as placas Arduino que usam ICs seriais USB FTDI podem ir MUITO rápido. O FT232 comum pode ter 3 Megabaud (ou seja, 3.000.000 de baud) sem problemas. O uso de um ATmega16U2 é o fator limitante.
Connor Wolf

11
Meu clone Arduino Nano que recebi do eBay atingiu o máximo de 1.099.999. A sério. Sim. Quando chegou a 1.100.000, a produção foi distorcida. laqq`na`fca`fga`fga`bcngaah````iin`ha`a`a`bga`fga`bcqpahhqfq```fh`oopa`bca`fca. Ele usa um chip CH340 para comunicações USB.
PNDA 27/09/15

Respostas:


59

Existem vários fatores aqui:

  • Qual a taxa de transmissão que o ATmega328P MCU pode atingir?
  • Qual o nível de taxa de transmissão que a interface USB-Serial pode atingir?
  • Qual é a frequência do oscilador no ATmega328P?
  • Qual é a frequência do oscilador na interface serial USB (se houver uma)?
  • Quão tolerante é a interface serial USB da incompatibilidade da taxa de transmissão?

Todos esses fatores são relevantes para determinar a taxa de transmissão máxima alcançável. O ATmega328P usa um divisor de hardware de sua taxa de clock para gerar o clock base para a interface serial. Se não houver uma taxa inteira entre o relógio principal e o tempo de bit da taxa de transmissão desejada, o MCU não poderá produzir exatamente a taxa desejada. Isso pode levar a possíveis problemas, pois alguns dispositivos são muito mais sensíveis à incompatibilidade da taxa de transmissão do que outros.

As interfaces baseadas em FTDI são bastante tolerantes à incompatibilidade da taxa de transmissão, até vários por cento de erro. No entanto, trabalhei com módulos GPS incorporados especializados que não conseguiam lidar nem com um erro de taxa de transmissão de 0,5%.

Interfaces seriais gerais são tolerantes a ~ 5% de erro na taxa de transmissão. No entanto, como cada extremidade pode ser desativada, uma especificação mais comum é + -2,5%. Dessa forma, se uma extremidade for 2,5% rápida e a outra 2,5% lenta, seu erro geral ainda será de apenas 5%.


Em todo o caso. O Uno usa um ATmega328P como o MCU principal e um ATmega16U2 como a interface serial USB. Também temos a sorte de que esses dois MCUs usem USARTs de harware semelhantes e relógios de 16 Mhz.

Como os dois MCUs têm o mesmo harware e taxa de clock, ambos terão o mesmo erro de taxa de transmissão na mesma direção, para que possamos ignorar funcionalmente o problema do erro de transmissão.

De qualquer forma, a resposta "adequada" a essa pergunta envolveria desenterrar a fonte do ATmega16U2 e elaborar as possíveis taxas de transmissão a partir daí, mas, como sou preguiçoso, acho que testes simples e empíricos funcionarão.

Uma rápida olhada na folha de dados do ATmega328P produz a seguinte tabela:
insira a descrição da imagem aqui

Portanto, considerando a taxa de transmissão máxima declarada de 2 Mbps, escrevi um programa de teste rápido:

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");
};

E então olhando para a porta serial relevante com um terminal serial:

insira a descrição da imagem aqui

Parece que o hardware pode rodar a 2.000.000 de bauds sem problemas.

Observe que essa taxa de transmissão fornece apenas ciclos de clock do MCU 64 80 por byte; portanto, seria muito desafiador manter a interface serial ocupada. Embora os bytes individuais possam ser transferidos muito rapidamente, é provável que haja muito tempo quando a interface estiver simplesmente ociosa.


Edit: Teste Real!

Os 2 Mbps são reais:
insira a descrição da imagem aqui
cada bit-time é de 500 ns, o que corresponde exatamente ao esperado.

Problemas de desempenho! Comprimento total do pacote:
500 Kbaud: insira a descrição da imagem aqui

1 Mbaud: insira a descrição da imagem aqui

2 Mbaud: insira a descrição da imagem aqui
Nota: O overshoot perceptível se deve a práticas inadequadas de aterramento da sonda e provavelmente não é real. Estou usando o chumbo de clipe de terra que faz parte da minha sonda de escopo, e a indutância de chumbo provavelmente é a causa da maioria dos excedentes.

Como você pode ver, o comprimento total da transmissão é o mesmo para 0,5, 1 e 2 Mbaud. Isso ocorre porque o código que está colocando os bytes no buffer serial é pouco otimizado. Como tal, você nunca alcançará nada melhor do que um eficaz 500 Kbaud, a menos que escreva suas próprias bibliotecas seriais. As bibliotecas do Arduino são muito otimizadas, portanto, provavelmente não seria muito difícil obter um 2 Mbaud adequado, pelo menos para transmissões intermitentes, se você gastasse um pouco de tempo com isso.


4
Bela ilustração da limitação da taxa de transferência!
jippie

11
@AnnonomusPerson - Se você alternar para um relógio de 20 Mhz, poderá fazer 2,5 Mbps.
Connor Lobo

11
@AnnonomusPerson - Você precisaria trocar os dois ou usar uma interface serial USB FTDI com um oscilador de 20 Mhz ATmega328P. O ATmega328P não pode fazer 2,5 Mbps sem um cristal / ressonador de 20 Mhz. O mesmo vale para qualquer interface ATmega16U2.
Connor Lobo

11
Ótima resposta! Apenas uma pequena correção: a 2 Mb / s, cada transmissão de byte leva 80 ciclos da CPU, e não 64. Isso ocorre porque, em termos de tempo, cada byte vale 10 bits (1 partida, 8 dados, 1 parada).
Edgar Bonet

11
@ linhartr22 - Os fios só entram em jogo se forem longos , como em 12 "+. Acho que é improvável que muitas pessoas usem cabos demais de 100 pés de comprimento. Além disso, a questão era a que altura o arduino / ATmega taxa de transmissão pode ir, não o quão alto um cabo arbitrária montagem pode ir.
Connor Lobo

7

A janela do Arduino Serial Monitor limita você a 115200, mas essa não é a taxa de transmissão mais alta possível. Você pode ler as folhas de dados do Atmel e do FT232 (ou o que você estiver usando) para descobrir o máximo, mas eu posso usar com êxito o 230400 (duas vezes mais rápido que o maior que o Arduino Serial Monitor suporta) sem problemas.

Se você quiser ver os resultados no seu computador, precisará de outro monitor serial que suporte outras opções de taxa de transmissão. Eu gosto de CoolTerm e Cupim .

Observe que isso depende muito da velocidade do relógio também.

Aqui está uma calculadora para ajudá-lo a calcular o que é possível.


À medida que você começa a ir cada vez mais rápido, a limitação se torna a biblioteca Serial - sua implementação não é muito eficiente.
Cybergibbons

site do link está morto
Codebeat 18/07/19

3

Esse é provavelmente um dos poucos aspectos em que as placas el-Cheapo diferem das placas originais. A taxa máxima de transferência serial é praticamente limitada apenas pela qualidade da placa e seu layout. Quando os dados seriais entrarem no chip da interface AVR ou USB, os dados serão processados ​​de maneira diferente do protocolo UART serial.

Lembre-se, porém, de que o microcontrolador possui algum hardware básico para transferir / inverter dados seriais de / para os pinos de E / S, mas a taxa máxima absoluta é limitada ao relógio de 16MHz (para AVRs). Depois que um byte é movido para o buffer serial, o hardware UART assume o controle e empurra / extrai os bits por conta própria. Um AVR, na melhor das hipóteses, atinge 16M de instruções por segundo e as interrupções usadas para preencher o buffer serial têm alguma sobrecarga (pelo menos oito marcações de relógio para o tratamento de interrupções + instruções para salvar o estado atual + várias instruções para realmente preencher o buffer). Em uma determinada taxa de bits, o protocolo será executado em n bits impressionantes por segundo, mas seu controlador precisa de mais tempo para preencher o buffer serial do que realmente precisa produzir os dados, resultando em uma taxa de transferência média mais baixa do que o esperado e no UART ocioso por um tempo relativamente longo.

Outro efeito a ser lembrado é que toda a sobrecarga necessária para enviar dados para o UART (ou extraí-los) não pode ser gasta no seu programa real, afetando novamente o rendimento prático médio. Você pode usar todos os ciclos de instruções apenas uma vez, para preencher o buffer ou para calcular o loop principal.

Portanto, a taxa de transferência máxima depende do aplicativo que você usa (a rapidez com que os dados são gerados / calculados / prontos para mover para / do buffer serial) e a taxa de bits 'física' real é apenas uma pequena parte da decisão do projeto.


11
Eu realmente duvido que alguma das placas tenha problemas de layout suficientemente severos para impedir que um sinal de 2 Mhz funcione bem. 2 Mhz não é exatamente alta frequência.
Connor Wolf

@FakeName Pelo menos uma placa na minha mesa aqui aumentou o BER quando pressiono a velocidade serial. Eu costumo usar 9600, que é mais que suficiente para a maioria dos aplicativos e é robusto.
jippie

Sem brincadeiras! Hã. Eu me pergunto o quão ruim o layout deve ser para que isso aconteça. Eu suspeitaria que não é o layout tanto quanto os ressonadores / cristais de baixa tolerância.
Connor Wolf

11
Altas taxas de transmissão, principalmente se estiverem U2Xn = 1no USART, tendem a ficar bastante irritadas quanto à incompatibilidade.
Connor Wolf

@FakeName eu sou um dinossauro, eu meio que gosto "9600 8N1" por todas as razões erradas legado que você pode pensar; o)
jippie

2

A verificação de erros é realmente muito fácil e existe uma biblioteca AVR que faz isso em um único liner.

Leia util/crc16.he você deve seguir rapidamente os exemplos incluídos.

O CRC é bastante robusto e rápido para aplicações simples.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.