- 45.1k
- 4
- 42
- 81
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.
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.
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.