Serial Debug Toggle

Hello all

I found this thread from 2013
https://forum.arduino.cc/index.php?topic=155268.0

I found this a wonderfull idea and thought I might apply it on my project. This is how I wanted to do it:

/*Debugging*/
#define DEBUG true // flag to turn on/off debugging
#define Serial if(DEBUG)Serial
#define LCD if(!DEBUG)LCD

The compiler tells me "expected ';' before if" for the second line. I cant figure out why.

Thank you for your help.

moses

Please post a complete program that shows the problem

Hello UKHeliBob

I don't really know what part of the program I should post as everything works fine if I comment the above mentioned portion out.

How about "the bit that causes the problem described in your original post" ?

The compiler tells me "expected ';' before if" for the second line.

in some line preceding where you use "Serial", you're probably missing a semicolon. (i forget them all the time. It's one reason the "Go" language doesn't use semicolons)

I dont know if you meant that but I had a look on the thread of 2013 once again and I think I might have found an explanation:

Also you have to comment things like "Serial.Read" or "if (Serial.available() > 0)" inside your program else you will see this error:

Then they post a picture asking for the primary expression.

Is there some other way of doing something like that? The have a toggle to permit debugging?

Thank you moses

moserroger:
I don't really know what part of the program I should post as everything works fine if I comment the above mentioned portion out.

I have a funny feeling that is exactly why Bob said

Please post a complete program

If I had made a similar comment it would have been Please post the complete program

...R

moserroger:
you have to comment things like "Serial.Read" or "if (Serial.available() > 0)" inside your program

I think it's pretty rare for a debug system to require serial input, but the while(!Serial) thing is definitely a problem. But there is a better solution than commenting out the problematic lines:

#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 Serial statements 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., Leonardo, Micro, MKR, Nano 33 IoT), use this code:

#if DEBUG == true
  while(!Serial);
#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 can easily be extended to allow multiple levels of debug output, still with no overhead:

#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.

1 Like

Thank you for all the ideas!

I will try it out and see how it work.

FYI

//***************************************************************
//   Example of use: 
//   #define DEBUG  //                              <---<<< this line must appear before the include line
//
//   #include <DebugMacros.h>
// 
//If you comment the line:    #define DEBUG
//the Macro lines are defined as blank, thus would be ignored by the compiler
//#define DEBUG  // if this line is NOT commented, these macros will be included in the sketch
//examples:
//  This  converts to >>>>----------------------->  This OR a Blank Line.  
// DPRINTLN("Testing123");                          Serial.println("Testing123");  
// DPRINTLN(0xC0FFEEul,DEC);                        Serial.println(0xC0FFEEul,DEC); 
// DPRINTLN(12648430ul,HEX);                        Serial.println(12648430ul,HEX); 
// DPRINTLNF("This message came from your flash");  Serial.println(F("This message came from your flash"));
// DPRINT(myVariable);                              Serial.print(myVariable);
// DELAY(100);                                      delay(100);
// PINMODE(9600);                                   pinMode(9600);
// TOGGLEd13;                                       PINB = 0x20;  // D13 Toggle,for UNO ONLY
//
// Also, this works  #define INFO(...)  { Console->printf("INFO: "); Console->printf(__VA_ARGS__); }   >>>--->   where {} allows multiple lines of code.
// See: http://forum.arduino.cc/index.php?topic=511393.msg3485833#new

#ifdef DEBUG
//examples:
//#define DPRINT(args...)  Serial.print(args)  OR use the following syntax:
#define SERIALBEGIN(...)   Serial.begin(__VA_ARGS__)
#define DPRINT(...)        Serial.print(__VA_ARGS__)
#define DPRINTLN(...)      Serial.println(__VA_ARGS__)
#define DRINTF(...)        Serial.print(F(__VA_ARGS__))
#define DPRINTLNF(...)     Serial.println(F(__VA_ARGS__)) //printing text using the F macro
#define DELAY(...)         delay(__VA_ARGS__)
#define PINMODE(...)       pinMode(__VA_ARGS__)
#define TOGGLEd13          PINB = 0x20                    //UNO's pin D13

#define DEBUG_PRINT(...)   Serial.print(F(#__VA_ARGS__" = ")); Serial.print(__VA_ARGS__); Serial.print(F(" ")) 
#define DEBUG_PRINTLN(...) DEBUG_PRINT(__VA_ARGS__); Serial.println()

//***************************************************************
#else
#define SERIALBEGIN(...)  
#define DPRINT(...)       
#define DPRINTLN(...)     
#define DPRINTF(...)      
#define DPRINTLNF(...)    
#define DELAY(...)        
#define PINMODE(...)      
#define TOGGLEd13      

#define DEBUG_PRINT(...)    
#define DEBUG_PRINTLN(...)  

#endif
//***************************************************************

larryd:
FYI

//***************************************************************

//  Example of use:
//  #define DEBUG  //                              <---<<< this line must appear before the include line
//
//  #include <DebugMacros.h>
//

I guess I might have to look at DebugMacros.h

pert:
This can easily be extended to allow multiple levels of debug output, still with no overhead:

#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.

I really like the idea of several debug levels. I guess I could then just leave the statements within the sketch and turned them on and off as needed.

On the other hand I usually slow my serial output down to be better able to read. Is there a way that I can automatically add a blink without delay type of statement to the serial debug statements within my sketch?

Or is there any other way to improve the readability of the serial output?

Thank you!

moserroger:
Is there a way that I can automatically add a blink without delay type of statement to the serial debug statements within my sketch?

Sure:

#if DEBUG == true
const unsigned long currentMillis = millis();
if (currentMillis - debugOutputTimestamp >= debugOutputInterval) {
  debugOutputTimestamp = currentMillis;
  DEBUG_SERIAL.println(F("Some debug information"));
}
#endif  // DEBUG == true

Thank you pert

I am sorry. Still to inexperienced:

Can I combine this with the above idea of various inputs and how do I add individual messages?

Thanks again! moses

I tried to read up a little bit. But still unsure how this works.

So this code

#if DEBUG == true
const unsigned long currentMillis = millis();
if (currentMillis - debugOutputTimestamp >= debugOutputInterval) {
  debugOutputTimestamp = currentMillis;
  DEBUG_SERIAL.println(F("Some debug information"));
}
#endif  // DEBUG == true

would appear if

#define DEBUG true  //set to true for debug output, false for no debug ouput

is true?

But is it somehow connected to

#define DEBUG_SERIAL if(DEBUG)Serial

?

Because if not how would I get the first code to the place in my sketch where I want it?

How would I be able to adapt the "Some debug information"?

Thank you!

moserroger:
is true? Often, the best way to answer these sorts of questions is to simply try it out. One of the great things about Arduino is it's so fast and easy to run experiments.

Correct. #if is a preprocessor conditional. The compiler will simply ignore all the code between the #if and the #endif if the #if conditional evaluates to false.

moserroger:
But is it somehow connected to

#define DEBUG_SERIAL if(DEBUG)Serial

?

Only in that I used DEBUG_SERIAL here:

  DEBUG_SERIAL.println(F("Some debug information"));

The #define directive simply causes a text replacement. So if you have this:

#define DEBUG true  //set to true for debug output, false for no debug ouput
#define DEBUG_SERIAL if(DEBUG)Serial

The second line is equivalent to:

#define DEBUG_SERIAL if(true)Serial

Then this line:

  DEBUG_SERIAL.println(F("Some debug information"));

is equivalent to:

  if(true)Serial.println(F("Some debug information"));

More information on preprocessor directives:
http://www.cplusplus.com/doc/tutorial/preprocessor/

moserroger:
Because if not how would I get the first code to the place in my sketch where I want it?

What do you mean by "the first code"?

moserroger:
How would I be able to adapt the "Some debug information"?

Just put anything you want to print out in there. I used the F() macro to keep the string literal ("Some debug information") from using up dynamic memory, but you don't need that if you want to simplify things:

  DEBUG_SERIAL.println("Some debug information");

In my limited understanding of coding I have the impression that the string "Some debug information" in this way of doing it is "hard coded". Would I need to do the same for every message I want to print? Is there a way to add the blink without delay and the possibility to turn debugging on and off in a general way? I mean with the possibility to add whatever message or several different messages to print?

pert:
Sure:

#if DEBUG == true

const unsigned long currentMillis = millis();
if (currentMillis - debugOutputTimestamp >= debugOutputInterval) {
  debugOutputTimestamp = currentMillis;
  DEBUG_SERIAL.println(F("Some debug information"));
}
#endif  // DEBUG == true

You can put anything you want in there. It works just like Serial.println(). For example:

DEBUG_SERIAL.print("The value of someVariable is: ");
DEBUG_SERIAL.println(someVariable);

Just get out your Arduino board and run some experiments and it will be clear to you soon enough.

pert:
You can put anything you want in there. It works just like Serial.println(). For example:

DEBUG_SERIAL.print("The value of someVariable is: ");

DEBUG_SERIAL.println(someVariable);



Just get out your Arduino board and run some experiments and it will be clear to you soon enough.

I do understand how this code works:

#define DEBUG true  //set to true for debug output, false for no debug ouput
#define DEBUG_SERIAL if(DEBUG)Serial

But the version with the added blink without delay code doesn't just replace the DEBUG_SERIAL code within my sketch, does it? I have the impression that in that code the message is hard coded. And I have difficulty to understand how this version findes the right place in the sketch where it needs to be.

moserroger:
But the version with the added blink without delay code doesn't just replace the DEBUG_SERIAL code within my sketch, does it?

You have to put the blink without delay code in your sketch where you want it. I suppose it could be turned into a function if you were going to have a bunch of different "blink without delay" debug outputs and didn't want to have code duplication.

moserroger:
I have the impression that in that code the message is hard coded.

This message is hard coded:

DEBUG_SERIAL.print("The value of someVariable is: ");

this part will print whatever the value of someVariable is:

DEBUG_SERIAL.println(someVariable);

My suggestion is that you try to implement this debug system in a test sketch, then if you get stuck, post the sketch here. That will make it more clear to us what you are trying to accomplish.