How to pass variable name to serial.print()?

Hi.

I have a list of Boolean volatile flags ex(button1, button2, button3) which I set inside ISR's and then test for in the Loop()..

I also have a function which receives and tests for any particular flag and then I want it to print the flag name if it is true.. How would I go about converting a boolean variable name into a printable string?

volatile bool button1flag = false;
volatile bool button2flag = false;

void test(bool a); //initialize function

ISR(INT2_vect){
   cli();
     button1flag = true;
  sei();
}

ISR(INT3_vect){
   cli();
     button2flag = true;
   sei();
}

void loop(){

  test(button1flag);
  test(button2flag);
}

void test(bool a) {
  if(a == true){
    Serial.println("a");
    a = false;     // <-- I also want to deactivate the flag after it has been tested.
  }
}

Thank you...

Once the code is compiled all the variable names are long gone and not available to use, hence you can't pass the name of a variable to a function unless you do it explicitly by passing a string, a pointer to a string or by passing a value that can be used to read the name from an array of names

1 Like

The same way as you're printing the variable name "a".

Serial.print ("button1flag = ");
Serial.println(button1flag);

That will print a 0 or 1. You can add an if-else statement if you want to print "true" or "false".

1 Like

Is this an experiment, or is it supposed to do something? There is no debounce logic in your program, to handle switch contact bounce.

Generally, the answer to your requirement (assuming it is really required), is to make an OO class of button objects, with all the data items associated with a button contained in the class. Then you instantiate an object from that class for each button you have. Each one would then have it's own I/O pin number, state, and also importantly for your purpose, a printable name. Furthermore, then, you can handle then in bulk, for example instead of:

  test(button1flag);
  test(button2flag);
  test(button3flag);
...

you can

  for (int i=0; i<NUMBER_OF_BUTTONS; i++) {
  buttons[i].test();
  }

the name would be printed like:

Serial.print( buttons[i].name() );

just to show a vague example. Your actual code may vary.

Also, your interrupt handling is flawed. You have implemented critical sections inside the ISR. That is completely the wrong place for them. Your cli() and sei() should be in the mainline code that samples the flags. Turning off interrupts inside an ISR does nothing because the CPU automatically disables interrupts as soon as an ISR is called, and enables them on return.

Usually when one ISR mistake is made, there are more. But I didn't look for them, I suggest you go to Nick Gammon's site and do some heavy reading on ISR's.
https://gammon.com.au/interrupts

2 Likes

yes, that is normally how I would go about this situation, but I'm trying to reduce repetitive code by using a function, and it seems like an OO class as recommended by @anon57585045 is the appropriate method.

OO isn't as scary as people think. Encapsulation and Inheritance flowed fairly naturally into my mind. Polymorphism is another story, it's one of those things that you can only understand once you understand it. :slight_smile: Luckily you don't need it most of the time.

thank you aarg.

I just got introduced to OO Class programming through these tutorials:
https://youtube.com/playlist?list=PL43pGnjiVwgTJg7uz8KUGdXRdGKE0W_jN so this will be the perfect opportunity to test this out..

I was hoping a simpler solution could be executed by use of a function.

And thank you for pointing out my redundant use of cli() sei(). Every little bit helps.

Well, it can. Sometimes that's all it takes, and so that's sometimes all I do.

yes absolutely, I didn't bother adding any debounce to this code because I'm focusing on the main topic, however, did you have a favorite debounce routine for ISR buttons? I know there's a bunch of them out there but I'm just wondering if you have one at your fingertips?

I have the pseudocode at my fingertips. :slight_smile:

ISR() {
if millis() - lastCall >= debounce interval
  {
  flag = true
  lastCall = millis()
  }
}

Note: There are a long list of reasons why you should never use interrupts for buttons.

Are there really a bunch of them out there? The mind boggles a little about how that is possible. :slight_smile:

Sweet, thanks for that piece of code.

I understand the issue with switch bounce and interrupts and that's why I use a hardware debouncer (NAND LATCH) on the buttons going into my circuits and I've been having great success with buttons and ISR's. Actually, the majority of my algorithm takes place in ISR land and void loop() takes care of all the other less time sensitive handling math or what have you.

Hi UKHeliBob,

do you have some code example reference for the method you recommend, please?

Thank you.

I am not sure that I would actually recommend this, but for a limited number of variables it could be made to work

void setup()
{
  Serial.begin(115200);
  boolean v1 = false;
  boolean v2 = true;
  printVar("v1", v1);
  printVar("v2", v2);
}

void loop()
{
}

void printVar(char * varName, boolean varValue)
{
  Serial.print(varName);
  Serial.print(" is ");
  {
    Serial.println(varValue ? "true" : "false");
  }
}
1 Like

I'll guess that there's a way to (ab)use the preprocessor to have a macro call your printVar function which would take a single parameter.

1 Like
#define debugPrint(v) do {Serial.print(F(#v " = ")); Serial.println(v);} while (0)

#v does "stringification" of the argument v, and two strings separated by a space concatenates them.
So debugPrint(foo) expands to:

do {
   Serial.print(F("foo" " = "));
   Serial.println(foo);
} while (0);

The do {} while(0) construct causes the multiple internal statements to be treated as a single statement, so that you can do things like

if (foo)
  debugPrint(foo);
2 Likes

Nice, albeit with a side order of OMG that's horrific :wink:

... Best disclaimer of the day :upside_down_face:

Heh. "Well known things that they don't teach you in school..."
A lot of "standard" stuff is pretty awful when you look at the details. I usually can't make heads or tails of the C++ STL code, for example. I'm sure it make sense once you get used to it.

WOW, that's a cool trick, I've been wondering about concatenating Serial.print strings together..

The best way to do that, if I understand your need correctly, is to use I/O streaming. e.g.

Serial << "the temperature is: " << temperature << " degrees." << endl;

https://github.com/janelia-arduino/Streaming

1 Like