Like most users, I have become adept at using Serial.print() as a tool to assist debugging. The trouble is that in the process the program becomes littered with such statements, and it is a significant chore to remove these at the end to get production code. Leaving them to "dangle" is bad practice, and they should be either deleted or commented out. Note I am not whinging about a program with a dozen lines either, many of my programs are thousands of lines with pin change, timer and conventional interrupts and tracking down every single one of those lingering Serial.print() in every tab takes considerable time.
I was watching YouTube not long ago and came across a suggestion to use the pre-processor to help alleviate the problem. My apologies to the YouTuber in question, I have lost the link, or I would quote it for reference.
The suggestion is not rocket science. Basically the idea is to create a substitute for Serial.print() which can be made null easily when you are done debugging. Like this:
#define debug_print // manages most of the print and
println debug, not all but most
#if defined debug_print
#define debug_begin(x) Serial.begin(x)
#define debug(x) Serial.print(x)
#define debugln(x) Serial.println(x)
#else
#define debug_begin(x)
#define debug(x)
#define debugln(x)
#endif
This is pretty obvious but, for the sake of completeness (as the pre-processor is anything but obvious to anyone new to C), I will give a short explanation. If debug_print is defined then a new series of "functions" are created which are used for debugging just like Serial.print() but when you are done you just undefine debug_print (by commenting it out) and all the associated statements just vanish as the pre-processor does its substitution. So for example, you use debug(variable) to print the variable while debugging. When the bugs are all dead (or at least dormant) just undefine debug_print, recompile, download, and you are done.
Now, this works pretty well, and I can't see any real downside. (But please comment if you can think of anything). It is pretty clever of the original YouTuber, 100% obvious once you see it, and I cannot comment if it is original. It is certainly helpful.
But there is a problem. Serial.print() usually takes one argument, but it can take at least 2. Like when I want to see the output in hex, like this: Serial.print(variable,HEX). When tried this with debug it looks like this:
debug(temp,HEX);
But as you would expect the compiler will have none of it, returning an error:
macro "debug" passed 2 arguments, but takes just 1
I can see exactly why it complains, and that is not the question.
OK, I thought, just pop the arguments in parentheses to make it appear like one parameter:
Like this:
Serial.print((temp,HEX)); //original
debug((temp,HEX)); // debug version
Surely the parser will handle this and strip off the redundant brackets. And indeed it compiles. Example Code:
#define debug_print // manages most of the print and println debug, not all but most
#if defined debug_print
#define debug_begin(x) Serial.begin(x)
#define debug(x) Serial.print(x)
#define debugln(x) Serial.println(x)
#else
#define debug_begin(x)
#define debug(x)
#define debugln(x)
#endif
byte temp;
void setup()
{
debug_begin(115200);
temp = 42; // pick a number, any number
Serial.print(temp,HEX); // original for reference
Serial.println();
Serial.print((temp,HEX)); // extra brackets
Serial.println();
debug((temp,HEX)); // extra brackets
debugln();
}
void loop()
{
// no loop needed
}
and the result is:
2A
16
16
2A is correct, the rest are not. And you get 0x16 no matter what the variable is, there has to be a clue there.
So I am wondering why the extra brackets make so much difference. I was expecting the C parser to manage this. Obviously not. There is something I do not understand.
Also, has anyone with more experience with C than me got a fix for this other than defining another debug substitute with 2 parameters, and use the one you need and perhaps what I am missing about the parser?
Regards,