Como o Arduino lida com o estouro de buffer serial?

27

Como o Arduino lida com o estouro de buffer serial? Joga fora os dados mais recentes ou os mais antigos? Quantos bytes o buffer pode conter?


fonte

Respostas:

13

Para portas seriais de hardware, você pode ver no HardwareSerial.cpp que o tamanho do buffer varia dependendo da quantidade de RAM disponível no AVR específico:

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

Para uma porta serial de software no SoftwareSerial.h, o tamanho do buffer do receptor _SS_MAX_RX_BUFFé definido como 64 bytes. Nos dois casos, ele pára de tentar inserir os dados recebidos na fila quando está cheio, para que você possa misturar os dados antigos e os novos, dependendo de como está recuperando dados da fila.

Idealmente, seria melhor garantir que o buffer sempre seja esvaziado rapidamente, para evitar o preenchimento do buffer. Talvez dê uma olhada nos temporizadores e na implementação de uma máquina de estado simples se o seu problema estiver relacionado a outro código que bloqueia o loop principal.

PeterJ
fonte
Tenho a impressão de que se eu transmitir dados para o Arduino e não tiver um "extrator" ativo de dados no lado do Arduino, se houver mais dados que possam caber no buffer, eles serão descartados. Você pode confirmar isso? Ingenuamente, presumi que o transmissor bloqueasse até que o espaço disponível para armazenar os dados fosse disponibilizado.
Kolban
Acabei de examinar todo esse código (em / usr / share / arduino / hardware / arduino / core / arduino / HardwareSerial.cpp) e posso confirmar o que você escreveu aqui. A única coisa que gostaria de acrescentar é que, como a SRAM é 2K (RAMEND> 1000), a instrução if sempre usará 64 em vez de 16 em um Nano ou um Uno. Então, se alguém iria querer expandir o tamanho do anel de buffer que seria o lugar para mudá-lo
SDsolar
5

Recebendo

Você pode ver na fonte do HardwareSerial que, se um byte recebido encontrar o buffer de anel cheio, ele será descartado:

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

Tenho a impressão de que se eu transmitir dados para o Arduino e não tiver um "extrator" ativo de dados no lado do Arduino, se houver mais dados que possam caber no buffer, eles serão descartados. Você pode confirmar isso?

Sim, será descartado. Não há controle de fluxo de software ou hardware, a menos que você implemente o seu.

No entanto, com um buffer de 64 bytes e recebendo dados em (digamos) 9600 baud, você recebe um byte a cada 1,04 ms e, portanto, leva 66,6 ms para preencher o buffer. Em um processador de 16 MHz, você deve poder verificar o buffer com freqüência suficiente para que ele não encha. Tudo o que você realmente precisa fazer é mover os dados do buffer HardwareSerial para o seu, se você não quiser processá-los agora.

Você pode ver pela #if (RAMEND < 1000)verificação de que os processadores com mais de 1000 bytes de RAM obtêm o buffer de 64 bytes, e aqueles com menos RAM obtêm o buffer de 16 bytes.


Enviando

Os dados que você escreve são colocados em um buffer do mesmo tamanho (16 ou 64 bytes). No caso de envio, se o buffer preencher os "blocos" de código, aguarde uma interrupção para enviar o próximo byte pela porta serial.

Se as interrupções forem desativadas, isso nunca acontecerá, portanto, você não fará impressões seriais dentro de uma rotina de serviço de interrupção.

Nick Gammon
fonte
Acredito que você esteja em uma ordem de magnitude: em 9600 baud, você recebe um byte a cada ~ 0,1 ms, portanto, são necessários apenas 6,6 ms para preencher o buffer.
Eric Dand
11
Em 9600 bauds, você recebe 9600 bits por segundo. Como cada byte tem 10 bits (8 dados + 1 bit de início + 1 bit de parada), você obtém 960 bytes por segundo. 1/960 = 0.001042 s- esse é um byte a cada 1,04 ms.
Nick Gammon
Ah, claro, bits, não bytes! Obrigado pela correção.
Eric Dand
Então, Nick, responda-me: Se eu tiver um Pi executando o Python sentado em um ser.readline () aguardando entrada como um data logger, e ele for alimentado via serial pelo Arduino, fazendo leituras e enviando-as como um lote com guia delimitadores e, em seguida, usando delay (120000) para que os lotes cheguem a cada dois minutos, as entranhas do Python provavelmente leem imediatamente em cada caractere até encontrar uma nova linha; nesse ponto, libera toda a linha como um valor de retorno. Portanto, não preciso me preocupar com o tamanho do buffer do Arduino, mesmo que eu esteja enviando 80 caracteres no total, não é? Isso seria uma boa suposição?
precisa saber é o seguinte
Sim, o tamanho do buffer de envio não importa neste cenário. Um pequeno buffer atrasaria o envio (levemente), mas se você estiver atrasando bastante, não se importará.
Nick Gammon