How does the Arduino handle serial buffer overflow? Does it throw away the newest incoming data or the oldest? How many bytes can the buffer hold?
2 Answers
For hardware serial ports you can see in HardwareSerial.cpp that the buffer size varies depending on the amount of RAM available on the particular AVR:
#if (RAMEND < 1000)
#define SERIAL_BUFFER_SIZE 16
#else
#define SERIAL_BUFFER_SIZE 64
#endif
For a software serial port in SoftwareSerial.h the receiver buffer size _SS_MAX_RX_BUFF
is defined as 64 bytes. In both cases it stops attempting to insert received data into the queue when it is full, so you could get a mix to old and new data depending on how you're retrieving data from the queue.
Ideally it would be best to ensure the buffer always gets emptied in a prompt manner to avoid the buffer filling. Maybe take a look at timers and implementing a simple state machine if your problem is related to other code blocking the main loop.
-
1I get the impression that if I transmit data to the Arduino and don't have an active "puller" of data on the Arduino side then if more data arrives than can fit in the buffer, it will be discarded. Can you confirm that? I had naively assumed that the transmitter would block until space available to hold the data became available.– KolbanJun 19, 2015 at 18:54
-
1I just looked through all that code (under /usr/share/arduino/hardware/arduino/core/arduino/HardwareSerial.cpp) and can confirm what you wrote here. The only thing I would add is that since the SRAM is 2K (RAMEND>1000) then that if statement will always use 64 rather than 16 on a Nano or an Uno. So if one would want to expand the size of the ring buffer that would be the place to change it– SDsolarAug 19, 2017 at 6:10
Receiving
You can see from the source of HardwareSerial that if an incoming byte finds the ring buffer full it is discarded:
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;
}
}
I get the impression that if I transmit data to the Arduino and don't have an active "puller" of data on the Arduino side then if more data arrives than can fit in the buffer, it will be discarded. Can you confirm that?
Yes it will be discarded. There is no software or hardware flow control, unless you implement your own.
However with a 64-byte buffer, and receiving data at (say) 9600 baud, you get one byte every 1.04 ms, and thus it takes 66.6 ms to fill up the buffer. On a 16 MHz processor you should be able to check the buffer often enough that it doesn't fill up. All you really have to do is move the data from the HardwareSerial buffer to your own, if you don't want to process it right now.
You can see from the #if (RAMEND < 1000)
check that the processors with 1000+ bytes of RAM get the 64-byte buffer, the ones will less RAM get the 16-byte buffer.
Sending
Data that you write is placed in a same-sized buffer (16 or 64 bytes). In the case of sending if the buffer fills up the code "blocks" waiting for an interrupt to send the next byte out the serial port.
If interrupts are turned off this will never happen, thus you do not do Serial prints inside an Interrupt Service Routine.
-
I believe you're off by an order of magnitude: at 9600 baud, you get a byte every ~0.1 ms, so it only takes 6.6 ms to fill up the buffer. Feb 7, 2017 at 3:29
-
2At 9600 baud you get 9600 bits per second. Since each byte is 10 bits (8 data + 1 start bit + 1 stop bit) then you get 960 bytes per second.
1/960 = 0.001042 s
- that is one byte every 1.04 ms.– Nick Gammon ♦Feb 7, 2017 at 4:11 -
-
So Nick, please answer this for me: If I have a Pi running Python sitting at a ser.readline() waiting for input as a data logger, and it is fed via serial by Arduino taking readings then sending them as a batch with tab delimeters, then using delay(120000) so the batches come in every two minutes, the Python innards probably immediately read in each character until it encounter a newline, at which point it releases the whole line as a return value. So I don't have to worry about the Arduino buffer size even if I am sending 80 characters total, eh? Would that be a good assumption?– SDsolarAug 19, 2017 at 7:13
-
Yes, the sending buffer size won't matter in this scenario. A small buffer would slow down the sending (slightly) but if you are doing a lengthy delay anyway you won't care.– Nick Gammon ♦Aug 19, 2017 at 7:21