¿Cómo maneja el Arduino el desbordamiento del búfer en serie?

27

¿Cómo maneja el Arduino el desbordamiento del búfer en serie? ¿Tira los datos entrantes más nuevos o los más antiguos? ¿Cuántos bytes puede contener el búfer?


fuente

Respuestas:

13

Para los puertos seriales de hardware, puede ver en HardwareSerial.cpp que el tamaño del búfer varía según la cantidad de RAM disponible en el AVR particular:

#if (RAMEND < 1000)
    #define SERIAL_BUFFER_SIZE 16
#else
    #define SERIAL_BUFFER_SIZE 64
#endif

Para un puerto serie de software en SoftwareSerial.h, el tamaño del búfer del receptor _SS_MAX_RX_BUFFse define como 64 bytes. En ambos casos, deja de intentar insertar los datos recibidos en la cola cuando está llena, por lo que puede obtener una combinación de datos antiguos y nuevos dependiendo de cómo esté recuperando los datos de la cola.

Idealmente, sería mejor asegurarse de que el búfer siempre se vacíe de manera rápida para evitar el llenado del búfer. Quizás eche un vistazo a los temporizadores e implemente una máquina de estado simple si su problema está relacionado con otro código que bloquea el bucle principal.

PeterJ
fuente
Tengo la impresión de que si transmito datos al Arduino y no tengo un "extractor" activo de datos en el lado de Arduino, si llegan más datos de los que pueden caber en el búfer, se descartarán. ¿Puedes confirmar eso? Asumí ingenuamente que el transmisor se bloquearía hasta que el espacio disponible para almacenar los datos estuviera disponible.
Kolban
Acabo de mirar todo ese código (bajo / usr / share / arduino / hardware / arduino / core / arduino / HardwareSer‌ ial.cpp) y puedo confirmar lo que escribió aquí. Lo único que agregaría es que, dado que la SRAM es 2K (RAMEND> 1000), esa instrucción if siempre usará 64 en lugar de 16 en un Nano o Uno. Entonces, si uno quisiera expandir el tamaño del buffer de anillo, ese sería el lugar para cambiarlo
SDsolar
5

Recepción

Puede ver desde la fuente de HardwareSerial que si un byte entrante encuentra que el búfer de anillo está lleno, se descarta:

inline void store_char(unsigned char c, ring_buffer *buffer)
{
  int i = (unsigned int)(buffer->head + 1) % SERIAL_BUFFER_SIZE;

  // if we should be storing the received character into the location
  // just before the tail (meaning that the head would advance to the
  // current location of the tail), we're about to overflow the buffer
  // and so we don't write the character or advance the head.
  if (i != buffer->tail) {
    buffer->buffer[buffer->head] = c;
    buffer->head = i;
  }
}

Tengo la impresión de que si transmito datos al Arduino y no tengo un "extractor" activo de datos en el lado de Arduino, si llegan más datos de los que pueden caber en el búfer, se descartarán. ¿Puedes confirmar eso?

Sí, será descartado. No hay control de flujo de software o hardware, a menos que implemente el suyo.

Sin embargo, con un búfer de 64 bytes y recibiendo datos a (digamos) 9600 baudios, obtienes un byte cada 1.04 ms y, por lo tanto, se necesitan 66.6 ms para llenar el búfer. En un procesador de 16 MHz, debería poder verificar el búfer con la frecuencia suficiente para que no se llene. Todo lo que realmente tiene que hacer es mover los datos del búfer de HardwareSerial a los suyos, si no desea procesarlos en este momento.

Puede ver en la #if (RAMEND < 1000)verificación que los procesadores con más de 1000 bytes de RAM obtienen el búfer de 64 bytes, los que menos RAM obtienen el búfer de 16 bytes.


Enviando

Los datos que escribe se colocan en un búfer del mismo tamaño (16 o 64 bytes). En el caso de enviar si el búfer llena el código "bloquea" esperando una interrupción para enviar el siguiente byte al puerto serie.

Si las interrupciones están desactivadas, esto nunca sucederá, por lo que no debe realizar impresiones en serie dentro de una rutina de servicio de interrupción.

Nick Gammon
fuente
Creo que está apagado en un orden de magnitud: a 9600 baudios, obtiene un byte cada ~ 0.1 ms, por lo que solo se necesitan 6.6 ms para llenar el búfer.
Eric Dand
1
A 9600 baudios obtienes 9600 bits por segundo. Como cada byte es de 10 bits (8 datos + 1 bit de inicio + 1 bit de parada), obtiene 960 bytes por segundo. 1/960 = 0.001042 s- eso es un byte cada 1.04 ms.
Nick Gammon
Ahh, por supuesto, ¡bits no bytes! Gracias por la corrección.
Eric Dand
Entonces, Nick, responde esto por mí: si tengo un Pi que ejecuta Python sentado en un ser.readline () esperando la entrada como un registrador de datos, y Arduino lo alimenta vía serial tomando lecturas y luego enviándolas como un lote con pestaña delimitadores, luego usando el retardo (120000) para que los lotes lleguen cada dos minutos, las entrañas de Python probablemente leen inmediatamente en cada personaje hasta que encuentre una nueva línea, momento en el cual libera toda la línea como valor de retorno. Así que no tengo que preocuparme por el tamaño del búfer Arduino, incluso si envío 80 caracteres en total, ¿eh? ¿Sería una buena suposición?
SDsolar
Sí, el tamaño del búfer de envío no importará en este escenario. Un pequeño búfer ralentizaría el envío (ligeramente), pero si está haciendo un retraso prolongado de todos modos, no le importará.
Nick Gammon