To debug or not debug... That, is the question!

Since debugging in Arduino seems all about printing values through the serial port, I was wondering the best way to turn on and off debugging.

Every time I want to check an area of code do I have to put in on/off states? Example:

int debug = 1;

if (debug == 1) {
Serial.println("If you're reading this message... RUN!!!!!!!!!");
}

That means putting "if (debug == 1) {" conditions everywhere I put Serial.print. Adding a lot of lines of code : (

Or:

Can I just condition a single line of code to toggle everything? Example:

if (debug == 1) {
Serial.begin(9600);
}
Which basically stops the Arduino from communicating.

I'm wondering if removing the Serial.begin function is ok if there is still Serial.print code all over the rest of the program?

Will it cause any problems?

Thanks for any help!

If you don't have a Serial.begin(), you can't use Serial.print(). The Serial.print() function will have no idea what speed to use to output the data.

You can use #define and #ifdef to conditionally compile Serial function calls, reducing the size of the code when debug output is not required.

As Pauls says you can use defines

#define DEBUG

#ifdef DEBUG
Serial.print();
#endif

However this get real messy real fast and can make the code all but impossible to read if there are a lot of them.

It's possible what you are suggesting will work, ie of you don't call Serial.begin all subsequent prints will do nothing. I would expect the Serial library to have something

if (not_inited) return;

At the start of all calls. In which case you are OK.

It's not all that kosher but may work as long as your application doesn't need to use the serial port.


Rob

I usually do something like:

#define DEBUG 0

#if DEBUG
#define DEBUGMSG(m) Serial.print(m)
#else
#define DEBUGMSG(m)
#endif

void setup()
{
#if DEBUG
   Serial.begin(9600);
   DEBUGMSG("sketch starting");
#endif
}

This also allows you to debug on a desktop pretty easily by doing#define DEBUGMSG(m) fprintf(stderr, m)

1 Like

Graynomad:
#ifdef DEBUG
Serial.print();
#endif

However this get real messy real fast and can make the code all but impossible to read if there are a lot of them.

That's really the issue for me. I currently have over 120 serial.print lines for debugging and would like to put a lot more.

Putting 120 plus #ifdef DEBUG / #endif all over the place is something I would like to avoid =(

Does anyone know for sure if it is safe to just toggle the Serial.begin() on and off to stop the Arduino sending messages?

Thanks : )

See reply #3.

AWOL:
See reply #3.

Please correct me if I'm wrong. But isn't reply #3 just a preprocessor version of what I originally said?

If so, I was worried what effect (if any) 120+ Serial.print messages constantly running into nowhere would have. It's a definite "no problem"?

Thanks for your attention to my questions : )

Please correct me if I'm wrong. But isn't reply #3 just a preprocessor version of what I originally said?

No, because instead of writing

#if DEBUG
  Serial.print (blah);
#endif

repeatedly, you just write DEBUGMSG(blah); wherever you want debug output.

If DEBUG is 0, then the prints simply don't exist, so no need for a runtime conditional - the preprocessor takes care of it all.

(I usually do it with "#ifdef DEBUG", but the principle is the same. If pushed, I'd probably write some PROGMEM macros for debug prints if I thought I'd need a lot of them)

The disadvantages of prints running into nowhere are:

  1. The messages consume precious RAM
  2. Even if they go nowhere, at 9600 baud, they delay your program by over 1ms per character.

I currently have over 120 serial.print lines for debugging and would like to put a lot more.

Thats a lot of debugging lines... I wonder did you make design for your sketch. What your sketch supposed to do and in what order? just with a pencil and paper and a pair of brains and a mug of coffee? One clear design prevents 100's of debug statements...

And beware, so much debug statements affect the behaviour of your sketch ...

BTW Another option to debug is using a spare pin with a LED, could be enough in many places and is very fast...

So, the most likelly reason is that someday you will have problems because all those debug prints ate all your RAM and you dont know.

SO I add another debug statement to check where the RAM is eaten away ... :wink:

And if its eaten away before that?

@SparksAlot
It's very unusual to have that many debug statements and also to leave them in the code.

I can think of one function where I have done so because it's quite complicated and for some time a new bug kept popping up so it was convenient to just re enable the debug statements rather than figure out what to print all over again. (no bugs for a year or so now, maybe I should clean it up :))

However in general a program should be modular with each module (normally a function) tested with test data then ticked off as working and all the debug dross removed.


Rob

@Rob

no bugs for a year or so now, maybe I should clean it up

The absence of bugs for a year is still no guarantee for errorfree code :wink:

and all the debug dross removed.

I always say leave it where it is.
If you have a robust, generic and tested method of enabling and disabling test code, then the fewer times you edit a source file, the fewer chances there are for the inadvertent introduction of bugs.
The temptation of "I'm here to remove the debug code, but I'll just have a little tidy up while I'm at it" is too great for most tinkerers.

It's what we do in my day-job (many MLOCs).

Always be aware, however, that even if it isn't connected to anything, enabled debug code may be affecting performance and consuming resources like time and RAM.

You can have too much of a good thing.

enabled debug code may be affecting performance and consuming resources like time and RAM.

Stronger: enabled debug code ALLWAYS affect performance and resources, but it can also affect the logic/semantic of your application (esp real time behavior, e.g. IRQ's )

In my app, I was spending so much time dumping debug messages out the first serial port that it made the problem worse by delaying the app, causing me to miss bytes coming in to the other serial port.

The macro solution suggested earlier is a good one.

Too bad we don't have a source level debugger! That would save SO MUCH time!

The temptation of "I'm here to remove the debug code, but I'll just have a little tidy up while I'm at it" is too great for most tinkerers.

That's true. I guess all shops have different practices. In one place I worked the code had to be tested without any debug code (commented or #if'd out), then we had to remove all debug code and DIFF the file(s) against the originals. The lot was then peer reviewed by a colleague. No "tinkering" was allowed.

Another practice for small changes was to add initials and date on every changed line, something like

/rg12jul85/

It was quite common as the first debugging technique when a bug was reported to search for a couple of well-known initials (of people who had not lasted in the job) for suspect code :slight_smile:


Rob

AWOL:
2) Even if they go nowhere, at 9600 baud, they delay your program by over 1ms per character.

If the USART Transmitter has not been enabled, then it will not spend any time shifting out any characters put into the Transmit register. The Data Register Empty and Transmit Complete flags will always be true. The only time that will get consumed is the write operation pushing characters into the Transmit buffer and waiting for the UDRE flag to get set (which will always be set). This still takes some time, but it'll be on the order of a few microseconds per character.

That being said, it's still a poor method of enabling/disabling debug messages. The method westfw presents is far better (and doesn't prevent you from using the serial port for other purposes as well).

By "nowhere", I meant that the code was enabled, but there was nothing hanging off the Tx pin.

The only time that will get consumed is the write operation pushing characters into the Transmit buffer and waiting for the UDRE flag to get set (which will always be set). This still takes some time, but it'll be on the order of a few microseconds per character

And when you send another character when there's one already being sent, like in a multi-character debug string?

Every time you go to write a new character, you have to wait until the last one has been clocked out, so every character (apart from the first, assuming it is more than a character period since the last string was sent) will consume, at 9600 baud, over 1 millisecond, whether or not there is something at the far end of the serial line/USB serial/taut string to receive it.

void HardwareSerial::write(uint8_t c)
{
  while (!((*_ucsra) & (1 << _udre)))
    ;

  *_udr = c;
}