Better solution for Serial.debug

I have Serial.prints throughout my (sizeable) code. I need them to see what is going on and to make sure I am actually achieving my goals.

But... then, I have to go through and comment them all out, as these calls significantly affect the speed of the program.

I have occasionally on programs that are not so speed reliant, put a simple flag check before the Serial print commands to enable me to be able to turn them on/off with a simple flag set statement.

But, that in itself is making all the Serial.prints more complicated and therefore slower.

Is there a better way of achieving a debug of your running code, or is this the best way?

Does a simple 'If (ShowDebug == true){Serial.println("blah");}' slow a program down significantly? (Bearing in mind, there are a lot of them)

I recently watched a video, you can easily remove the debugging print statements with a single change to the code.

I couldn't find it, but I googled

  define debug serial.print arduino

and this article outlines the same idea:

There are endless tweaks and variations, but this one is dead simple to understand and works well.

HTH

a7

1 Like

That is an interesting link. Thank you.

I will try that

Thanks for that link. Works well.

#define DEBUG_C 1                                                       // Serial debug routine for critical functions

#if DEBUG_C==1                                                          // Setting this to anything but 1 will halt all crictical serial prints to the debug screen
#define outputDebugC(x); Serial.print(x);
#define outputDebugLineC(x); Serial.println(x);
#else
#define outputDebugC(x);
#define outputDebugLineC(x);
#endif

#define DEBUG_N 1                                                       // Serial debug routine for non critical functions

#if DEBUG_N==1                                                          // Setting this to anything but 1 will halt all non-critical serial prints to the debug screen
#define outputDebugN(x); Serial.print(x);
#define outputDebugLineN(x); Serial.println(x);
#else
#define outputDebugN(x);
#define outputDebugLineN(x);
#endif

Implemented 2 versions. One for critical debugging that doesn't affect my timing loops, and one for non-critical timing debugging for when I don't care if the timings etc are affected, but I would rather see all the debugging info.

I might add this feature as a twin dip switch on my PCB.

Thanks again

Nice. Someone did say

so you are on your way.

I like it! But... you'll have some work to do, as the magic happens at compile time... you'll be back to conditional statements of some kind. So you'll have the (slight) drag on things those tests will take.

Obvsly, I hope, the DIP switches could be read once at the top of your beautiful free running loop and stashed in boolean variables for use everywhere else, or in setup(), where a reset or power cycling would be necessary to change modes.

a7

The dip switches would be for testing enabled/disabled at boot only.
Once I am happy all was well, they would be turned off and the module rebooted and left off.

OK.... Can't work it out.

So the code below is defined at the boot of the processor.

How can I make that DEBUG flag change state once the program is running?

I want to implement a PCB mounted switch. A hard reboot isn't a problem, but how can I read the state of a switch (or memory location) before Setup()?

I thought of basically writing a bool state to EEPROM and then reading that back at boot, but you (don't appear) to be able to read an EEPROM value at this point in the boot routine.

#define DEBUG_C 1                                                       // Serial debug routine for critical functions

#if DEBUG_C==1                                                          // Setting this to anything but 1 will halt all crictical serial prints to the debug screen
#define outputDebugC(x); Serial.print(x);
#define outputDebugLineC(x); Serial.println(x);
#else
#define outputDebugC(x);
#define outputDebugLineC(x);
#endif

You can do something like this:

#define outputDebugC(x); if(enableDebugOutput)Serial.print(x);

Here is a demonstration program using the idea of a pin state on startup determining whether it is enabled (but the same could be done with a flag value in EEPROM if you like):

#define outputDebugC(x); if(enableDebugOutput)Serial.print(x);
bool enableDebugOutput;
const byte enableDebugPin = 2;
void setup() {
  Serial.begin(9600);
  pinMode(enableDebugPin, INPUT_PULLUP);
  if (digitalRead(enableDebugPin) == LOW) {
    enableDebugOutput = true;
  } else {
    enableDebugOutput = false;
  }
}

void loop() {
  outputDebugC("Some debug output");
  delay(1000);
}

So I may as well go back to have a simple bool flag before each serial.print statement.

I realise I can't change the DEBUG value after being complied. I was just hoping I could set it somehow so that next compile around, it could be read in a different state.

At the moment, I would have to actually upload new code to change that value

I have realised that.... Pretty obvious now that I think of it.

I have binned that code above and put in a simple bool to ignore un-required Serial.prints using the dip switch

i use sprintf() to format a complete line rather than use multiple Serial.print, for example, which also uses a bitmapped debug flag

    if (4 & debug) {
        sprintf (s, " %s: chip %d, bit %d, val0 0x%02x, val1 0x%02x",
            __func__, chip, bit, val0, val1);
        Serial.println (s);
    }

but by using an sprintf() and a single Serial.println() allows just the println to be commented out (if not using the debug flag)

        sprintf (s, " %s: chip %d, bit %d, val0 0x%02x, val1 0x%02x",
            __func__, chip, bit, val0, val1);
    //  Serial.println (s);

(the debug flag can be set at run time using the Serial monitor to process commands)

That is what the code I provided does. It just makes it so you don't have to write the code for each line. That is useful if you have a lot of debug code in your sketch.

I use something similar:

#define DEBUG true  // Set to true for debug output, false for no debug output.
#define DEBUG_SERIAL \
  if (DEBUG) Serial

I haven't had a need to be able to control debug output at runtime so you can see I just use a macro in the code to toggle it at compile time. But you could use a variable name in place of the DEBUG macro and set the variable at runtime.

As already pointed out by @alto777, there is overhead to the runtime-controllable system. This overhead includes memory usage in addition to clock cycles. The compile time-controlled system allows the compiler to optimize out the code when it is unreachable due to DEBUG being set to false.

I personally prefer the if (DEBUG) Serial approach over your macro function approach because I think it is more intuitive to still use the familiar Print API in the code:

DEBUG_SERIAL.begin(9600);
DEBUG_SERIAL.println("Some debug output");

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.