Does someone know if all the serial.println output goes to something like /dev/null, if the board is NOT connected to a console? I’ve got a lot of output messages that I was using to see what my little program was doing, and instead of commenting out all the messages – I was wondering if the board is going to buffer till death or just throw the messages away when not connected to a serial monitor. I’m using a little nano v3, but my question is broader than just for that one board. I’ve looked through the Arduino language docs, but didn’t see anything that addressed this particular serial.println behavior
As I understand things, the serial buffer is what is known as a circular buffer. When the buffer is full because nothing is written out, all subsequent wrights to the buffer are ignored. So, as you suggest, they are in effect thrown away, by there is no throwing, they are just ignored.
Your arduino Nano will continue to blast the bits on Tx and does not care if there is (or not) someone listening on the other side.
Said differently, your program keeps working exactly as when the serial monitor is open. If those print were slowing you down or using lots of memory, they will keep doing so.
I use these macros
#define DEBUG 1 // SET TO 0 OUT TO REMOVE TRACES
#if DEBUG
#define D_SerialBegin(...) Serial.begin(__VA_ARGS__);
#define D_print(...) Serial.print(__VA_ARGS__)
#define D_write(...) Serial.print(__VA_ARGS__)
#define D_println(...) Serial.println(__VA_ARGS__)
#else
#define D_SerialBegin(bauds)
#define D_print(...)
#define D_write(...)
#define D_println(...)
#endif
To easily remove all traces when I’m done debugging
The Serial device ignores the presence or absence of a receiving station. It simply outputs whatever it's given at the given baudrate.
If you want a response (ACK) from a receiver then you have to implement such a protocol on top of Serial. Or you use hardware handshake lines (RTS/CTS/DSR/DTR) between both stations. In either case both stations have to support the handshake protocol or it won't work.
No, the code blocks until the buffer has sufficient room to accept the new data so your code will slow down, even if nobody is listening.
No, I have several Arduino nano's that run 24/7 and have serial output and they are never blocked from continuing to run.
Why No? If the buffer is full then a program is blocked while the buffer is full. The block is removed once all output could be placed into the buffer.
Transmit continues until buffer is empty. No knowledge of connection outbound.
void HardwareSerial::_tx_udr_empty_irq(void)
{
// If interrupts are enabled, there must be more data in the output
// buffer. Send the next byte
unsigned char c = _tx_buffer[_tx_buffer_tail];
_tx_buffer_tail = (_tx_buffer_tail + 1) % SERIAL_TX_BUFFER_SIZE;
*_udr = c;
// clear the TXC bit -- "can be cleared by writing a one to its bit
// location". This makes sure flush() won't return until the bytes
// actually got written. Other r/w bits are preserved, and zeroes
// written to the rest.
#ifdef MPCM0
*_ucsra = ((*_ucsra) & ((1 << U2X0) | (1 << MPCM0))) | (1 << TXC0);
#else
*_ucsra = ((*_ucsra) & ((1 << U2X0) | (1 << TXC0)));
#endif
if (_tx_buffer_head == _tx_buffer_tail) {
// Buffer empty, so disable interrupts
cbi(*_ucsrb, UDRIE0);
}
}
Consider this program
void setup() {
Serial.begin(9600);
Serial.println("ready");
for(int i=0; i<32; ++i) {
Serial.println("0123456");
}
}
void loop() {
}
and the output
11:04:03.753 -> ready
11:04:03.753 -> 0123456
11:04:03.800 -> 0123456
11:04:03.800 -> 0123456
11:04:03.800 -> 0123456
11:04:03.800 -> 0123456
11:04:03.800 -> 0123456
11:04:03.848 -> 0123456
11:04:03.848 -> 0123456
11:04:03.848 -> 0123456
11:04:03.848 -> 0123456
11:04:03.848 -> 0123456
11:04:03.895 -> 0123456
11:04:03.895 -> 0123456
11:04:03.895 -> 0123456
11:04:03.895 -> 0123456
11:04:03.895 -> 0123456
11:04:03.942 -> 0123456
11:04:03.942 -> 0123456
11:04:03.942 -> 0123456
11:04:03.942 -> 0123456
11:04:03.942 -> 0123456
11:04:03.990 -> 0123456
11:04:03.990 -> 0123456
11:04:03.990 -> 0123456
11:04:03.990 -> 0123456
11:04:03.990 -> 0123456
11:04:04.036 -> 0123456
11:04:04.036 -> 0123456
11:04:04.036 -> 0123456
11:04:04.036 -> 0123456
11:04:04.036 -> 0123456
11:04:04.083 -> 0123456
You will notice that the 64 byte buffer fills up and then there is about a 48msec delay while it empties and then it repeats. At 115200, this delay is smaller, but still can happen. For a normal program, 115200 should be fast enough that you don't really see it. Yet another reason the default baud rate should be 115200 vs. all the 9600 stuff that is everywhere.
After reading through the responses, it kind of sounds as though there is an argument to be made on both sides of the question. A couple of the responses indicated that there is the potential to cause the program to hang or at least have significant performance impact. @DrDiettrich actually defined its function how I was hoping it works, and @Paul_KD7HB has given a real-world example of a ‘no impact scenario’ (I appreciated the R-L example) . @blh64‘ s description supported my belief of what may happen if I left it running for extended periods of time.
But @J-M-L gave a safety net solution that handles the issue even if it does impact an extended run scenario. I think I will implement that solution, it’s an effective way of toggling the debug messages.
I feel as though my question was resolved, but I’m leaving the topic open since there was some excellent dialog about the question and possibly someone logging in later in the day will have additional information. Thanks to everyone that responded.
The buffer In my response is in the USB processor on the nano, etc. Not the buffer in the Serial() code.
So it is unrelated to all Arduinos with a separate USB controller. The main controller doesn't care whether the USB controller actually sends what it receives on its Rx input.
Doesn't know and doesn't care. Totally asynchronous with no acknowledgement. More over, the baud rate only effects the time-out before a partially filled buffer is sent to the USB host. The faster the Baud rate, the more full the buffer is when it is sent to the host. Again, because of asynchronous communication, the bytes can be sent any time.
That happens anyway whether you marked it solved or not.
The serial buffer in an unconnected Arduino is like Oman, it spills its seed into the sand. At least on the ATmega processors. Note that you will not get the TX and RX LED lighting up if there is no USB plugged into the USB to serial chip.
The processors that emulate a virtual USB port like the Leonardo will jam up if you have a wait for serial loop in the code because the serial emulation will never complete. So you must remove that to run it without a USB connection.
Oman may be a sandy place, but it was Onan who was the seed spiller.
That has nothing to do with the fact that there is no one listening on the other end. This blocking happens regardless and is often a challenge especially at 9600 bauds : if you have Lots of debug traces then your debugging code can actually create timing challenges and introduce bugs that would not be there in the first place (if your code requires specific timing).
That was the point I was trying to make when I wrote
So it’s always good to keep debug traces short, use the F() macro to not overload the SRAM with the text, and get rid of those when they are not needed anymore - which is where using the macros I suggested can help do that easily.
Note that on boards with "Native USB" connections, like an Arduino Micro, or the "native USB port" on Due or Zero, an attempt to use "Serial" (which is actually the USB port) will probably fail in a number of interesting ways.
Oh, my! Lions, tigers, and bear arse.
Apart from the "while not serial loop" I mentioned earlier I have not found this to be the case. I think it is because the serial logic is not initialised.
@cattledog - Thanks for the correction, dyslexia rules KO.
Fair difference to note that the behavior is not the same but here the OP has a regular plain old Nano apparently