In the case where all my Serial output is for debugging, I use this:
#define DEBUG true //set to true for debug output, false for no debug output
#define DEBUG_SERIAL \
if (DEBUG) Serial
Then use debug output like this:
DEBUG_SERIAL.println("Some debug output");
When DEBUG is set to false, the compiler will optimize the calls using DEBUG_SERIAL out of the code because it knows they will never run.
If you want your program to wait for Serial Monitor to be opened before running when using native USB boards (e.g., Arduino Leonardo), add this line:
#if DEBUG == true
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
#endif // DEBUG == true
In the rare case where your debug system needs to read serial input, you would use similar code:
#if DEBUG == true
if (Serial.available()) {
x = Serial.read();
}
#endif // DEBUG == true
This system can easily be extended to allow multiple levels of debug output, still with no overhead when it's disabled:
#define DEBUG_ERROR true
#define DEBUG_ERROR_SERIAL \
if (DEBUG_ERROR) Serial
#define DEBUG_WARNING true
#define DEBUG_WARNING_SERIAL \
if (DEBUG_WARNING) Serial
#define DEBUG_INFORMATION true
#define DEBUG_INFORMATION_SERIAL \
if (DEBUG_INFORMATION) Serial
void setup() {
Serial.begin(9600);
while (!Serial)
;
DEBUG_ERROR_SERIAL.println("This is an error message");
DEBUG_WARNING_SERIAL.println("This is a warning message");
DEBUG_INFORMATION_SERIAL.print("The state of pin 5 is ");
DEBUG_INFORMATION_SERIAL.println(digitalRead(5) ? "HIGH" : "LOW");
Serial.println("This is standard program output");
}
void loop() {}
You can use the Boolean debug macros to switch on and off other parts of your code too.
A problem is that you need a "type" for the toprint argument, but Serial.print() accepts a whole bunch of different types (strings, floats, integers, integers AND base, floats AND precision...)
AFAIK, there's not clever way to do this in C/C++, so you're forced into using less elegant techniques like Pert's preprocessor-macro based technique.