How do i improve this Code? (or how to pass a Char String into a Function to behave like a Variable)
Sorry i am a beginner and amateur when it comes to coding, can somebody help me to make the code inside the loop() less "monkey-like" by using a proper function?
I have tried a lot and at some point i am running out of ideas about how to even phrase the question on google.
My main problem when writing a function for this case is that i don't know how to pass a variable into a function which has to be written out as part of a Variable but also as part of Char Strings if that makes sense.
If you look at the code inside the loop() i actually only had to pass the number to the function, like "3" to change some Variables and Char Strings accordingly. I would be able to solve the issue with those Char Strings but i am completely clueless how to handle the Variable (rmd3, rmd4...).
"3" as in: Variable: rmd3, Char String "rmd3 = 1", Variable Value: rotary_mode = 3 and Char String: "rotary_mode = 3"
This is a simplified version of my code but boils down to where i am stuck at. It refers to a rotary selector i am using which has 6 Positions (rmd1 - rmd6). However if i knew how to solve this issue i could use it in many other situations as well.
Bounce rmd3 = Bounce(45,10); //rotary selector on pos.3
Bounce rmd4 = Bounce(44,10); //rotary selector on pos.4
int rotary_mode = 0; //Rotary Mode
void setup() {
Serial.begin(11520);
pinMode(45, INPUT_PULLUP); //pin of pos.3
pinMode(44, INPUT_PULLUP); //pin of pos.4
}
void loop() {
rmd3.update();
if (rmd3.fallingEdge()) {
Serial.print("rmd3 = 1");
rotary_mode = 3;
Serial.print("rotary_mode = 3");
}
if (rmd3.risingEdge()) {
Serial.print("rmd3 = 0");
rotary_mode = 0;
Serial.print("rotary_mode = 0");
}
rmd4.update();
if (rmd4.fallingEdge()) {
Serial.print("rmd4 = 1");
rotary_mode = 4;
Serial.print("rotary_mode = 4");
}
if (rmd4.risingEdge()) {
Serial.print("rmd4 = 0");
rotary_mode = 0;
Serial.print("rotary_mode = 0");
}
} ́ ́ ́
Pseudocode:
́ ́ ́void loop() {
int rmd_int; //Mode numbers as int from 1 to 6
char rmd_char = [2]; //Mode numbers as char from "1" to "6"
rmd3.update();
rmd_int = 3;
rmd_char = "3";
void selected_mode(rmd_int, rmd_char);
}
void selected_mode(int rmd_int, char rmd_char ){
if (rmd[rmd_int].fallingEdge()) {
Serial.print("rmd[rmd_char] = 1");
rotary_mode = [rmd_int];
Serial.print("rotary_mode = [rmd_char]");
}
if (rmd[rmd_int].risingEdge()) {
Serial.print("rmd[rmd_char] = 0");
rotary_mode = 0;
Serial.print("rotary_mode = 0");
}
}```
1 Answer 1
The question is somewhat confused, but I think I got what you mean. Your code suffers from too much repetition. You only showed the handling of two selectors, but you want to handle 6 of them. Repeating all the logic 6 times would make the code unwieldy and hard to maintain. So you want to put the logic in a function and just call that function six times.
I actually only had to pass the number to the function, like "3" to change some Variables and Char Strings accordingly
You do not need to pass the number as a string: you can use
Serial.print()
to format the number instead. And you do not need to
write a function either: you can just put a for
loop inside the
loop()
function:
const int rmd_count = 6;
Bounce rmd[rmd_count] = {
Bounce(48, 10), // rotary selector on pos. 0
Bounce(47, 10), // rotary selector on pos. 1
Bounce(46, 10), // rotary selector on pos. 2
Bounce(45, 10), // rotary selector on pos. 3
Bounce(44, 10) // rotary selector on pos. 4
Bounce(43, 10) // rotary selector on pos. 5
};
void loop() {
for (int i = 0; i < rmd_count; i++) {
rmd[i].update();
if (rmd[i].fallingEdge()) {
Serial.print("rmd[");
Serial.print(i);
Serial.println("] = 1");
rotary_mode = i;
Serial.print("rotary_mode = ");
Serial.println(i);
}
if (rmd[i].risingEdge()) {
Serial.print("rmd[");
Serial.print(i);
Serial.println("] = 0");
rotary_mode = 0;
Serial.println("rotary_mode = 0");
}
}
}
The key to using for
loops is to structure your data in arrays,
instead of collections of variables named with numbers. Thus, instead of
rmd3
you would use rmd[3]
. Note that array indices start at zero.
Obviously, you could put the body of the for
loop inside a function,
but at this point that would not help much in simplifying the code.
Edit: As a clarification, and per Delta_G's suggestion, I'll try to explain the difference between an array and a collection of variables. Each variable you define is mapped by the compiler (technically, the linker) to a memory area. You can think of the variable names as convenient names assigned to those memory locations. If you write:
Bounce rmd0(48, 10), rmd1(47, 10), rmd2(46, 10), ...;
You get:
┌───────┐ ┌───────┐ ┌───────┐
rmd0: | | rmd1: | | rmd2: | | ...
└───────┘ └───────┘ └───────┘
In the picture above, the boxes are the memory areas. They are large
enough to hold a Bounce
object, i.e. their size is sizeof(Bounce)
.
Each one has a name. You have no control over where, within the memory,
those variables are allocated: it's the linker's call.
In contrast, when you declare an array, you get a single variable which is mapped to a contiguous memory area large enough to hold the whole array:
Bounce rmd[6] = { ... };
Gives:
┌───────┬───────┬───────┬───────┬───────┬───────┐
rmd: | | | | | | |
└───────┴───────┴───────┴───────┴───────┴───────┘
The individual cells do not have a name, and you instead use indices to
access them. For instance, rmd[0]
references the first cell. Please,
note that in this example there is no variable named rmd0
: if you try
to use that identifier the compiler will complain it is not defined.
Again, an array is not a "collection of variables": it is a single
variable.
The array cells do behave in some sense much like individual variables
(they are called lvalues), as you can use rmd[0]
in the same way you
would have used rmd0
in the previous code. The point of using an array
is that the indices do not need to be literals: you can use a variable
instead (rmd[i]
, where i
is a variable), which comes handy when you
want to loop over all the cells.
Edgar pointed out that I can write the variable
rmd3
byint i = 3
andrmd[i]
.
I hope it is now clear that this is not the case. There is no variable
named rmd3
unless you create it explicitly. Declaring an array named
rmd
does not create such a variable.
[Can I] "form" a variable by "characters"?
Your question is not very clear, but my guess is you are talking about computed variable names. This is a programming technique where you access a variable by computing its name at run time. For example, you combine the strings "rmd" and "3" in order to build the name of the variable "rmd3". Then you use this computed name to access the variable that has this name.
Computed variable names are quite often supported by interpreted languages. For example, in PHP this is called variable variables:
$foobar = 42; // the variable we want to access
$start = "foo"; // one piece of the name
$end = "bar"; // the other piece
$name = $start . $end; // build the name from its pieces
print $name . "\n"; // prints the variable name: "foobar"
print $$name . "\n"; // prints the variable's value: "42"
Computed variable names are not supported by C++, which is the language you use to program an Arduino. And for a good reason: when the compiler translates your program to machine code, the names of the variables are lost, they do not make their way to the actual Arduino. And this is a good thing, as you would not want those names to consume memory on the microcontroller.
Note that the names are present in the .elf file, as they could be
useful for debugging. If you were programming for a PC, you program
could in principle look into the file and find those names. On Linux you
would do that with the dlopen()
and dlsym()
functions, from the libdl library. The libdl technique is, however, very
far from the capabilities of your typical Arduino, orders of magnitude
more complex than a simple array, and perfectly useless for your use
case.
-
Brilliant, thanks! I did not know i can form the Variable rmd3 by rmd[i] and int i=3. Now i am wondering if this only works with numbers or if it would work as well by something like char i[] = "3".Baka– Baka2020年09月30日 21:27:11 +00:00Commented Sep 30, 2020 at 21:27
-
I think this answer would be greatly improved by making sure it is apparent that you are using an array and not the list of variables that the OP had. From the question in this comment it would seem that the OP is still confused about how that will work.Delta_G– Delta_G2020年09月30日 23:12:22 +00:00Commented Sep 30, 2020 at 23:12
-
1You're not "forming a variable" with rmd[i] and a 3. He's gotten rid of your variables entirely and created an array. With an array you can use an index to choose which member of the array you want to talk about, in this case member 3 which is the fourth member since counting always starts at 0. Note the line that starts "Bounce rmd[rmd_count]" where the array is created. Note that at no point to we create anything called rmd3. We instead create an array simply called rmd (without any numbers) which contains several of those Bounce objects.Delta_G– Delta_G2020年09月30日 23:14:21 +00:00Commented Sep 30, 2020 at 23:14
-
Yeah i got that, he is using an array but english is not my native tongue so i didn't knew how else to call it. So if variables are just adresses would it work with pointers somehow? All i care is the result... i got over 1800 lines of code for the same crap repeating over and over again but just with different variables. The only point of the code i posted at first as to make it "easy" otherwise i had to past 1800 lines of code.Baka– Baka2020年09月30日 23:18:38 +00:00Commented Sep 30, 2020 at 23:18
Explore related questions
See similar questions with these tags.
loop()
andsetup()
functions. And the description unfortunately is a mess. I understand, that it is difficult to explain, when you may have misconceptions or not understanding enough to find the correct words. Maybe you can show us directly with your code, what you are trying to do.