Use a function to return a string, then print this return value in the void loop

Hi.

I come from a python background so forgive me if I am missing some essentials here.
What I am trying to do is write a function that will return a value. Then I want the void loop to print whatever value it returns.

In python that would be:

def func():
    return "ninja"

print (func)

Now what I have in my Arduino code is the following:

void loop() {
  Serial.println(returnButtonLetter());
}

boolean isClicked(int button){
  return digitalRead(button) == HIGH;
}

String returnButtonLetter(){
  if (isClicked(buttonA)){
    Serial.println("Returning A");
    return String("A");
  }else if (isClicked(buttonB)){
    Serial.println("Returning B");
    return String("B");
  }else if (isClicked(buttonC)){
    Serial.println("Returning C");
    return String("C");
  }
}

The code is trying to do the following:

  1. boolean isClicked() is checking if a button is pressed. The button is in the argument. "int button". All buttons are set to INPUT_PULLUP so HIGH should mean when it is actually clicked.

  2. String returnButtonLetter() checks if button A is clicked, button B is clicked or button C is clicked. If any of these are clicked it should return the corresponding letter. If you click the A button, it returns "A".

  3. void loop() tries to print the return value. I am expecting a single letter.

When I have the code set up like this, the serial monitor goes bananas...
XY problem:
What I am actually trying to achieve with the code is to click a button labeled A , B or C. Then add this to an array. I would append it to the array in python, but I understand that I have to predefine the length of the array in Arduino and then check if the index is empty. If it is I add the character?

Appreciate any help.

cheers,
Martin

All buttons are set to INPUT_PULLUP so HIGH should mean when it is actually clicked.

LOW would mean it's clicked ....

your image

(we would advise not to use the String class)

And what String is returned when nothing is clicked..?

@ J.M.L:
Thank you. If I check for LOW, it triggers "Returning A" in a constant stream of prints. That's why I assumed HIGH was correct. If I check for HIGH, it only triggers when I actually click the button.

I have read several places that String should be avoided. One would think that such a vital class would work better. I did test to just return an int instead and go if 1, add A, if 2 add B etc. but it didn't really feel right.

Any idea what is happening to the Monitor?

@TheMemberFromerlyKnownAsAWOL:
I don't want it to return anything when there are no clicks. I just want to get the input from the user. So click kicks off a letter. If there are no clicks , nothing happens.

martinaaberge:
I don't want it to return anything when there are no clicks. I just want to get the input from the user. So click kicks off a letter. If there are no clicks , nothing happens.

You've promised the compiler that your function will return a String. So, you must return a String for EVERY call to that function. What that String contains is up to you.

It’s likely that your buttons are not wired properly. It should be wired like this : Pin — button — GND

The String class works but through dynamic memory allocation / de-allocation which could lead to poking holes in the dynamic memory storage area and at some point not having the ability to allocate a String (which you don’t test for).

There is no OS to do garbage collection nor a concept of virtual memory and your UNO has a very small Memory hence the preference for avoiding dynamic allocation or do that in a very conscious way.

Here to return one char there is no need for strings at all, just return a char ‘A’ or ‘B’ or the NULL char if nothing is pressed ‘\0’ (as you need to return something and test what is returned before printing)

if you want to return the state of the 3 buttons as a String, like "ABC" if the 3 of them got pressed at the same time you could do something like this

const uint8_t buttonA = 2;
const uint8_t buttonB = 3;
const uint8_t buttonC = 4;

char* const getButtonPhrase()
{
  static char buttonSentence[4]; // if 3 buttons pressed return "ABC" and need space for trailing '\0'

  static uint8_t previousA = 0xFF;
  static uint8_t previousB = 0xFF;
  static uint8_t previousC = 0xFF;

  uint8_t currentA, currentB, currentC;

  currentA = digitalRead(buttonA);
  currentB = digitalRead(buttonB);
  currentC = digitalRead(buttonC);

  memset(buttonSentence, '\0', 4); // erase previous sentence

  // check if HIGH to LOW transition
  if ((currentA == LOW) && (previousA == HIGH)) strcat(buttonSentence, "A");
  if ((currentB == LOW) && (previousB == HIGH)) strcat(buttonSentence, "B");
  if ((currentC == LOW) && (previousC == HIGH)) strcat(buttonSentence, "C");

  previousA = currentA;
  previousB = currentB;
  previousC = currentC;

  return buttonSentence;
}

void setup()
{
  pinMode(buttonA, INPUT_PULLUP); // 2 <<--->> button <<--->> GND
  pinMode(buttonB, INPUT_PULLUP); // 3 <<--->> button <<--->> GND
  pinMode(buttonC, INPUT_PULLUP); // 4 <<--->> button <<--->> GND

  Serial.begin(115200);
}

void loop()
{
  char* const s = getButtonPhrase();
  if (strlen(s) != 0) Serial.println(s);
  delay(50); // will also serve as anti-bounce
}