I don't have muchknowledge about macros.
Somewhere years ago I found a similar macro like this online and then modified it to my needs.
one important thing to know is that the backslash at the end of the lines has a very special meaning and is required as a must.
inside a "#define"-macro this backskash "\" has the meaning
"macro continues in the next line.
If you delete a single backslash the macro ends at the line above and you well get strange sounding compiler-errors that only make sense if you are know this funcionality of the backslash inside a "#define-macro"
If you look inside these macros you will see that some of them use the integertype long
or
float
A macro does replace source-code before
compiling. And this is the reason why you can't mix integer and float types directly.
If you want to do that you will have to write a macro that is based on the technique that user @gfvalvo showed in his demo-sketch.
// MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START *
// a detailed explanation how these macros work is given in this tutorial
// https://forum.arduino.cc/t/comfortable-serial-debug-output-short-to-write-fixed-text-name-and-content-of-any-variable-code-example/888298
#define dbg(myFixedText, variableName) \
Serial.print( F(#myFixedText " " #variableName"=") ); \
Serial.println(variableName);
#define dbgi(myFixedText, variableName,timeInterval) \
{ \
static unsigned long intervalStartTime; \
if ( millis() - intervalStartTime >= timeInterval ){ \
intervalStartTime = millis(); \
Serial.print( F(#myFixedText " " #variableName"=") ); \
Serial.println(variableName); \
} \
}
#define dbgc(myFixedText, variableName) \
{ \
static long lastState; \
if ( lastState != variableName ){ \
Serial.print( F(#myFixedText " " #variableName" changed from ") ); \
Serial.print(lastState); \
Serial.print( F(" to ") ); \
Serial.println(variableName); \
lastState = variableName; \
} \
}
#define dbgcf(myFixedText, variableName) \
{ \
static float lastState; \
if ( lastState != variableName ){ \
Serial.print( F(#myFixedText " " #variableName" changed from ") ); \
Serial.print(lastState); \
Serial.print( F(" to ") ); \
Serial.println(variableName); \
lastState = variableName; \
} \
}
// MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END *
unsigned long MyTestTimer;
byte myByte = 0;
int myInt = -100;
long myLong = -1000000;
float myFloat = -12345.78;
void setup() {
Serial.begin(115200);
Serial.println("Setup-Start dbg-Macro-Demo");
PrintFileNameDateTime();
MyTestTimer = millis();
}
void loop() {
myInt++;
dbgi("02",myInt,2000);
myLong += 100;
dbgi("03",myLong,4000);
if ( TimePeriodIsOver(MyTestTimer,1000) ) {
myByte++;
dbg("00",myByte);
myFloat += 2345.67;
}
dbgcf("999",myFloat);
}
// helper-functions
void PrintFileNameDateTime() {
Serial.println( F("Code running comes from file ") );
Serial.println( F(__FILE__) );
Serial.print( F(" compiled ") );
Serial.print( F(__DATE__) );
Serial.print( F(" ") );
Serial.println( F(__TIME__) );
}
// easy to use helper-function for non-blocking timing
// explanation see here
// https://forum.arduino.cc/t/example-code-for-timing-based-on-millis-easier-to-understand-through-the-use-of-example-numbers-avoiding-delay/974017
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - startOfPeriod >= TimePeriod ) {
// more time than TimePeriod has elapsed since last time if-condition was true
startOfPeriod = currentMillis; // a new period starts right here so set new starttime
return true;
}
else return false; // actual TimePeriod is NOT yet over
}
void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
static unsigned long MyBlinkTimer;
pinMode(IO_Pin, OUTPUT);
if ( TimePeriodIsOver(MyBlinkTimer,BlinkPeriod) ) {
digitalWrite(IO_Pin,!digitalRead(IO_Pin) );
}
}
I don't know anything about how to use templates like user @gfvalvo showed in his demo-sketch.
To me the given names are not all clear.
@gfvalvo
"first" somehow indicate the first, first what?
first type or first variable?
Is the meaning of the three dots "..."
there can follow a list of whatever kind variables?
Why did you name "T" T?
I think there can be much more selfexplaining typenames and variable names.
And how the heck does this work to have the exact same function name
why do you name "Remainder" Remainder?
And why is it written one time with a capital letter Remainer
and one time with a lower-case letter?