It would be helpful with my project to be able to update a variable value through the Serial Monitor. An example would be typing into the Serial Monitor "valOne=33" and have the already defined variable int valOne = 0; then set to 33?
I know that I could use an if statement for each variable name or a switch statement, however I am hoping there is a method that does not require me to predefine the if statement comparisons or switch statement cases?
Possibly through a command that returns all of the variable names defined into an array? So that I could loop through them and if one matches "valOne", I can have a generic function that updates that variable?
I'm not coming up with much in a search and I'm sure I am not the first to ask about this, so I'm also open to ideas if someone has a better approach.
I think you have to populate such array in the code before compilation yourself, because there is no method to get all variable names in the C automatically
you could create a table of strings, ptrs to the variables, #bytes and type that a relatively small piece of logic can operate on, given a variable name and value. Simlar logic could be used to dump the table of variable values and strings
Well, it is possible but not in C++/Arduino "base" language.
There is a programming language concept called Reflection which is available in higher-level languages. It allows you to explore attributes defined in your program without prior knowledge of them.
Some arduino boards can run MicroPython or CircuitPython and Python supports reflection. That's the only way that I can think of doing it with arduino. Even then, I don't know if the arduino variants will support Python's reflection features.
After reading all of the comments, I think I'm too noob to implement it properly and understand it completely. I'm going to reread it a few more times and see if it starts to be more clear after a few rereads.
I was thinking that there might be a way of doing it if the program processed its own .map file to find where functions & global variable are stored, but TBH, that sounds rather painful.
For this to work, it appears that each variable needs predefining in the vars array, is my understanding correct?
I tried to add a boolean variable to see if I understood how it worked, I was not able to set it to "true" or "false" but could set it to 0 or 1, which I believe is because I used atoi ? I don't believe there is an atobool function?
byte b = 123;
int i = 30000;
float f = 1.23;
bool exOn = false;
// -----------------------------------------------------------------------------
enum { Byte, Int, Float, Bool };
struct Var{
void *ptr;
int nByte;
int type;
const char *name;
}
vars [] = {
{ &b, sizeof(byte), Byte, "b" },
{ &i, sizeof(int), Int, "i" },
{ &f, sizeof(float), Float, "f" },
{ &exOn, sizeof(bool), Bool, "exOn"},
};
const unsigned Nvar = sizeof(vars)/sizeof(Var);
// -------------------------------------
void
varDump ()
{
Var *v = &vars [0];
for (unsigned n = 0; n < Nvar; n++, v++) {
switch (v->type) {
case Byte:
Serial.print (*(byte*) v->ptr);
break;
case Int:
Serial.print (*(int*) v->ptr);
break;
case Float:
Serial.print (*(float*) v->ptr);
break;
case Bool:
Serial.print (*(bool*) v->ptr);
break;
}
Serial.print (" ");
Serial.println (v->name);
}
}
// -------------------------------------
void
varSet (
char *name,
char *val )
{
Var *v = &vars [0];
for (unsigned n = 0; n < Nvar; n++, v++) {
if (! strcmp (v->name, name)) {
switch (v->type) {
case Byte:
*(byte *) v->ptr = atoi (val);
break;
case Int:
*(int *) v->ptr = atoi (val);
break;
case Float:
*(float *) v->ptr = atof (val);
break;
case Bool:
*(bool *) v->ptr = atoi (val);
break;
}
return;
}
}
Serial.print ("setVar: ");
Serial.print (name);
Serial.println (" - not found");
}
// -----------------------------------------------------------------------------
void
loop (void)
{
if (Serial.available ()) {
char buf [90];
int n = Serial.readBytesUntil ('\n', buf, sizeof(buf)-1);
buf [n] = '\0';
switch (buf [0]) {
case 'd':
varDump ();
break;
case 's':
char name [20];
char val [20];
sscanf (buf, "%*s %s %s", name, val);
varSet (name, val);
}
}
}
void
setup (void)
{
Serial.begin (9600);
Serial.println("");
Serial.println("-------");
Serial.println("Variable Dump/Set Example");
Serial.println("-------");
}