Go Down

Topic: how to debug code in arduino IDE (Read 95097 times) previous topic - next topic

Unicornis

#15
Jul 19, 2018, 07:30 am Last Edit: Jul 19, 2018, 07:38 am by Unicornis
This my useful macro:
Code: [Select]
#define DEBUG

#ifdef DEBUG
 #define DEBUG_PRINT(x)  Serial.print(F(#x" = ")); Serial.print (x);Serial.print (F(" "));
#else
 #define DEBUG_PRINT(x)
#endif
#ifdef DEBUG
 #define DEBUG_PRINTLN(x)  DEBUG_PRINT(x); Serial.println (x);
#else
 #define DEBUG_PRINTLN(x)
#endif


it prints the variable name, then " = " and variable name.

example:
Code: [Select]

a=6;
b=0;
DEBUG_PRINT(a);
DEBUG_PRINT(b);

will produce the output:
a = 6 b = 0

the DEBUG_PRINTLN(x) additionally adds new line at the end. Variable labels are stored in program memory, so it does not add up to RAM usage.

Robin2

Two or three hours spent thinking and reading documentation solves most programming problems.

UKHeliBob

Works very nicely. Thank you.

...R
Thanks from me too.

There is a mistake in the definition of DEBUG_PRINTLN
It should be
Code: [Select]

 #define DEBUG_PRINTLN(x)  DEBUG_PRINT(x); Serial.println ();

instead of
Code: [Select]

 #define DEBUG_PRINTLN(x)  DEBUG_PRINT(x); Serial.println (x);

otherwise the value of the variable is printed twice
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Robin2

There is a mistake in the definition of DEBUG_PRINTLN
Thanks for mentioning that. I had noticed it and corrected it but forgot to mention it.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

larryd

#19
Jul 30, 2018, 08:23 pm Last Edit: Jul 31, 2018, 12:34 am by larryd
Thanks.

Removed the ; from the end of the macros.
Code: [Select]

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

//and

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


Add these to DebugMacros.h file:

Code: (DebugMacros.h) [Select]

//***************************************************************
//   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
//***************************************************************



Code: ("Example sketch") [Select]

#define DEBUG
#include <DebugMacros.h>

void setup()
{
  Serial.begin(9600);
}
void loop()
{
  for (byte x = 0; x < 100; x++)
  {
    delay(100);
    DEBUG_PRINTLN(x,HEX);
    DEBUG_PRINTLN(x,BIN);
  }
  
}



No technical PMs.
The last thing you did is where you should start looking.

robsworld78

#20
Jul 31, 2018, 02:29 am Last Edit: Jul 31, 2018, 02:31 am by robsworld78
Another good thing I've found is counting millis between functions so you can see speed and change things to compare, this helps optimize the code.

Create some variables like below
Code: [Select]
  unsigned long startMilli;
  unsigned long stopMilli;
  unsigned long loadMilli;

Then add this right before the function starts
Code: [Select]
  startMilli = millis();
And add this right after the function ends
Code: [Select]
  stopMilli = millis();
  loadMilli = stopMilli - startMilli;
  Serial.print(F("Load Millis: "));
  Serial.println(loadMilli);

Whatever "load millis" shows in the serial monitor is how long in milliseconds it takes to run.

Also remember Serial.prints dramatically slow down your code so comment them out before you do a speed test and when you are certain everything will be ok. :)

larryd

Another good thing I've found is counting millis between functions so you can see speed and change things to compare, this helps optimize the code.

Create some variables like below
Code: [Select]
  unsigned long startMilli;
  unsigned long stopMilli;
  unsigned long loadMilli;

Then add this right before the function starts
Code: [Select]
  startMilli = millis();
And add this right after the function ends
Code: [Select]
  stopMilli = millis();
  loadMilli = stopMilli - startMilli;
  Serial.print(F("Load Millis: "));
  Serial.println(loadMilli);

Whatever "load millis" shows in the serial monitor is how long in milliseconds it takes to run.

Also remember Serial.prints dramatically slow down your code so comment them out before you do a speed test and when you are certain everything will be ok. :)
Also, Mr. Gammon has a library called 'Profile Timer' for timing code.
https://www.gammon.com.au/forum/?id=11093   

Zip file:
http://www.gammon.com.au/Arduino/ProfileTimer.zip   





No technical PMs.
The last thing you did is where you should start looking.

robsworld78

Also, Mr. Gammon has a library called 'Profile Timer' for timing code.
https://www.gammon.com.au/forum/?id=11093  

Zip file:
http://www.gammon.com.au/Arduino/ProfileTimer.zip  
Why would you need a library for a couple lines of code lol... 

larryd

#23
Jul 31, 2018, 03:11 am Last Edit: Jul 31, 2018, 03:13 am by larryd
Try it, you will like it.


"The purpose of the braces is to "scope" the ProfileTimer class so that when it hits the closing brace it goes out of scope and the destructor is called."


No technical PMs.
The last thing you did is where you should start looking.

robsworld78

Don't knock it till you try hey, lol....

Hutkikz

#25
Feb 04, 2019, 12:34 am Last Edit: Feb 04, 2019, 12:39 am by Hutkikz
 I just ran across this old post again.
There is so much good info here that I just had to bump it back up.
It really should be in the useful links post.

Robin2

#26
Feb 04, 2019, 09:12 am Last Edit: Feb 04, 2019, 10:22 am by Robin2
My experience is mixed, to say the least.

I am building a project in which the logic is shared between a program on a Mega and a Python program on a PC. There has been a need for a LOT of debug messages in the Arduino code (and more to come, no doubt).

I started using the Macro from this Thread but the problem I found is that I don't want a single ON/OFF for my debug code, but a separate ON/OFF for each one, or for a small group of two or three. Eventually I just took out the Macro and have reverted to using Serial.print() and just commenting it out when that part works.

Somewhere in the mists of time I found a macro that turns something like
Code: [Select]
dbug(myVariable);
into
Code: [Select]
Serial.print("< myVariable "); Serial.print(myVariable); Serial.println('>');

I must try and find it again just to save my weary fingers

UPDATE ... this is it
Code: [Select]
#define dBug(abc) Serial.print("<  "#abc" = "); Serial.print(abc); Serial.println('>')

Note that the angle brackets are not necessary. I just use them like in the 3rd example in Serial Input Basics

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Hutkikz

Quote
Somewhere in the mists of time I found a macro that turns something like

Code: [Select]
dbug(myVariable);


into

Code: [Select]
Serial.print("< myVariable "); Serial.print(myVariable); Serial.println('>');



I must try and find it again just to save my weary fingers
That would be reply #15 of this thread ;)

Robin2

That would be reply #15 of this thread ;)
DOH ...

I must have got this Thread mixed up with another one.

Like the song says of New York ... "so good they named it twice"

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Watcher

Code: [Select]
#define DEBUG_PRINT(...)   Serial.print(F(#__VA_ARGS__" = ")); Serial.print (__VA_ARGS__);Serial.print(F(" ")) 
#define DEBUG_PRINTLN(...) DEBUG_PRINT(__VA_ARGS__); Serial.println()



Could someone please explain how this __VA_ARGS__ thing works?

Also this thread is very very useful for all users and therefore should /could it be made sticky?

Go Up