How to execute function directly based on user's input

Instead of using code like this:

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
}

void loop() {
  if (Serial.available() > 0) {
    String input = Serial.readStringUntil('\n');
    
    if (input.equals("ledon")) {
      turnOnLED();
    } else if (input.equals("ledoff")) {
      turnOffLED();
    } else {
      Serial.println("Invalid command");
    }
  }
}

void turnOnLED() {
  digitalWrite(ledPin, HIGH);
  Serial.println("LED turned on");
}

void turnOffLED() {
  digitalWrite(ledPin, LOW);
  Serial.println("LED turned off");
}

Is there ANY way to write code which calls a function directly, based on a user's input? ie. NOT using if/ else or switch statements. Even if this means writing an external C function/ program. Something on the lines of:

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
}

void loop() {
  if (Serial.available() > 0) {
    String input = Serial.readStringUntil('\n');

    >>exec(input);<<  //if user enters 'turnOnLED', execute that function.
  }
}

void turnOnLED() {
  digitalWrite(ledPin, HIGH);
  Serial.println("LED turned on");
}

void turnOffLED() {
  digitalWrite(ledPin, LOW);
  Serial.println("LED turned off");
}

Welcome

Functions names are lost after the program is compiled, so it's not that easy.

You can do with an array, each item of the array containing the function name as a string, and a function pointer. Use a for loop to compare the user input with each items names in the array ; if it matches, call the function pointer.

1 Like

maybe this

const byte ledPin = LED_BUILTIN;

void turnOnLED() {
  digitalWrite(ledPin, HIGH);
  Serial.println("LED turned on");
}

void turnOffLED() {
  digitalWrite(ledPin, LOW);
  Serial.println("LED turned off");
}

void (*func [])(void) = {
    turnOffLED,
    turnOnLED,
};
const int Nfunc = 2;

void loop() {
  if (Serial.available() > 0) {
    String input = Serial.readStringUntil('\n');
    int    n = input.toInt();

    if (n < Nfunc)
        func[n] ();
  }
}

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
}
1 Like

This example shows what I described

1 Like
  if (n >= 0 && n < Nfunc)

a7

should have made "n" unsigned

Thank you for your example.

Is it possible to access an internal function like 'digitalWrite()' directly, without using pointers, if/ else or switch statements? Or do the same issues apply?

Can you use function pointers to point to internal functions?

to the compiler there is no difference between your own function or functions provided by Arduino like digitalWrite. Once it's compiled, it's all your code, so you can take the address of any function.

But as said before, function names do go away when you compile, it's not an interpreted language environment. Once in your arduino it's just bytes and pointers etc, nothing trying to parse a function name dynamically to find out what to do next.


if you were trying to tell us what's the goal, may be we can suggest an alternative approach.

Hi, @tom707

Is this an intellectual pursuit, or does this thread have a practical use?

Interested to know.

Thanks.. Tom.. :grinning: :+1: :coffee: :australia:

I would like to change any setting and control the Arduino board from an external device, like an Android smartphone.

I was hoping to do this without having a large switch structure with all the functions I require, or having to type them all out into a pointer array.

For example, by entering the function name I required into Serial Monitor, and the board executes the function directly.

as said, not possible

1 Like

As already pointed out, that's not possible. The Arduino simply doesn't know anything about your function names, until you explicitely write them as strings into your code and compare which you want to execute. However you do that.

1 Like

As the other said, you need to develop specific code for this. Ideally you build a "language" with grammar rules, keywords etc and then your arduino code is a parser for that language ➜ you add an interpreter on top of your arduino.

there are simple examples out there you could look at, here is the first google hit:

You could easily generate that table, for example using a Python script.

Presumably, you need to type out all the functions anyway, adding one line to an array doesn't seem that hard.

Yeah, this is pretty much what I'm trying to achieve. Thanks.

Now imagine there was an Arduino/ C library that allowed this:

String input = Serial.readStringUntil('\n');
exec(input); //input is 'digitalWrite()', 'digitalRead()', etc.

Instead of:

else if (strcmp_P(command, PSTR("mode")) == 0) {
        int pin = atoi(strsep(&cmdline, " "));
        int mode = atoi(cmdline);
        pinMode(pin, mode);
    } else if (strcmp_P(command, PSTR("read")) == 0) {
        int pin = atoi(cmdline);
        Serial.println(digitalRead(pin));
    } else if (strcmp_P(command, PSTR("aread")) == 0) {
        int pin = atoi(cmdline);
        Serial.println(analogRead(pin));
    } else if (strcmp_P(command, PSTR("write")) == 0) {
        int pin = atoi(strsep(&cmdline, " "));
        int value = atoi(cmdline);
        digitalWrite(pin, value);
    } else if (strcmp_P(command, PSTR("awrite")) == 0) {
        int pin = atoi(strsep(&cmdline, " "));
        int value = atoi(cmdline);
        analogWrite(pin, value);
    } else if (strcmp_P(command, PSTR("echo")) == 0) {
        do_echo = atoi(cmdline);
    } else {
        Serial.print(F("Error: Unknown command: "));
        Serial.println(command);
    }

How much simpler, and how much more power would that provide. Somebody should write such a library.

Simpler than what?
And when it comes to power - you realize it’s super slow, right?

I meant a library that would add this functionality using function pointers.

You haven't added anything constructive on this post, so why are you posting on this forum??

Other languages that can run on at least some arduinos can do this (usually with a major performance impacts.). Basic interpreters and bitlash (sort of), and Forth, python, LisP, etc have inherent internal symbol tables.

Function pointers are a red herring, the compiled code needs to know the function name to get the pointer. There is no magic solution here, it is a Simple Matter of Writing Code.

I guess if you had standard functions like "digitalWrite" then it could be self-contained, and you could add custom commands at run-time. All you are doing is writing your own interpreter (which was suggested earlier).

Agreed, you need the code, you should write it!

The fact that someone hasn't pretty much shows it's not a useful idea.

1 Like