1

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
    I really don't understand, what you are saying there. You are talking about providing a char string as function parameter, but I don't see such a function in your code. You don't show any function other than the standard loop() and setup() 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. – chrisl Sep 30 at 19:08
  • Do you want to pass a character array, as an argument, to a function? – Gerben Sep 30 at 19:23
  • It can sometimes help to write "pseudocode" to describe how you want your program to work. There's no syntax rules, and nothing you cannot do - just write your code as if everything you wanted to do could be done in any way you want to do it. Then we may be able to work out from that what it is you intend your code to do. – Majenko Sep 30 at 19:23
  • Whenever you start putting numbers on variable names and then want to use them, what you really want is an array. With an array you can use those numbers to refer to different things. What you want to do with a char array won’t work. Aria me names only exist in the code as you write it. They all become memory addresses once the code is compiled. There is no concept of a variable name at runtime. – Delta_G Sep 30 at 20:14
  • I added a Pseudocode so you could mabye get a picture what i mean. Left it out at first because i know its wrong and may cause confusion. – Baka Sep 30 at 21:12
4

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 by int i = 3 and rmd[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.

| improve this answer | |
  • 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 Sep 30 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 Sep 30 at 23:12
  • 1
    You'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 Sep 30 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 Sep 30 at 23:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.