¿Qué velocidad de transmisión puedo alcanzar (sin errores)?

40

El estándar es 9600 baudios. Eso es solo el estándar . Usando un Arduino Uno SMD R2, ¿cuál es la velocidad de transmisión práctica más alta que puedo lograr?

Puntos de bonificación para los audaces: ¿cómo harías para crear un mecanismo de verificación de errores y luego aumentar la velocidad en baudios ridículamente alta para obtener altas tasas de transferencia?

Pingüino anónimo
fuente
2
Vale la pena señalar que las placas Arduino que usan circuitos integrados USB serie FTDI pueden ir REALMENTE rápido. El FT232 común puede ir a 3 Megabaudios (eso es 3,000,000 baudios) sin problemas. El uso de un ATmega16U2 es el factor limitante.
Connor Wolf
1
Mi clon Arduino Nano que obtuve de eBay alcanzó un máximo de 1,099,999. Seriamente. Lo hizo. Una vez que llegó a 1,100,000, la producción fue confusa. laqq`na`fca`fga`fga`bcngaah````iin`ha`a`a`bga`fga`bcqpahhqfq```fh`oopa`bca`fca. Utiliza un chip CH340 para comunicaciones USB.
PNDA

Respuestas:

59

Hay varios factores aquí:

  • ¿Qué velocidad de transmisión puede alcanzar la MCU ATmega328P?
  • ¿Qué velocidad de transmisión de baudios puede alcanzar la interfaz serial USB?
  • ¿Cuál es la frecuencia del oscilador en el ATmega328P?
  • ¿Cuál es la frecuencia del oscilador en la interfaz serial USB (si tiene una)?
  • ¿Qué tan tolerante es la interfaz serial USB de la falta de coincidencia de velocidad de transmisión?

Todos estos factores son relevantes para determinar la velocidad de transmisión máxima alcanzable. El ATmega328P utiliza un divisor de hardware de su velocidad de reloj para generar el reloj base para la interfaz en serie. Si no hay una relación de enteros desde el reloj principal hasta el tiempo de bits de la velocidad de transmisión deseada, la MCU no podrá producir exactamente la velocidad deseada. Esto puede generar problemas potenciales, ya que algunos dispositivos son mucho más sensibles a la falta de coincidencia de velocidad de transmisión que otros.

Las interfaces basadas en FTDI son bastante tolerantes a la falta de coincidencia de la velocidad de transmisión, hasta varios errores porcentuales. Sin embargo, he trabajado con módulos GPS integrados especializados que no pudieron manejar ni siquiera un error de velocidad de transmisión del 0.5%.

Las interfaces seriales generales toleran ~ 5% de error de velocidad de transmisión. Sin embargo, dado que cada extremo puede estar desactivado, una especificación más común es + -2.5%. De esta manera, si un extremo es 2.5% rápido y el otro es 2.5% lento, su error general sigue siendo solo 5%.


De todos modos El Uno utiliza un ATmega328P como MCU principal y un ATmega16U2 como interfaz serial USB. También somos afortunados aquí porque ambas MCU usan hardware similar USART, así como relojes de 16 Mhz.

Dado que ambas MCU tienen el mismo hardware y velocidad de reloj, ambas tendrán el mismo error de velocidad en baudios en la misma dirección, por lo que podemos ignorar funcionalmente el problema del error en baudios.

De todos modos, la respuesta "adecuada" a esta pregunta implicaría desenterrar la fuente del ATmega16U2 y calcular las posibles velocidades de transmisión a partir de ahí, pero como soy flojo, creo que las pruebas empíricas simples funcionarán.

Un vistazo rápido a la hoja de datos ATmega328P produce la siguiente tabla:
ingrese la descripción de la imagen aquí

Entonces, dada la velocidad de transmisión máxima indicada de 2 Mbps, escribí un programa de prueba rápida:

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

Y luego mirando el puerto serial relevante con un terminal serial:

ingrese la descripción de la imagen aquí

Entonces parece que el hardware puede funcionar a 2,000,000 baudios sin problemas.

Tenga en cuenta que esta velocidad en baudios solo le da al MCU 64 80 ciclos de reloj por byte, por lo que sería muy difícil mantener ocupada la interfaz en serie. Si bien los bytes individuales pueden transferirse muy rápidamente, es probable que haya mucho tiempo cuando la interfaz está simplemente inactiva.


Editar: ¡Pruebas reales!

Los 2 Mbps son reales:
ingrese la descripción de la imagen aquí
cada bit-time es de 500 ns, que coincide exactamente con lo que se espera.

¡Problemas de desempeño! Longitud total del paquete:
500 Kbaudios: ingrese la descripción de la imagen aquí

1 Mbaudio: ingrese la descripción de la imagen aquí

2 Mbaudios: ingrese la descripción de la imagen aquí
Nota: el sobreimpulso notable se debe a las prácticas de puesta a tierra de la sonda de alcance deficiente y probablemente no sea real. Estoy usando el cable de conexión a tierra que forma parte de mi sonda de alcance, y la inductancia del cable es probablemente la causa de la mayoría del sobreimpulso.

Como puede ver, la longitud total de transmisión es la misma para 0.5, 1 y 2 Mbaud. Esto se debe a que el código que coloca los bytes en el búfer en serie está mal optimizado. Como tal, nunca logrará nada mejor que un efectivo de 500 Kbaud, a menos que escriba sus propias bibliotecas en serie. Las bibliotecas Arduino están muy mal optimizadas, por lo que probablemente no sería demasiado difícil obtener 2 Mbaud adecuados, al menos para transmisiones en ráfaga, si dedicas un poco de tiempo a ello.

Connor Wolf
fuente
44
Bonita ilustración de la limitación de rendimiento!
jippie
1
@AnnonomusPerson: si cambia a un reloj de 20 Mhz, puede hacer 2.5 Mbps.
Connor Wolf
1
@AnnonomusPerson: necesitaría intercambiar ambos, o utilizar una interfaz serial USB FTDI con un oscilador ATmega328P de 20 Mhz. El ATmega328P no puede hacer 2.5 Mbps sin un cristal / resonador de 20 Mhz. Lo mismo es cierto para cualquier interfaz ATmega16U2.
Connor Wolf
1
¡Gran respuesta! Solo una pequeña corrección: a 2 Mb / s, cada transmisión de bytes toma 80 ciclos de CPU, no 64. Esto se debe a que, en cuanto al tiempo, cada byte vale 10 bits (1 inicio, 8 datos, 1 parada).
Edgar Bonet
1
@ linhartr22 - Los cables solo entran en juego si son largos , como en 12 "+. Creo que es poco probable que muchas personas estén usando cables de 100 pies de largo. Además, la pregunta era qué tan alto era el arduino / ATmega puede aumentar la velocidad de transmisión, no lo alto que puede llegar un conjunto de cable arbitrario.
Connor Wolf
7

La ventana Arduino Serial Monitor lo limita a 115200, pero esa no es la velocidad de transmisión más alta capaz. Puede leer las hojas de datos de Atmel y FT232 (o lo que sea que esté usando) para averiguar el máximo, pero puedo usar 230400 (el doble de rápido que el monitor serie Arduino) sin problemas.

Si desea ver los resultados en su computadora, necesitará otro monitor en serie que admita otras opciones de velocidad de transmisión. Me gustan CoolTerm y Termite .

Tenga en cuenta que esto también depende en gran medida de la velocidad de su reloj.

Aquí hay una calculadora para ayudarlo a calcular lo que es posible.

Sachleen
fuente
A medida que comienza a ir más y más rápido, la limitación se convierte en la biblioteca de serie: su implementación no es muy eficiente.
Cybergibbons
sitio web del enlace está muerto
Codebeat
3

Este es probablemente uno de los pocos aspectos en los que las placas el-Cheapo difieren de las placas originales. La velocidad máxima de transferencia en serie está limitada solo por la calidad de la placa y su diseño. Una vez que los datos en serie ingresan al chip de interfaz AVR o USB, los datos se procesarán de manera diferente al protocolo UART en serie.

Sin embargo, tenga en cuenta que el microcontrolador tiene un hardware básico para cambiar datos de entrada / salida en serie a / desde los pines IO, pero la velocidad máxima absoluta se limita al reloj de 16MHz (para AVR). Una vez que un byte se mueve al búfer en serie, el hardware UART se hará cargo y empujará / extraerá los bits por sí mismo. Un AVR, en el mejor de los casos, alcanza 16M de instrucciones por segundo y las interrupciones utilizadas para llenar el búfer en serie tienen algo de sobrecarga (al menos 8 tics de reloj para el manejo de interrupciones + instrucciones para guardar el estado actual + varias instrucciones para llenar realmente el búfer). A una tasa de bits dada, el protocolo se ejecutará a una velocidad de n bits por segundo, pero su controlador necesita más tiempo para llenar el búfer en serie de lo que realmente necesita para generar los datos, lo que resulta en un rendimiento promedio más bajo de lo que espera y el ralentí UART por un tiempo relativamente largo.

Otro efecto a recordar es que todos los gastos generales necesarios para enviar datos a UART (o extraerlos) no se pueden gastar en su programa real, lo que nuevamente afecta el rendimiento práctico promedio. Solo puede usar cada ciclo de instrucción una vez, ya sea para llenar el búfer o para calcular el bucle principal.

Por lo tanto, el rendimiento máximo depende de la aplicación que utilice (la rapidez con la que se generan / calculan / preparan los datos para moverse hacia / desde el búfer en serie) y la tasa de bits 'física' real es solo una pequeña parte de la decisión de diseño.

jippie
fuente
1
Realmente, REALMENTE dudo que alguna de las placas tenga problemas de diseño lo suficientemente graves como para evitar que una señal de 2 Mhz funcione bien. 2 Mhz no es exactamente alta frecuencia.
Connor Wolf
@FakeName Al menos una placa en mi escritorio aquí ha aumentado la BER cuando presiono la velocidad en serie. Usualmente uso 9600, que es más que suficiente para la mayoría de las aplicaciones y es robusto.
jippie
¡En serio! Huh Me pregunto qué tan malo debe ser el diseño para que eso suceda. Sin embargo, sospecho que no es tanto el diseño como los resonadores / cristales de baja tolerancia.
Connor Wolf
1
Las altas tasas de baudios, particularmente si están U2Xn = 1en el USART, tienden a ponerse bastante irritables por la falta de coincidencia.
Connor Wolf
@FakeName Soy un dinosaurio, me gusta "9600 8N1" por todos los motivos heredados incorrectos que se te
ocurran
2

La comprobación de errores es realmente muy fácil y hay una biblioteca AVR que hace esto de una sola vez.

Siga leyendo util/crc16.hy debería estar listo para comenzar en poco tiempo con los ejemplos incluidos.

CRC es bastante robusto y rápido para aplicaciones simples.

80HD
fuente