Call a function with an int

I am working on a project that will needs to call different functions depending of the value within a for loop, in this case the value of i will trigger upto 21 different functions.

My current thinking is to use case...select. I ma aware i could be these funsction into the case...select statement bu each function is most likely going to be used in other parts of the code

I am wondering if there is another more effective wat of doing the same thing?

  for (i=0; i<21; i++){
    //call function depending on value of i
  }

Yes, the 'switch - case' statement. Just because you place the functions in it, does not mean they can't be used elsewhere in the program. Functions can be called from many places in a program. It would be almost completely useless if that were not the case.

If you want to get "really fancy" you can put pointers to functions in a table and execute them by their index. It's cool but usually not a recommended practice unless you have a solid reason for doing it that way.

Your demo code doesn't demonstrate much. It's still a little uncertain what you intend to do.

You know the sequence of i so there would be no difference than just calling all 21 functions in sequence.

I could it it like this

  for (i=0; i<20; i++){
    Switch (i){
      case 1:
        for(n=0; n<36; n++) {             //light up first set of LEDs
          pixels.setPixel(n,R,G,B);
        }
      break;
      //more cases here
    
    }
  }

This I would assume would stop me from calling the code with case 1 from else where in the code

However putting a function call and the code for case 1 in that function would allow that code to be called from else where

  for (i=0; i<20; i++){
    switch (i){
      case 1:
        led_one();     //call function for first group of LEDs
      break;
      //more cases here
    
    }
  }

Hopefully that brings some clarity.

Yes there are going to be 21 groups of LEDs to control. Its going to take some time to write out all 21 functions. But it will be better than the mess I have writen for intial testing.

You could make an array of function pointers and index it by 'i'.

Were is the best place to read about that?
Not used pointers with arduino before.

If you move the whole switch-cases into a separate function you can call any of the different functions from other places in your code. E.g. this way:

void switchTo(byte FunctionNo){
  switch (FunctionNo){
        case 1:
         led_one();     //call function for first group of LEDs
       break;
      //more cases here
    }
 }

If you then use nice named Enums instead of byte FunctionNo it would even improve the readability of the code.

Not sure about "the best". A Google search for 'function pointer tutorial' returned quite a few hits. Here are are couple:
https://www.cprogramming.com/tutorial/function-pointers.html
https://www.learncpp.com/cpp-tutorial/function-pointers/

My gawd man! You've invented the jump table!

The key to a reliable jump table is absolute array bound checking. Over or underrun the table and your code executes a "boonie branch" where it transfers control to some random memory location instead of your code.

Used to use this trick back in the old .ASM days.

Not if you actually make a function that contains that code.

OK, this a first complete run. I was testing as i went and now everything seem to be working as anticipated. It running on a teensy 3.2. There is still along way to go on this project but is by far the most LEDs i have used at one time.

#include <OctoWS2811.h>

const int ledsPerStrip = 216;
DMAMEM int displayMemory[ledsPerStrip*6];
int drawingMemory[ledsPerStrip*6];

const int config = WS2811_GRB | WS2811_800kHz;
OctoWS2811 pixels(ledsPerStrip, displayMemory, drawingMemory, config);

uint16_t R = 255;
uint16_t B = 0;
uint16_t G = 0;

byte Brightness = 35;

uint16_t i = 0;
uint16_t j = 0;


#define DELAYVAL 1 // Time (in milliseconds) to pause between pixels

void setup() {
  pixels.begin();
  pixels.show();
  Serial.begin(115200);
  delay(1000);
  Serial.println("Starting");
 }

void loop() {
  for (j = 0; j < 255; j++){
    for (i=1; i<22; i++){
      Wheel((i+j) & 255);
      switch (i){
        case 1:
          led_one();
          pixels.show();
        break;
        case 2:
          led_two();
          pixels.show();
        break;
        case 3:
          led_three();
          pixels.show();
        break;
        case 4:
          led_four();
          pixels.show();
        break;
        case 5:
          led_five();
          pixels.show();
        break;
        case 6:
          led_six();
          pixels.show();
        break;
        case 7:
          led_seven();
          pixels.show();
        break;
        case 8:
          led_eight();
          pixels.show();
        break;
        case 9:
          led_nine();
          pixels.show();
        break;
        case 10:
          led_ten();
          pixels.show();
        break;
        case 11:
          led_eleven();
          pixels.show();
        break;
        case 12:
          led_twelve();
          pixels.show();
        break;
        case 13:
          led_thirteen();
          pixels.show();
        break;
        case 14:
          led_fourteen();
          pixels.show();
        break;
        case 15:
          led_fifteen();
          pixels.show();
        break;
        case 16:
          led_sixteen();
          pixels.show();
        break;
        case 17:
          led_seventeen();
          pixels.show();
        break;
        case 18:
          led_eighteen();
          pixels.show();
        break;
        case 19:
          led_nineteen();
          pixels.show();
        break;
        case 20:
          led_twenty();
          pixels.show();
        break;
        case 21:
          led_twentyone();
          pixels.show();
        break;
      }
      delay (DELAYVAL);
    }
    /*
    if (R == 255){
      R = 0;
      B = 255;
    }else if (B == 255){
      B = 0;
      G = 255;
    }else{
      G = 0;
      R = 255;
    } 
    */  
  }
}

//there are 21 faux pixels
void led_one() {
  for(byte n=0; n<36; n++) {
    pixels.setPixel(n,R,G,B);
  }
}

void led_two() {
  pixels.setPixel(36,R,G,B);
  pixels.setPixel(99,R,G,B);
  pixels.setPixel(117,R,G,B);
  
  pixels.setPixel(152,R,G,B);
  pixels.setPixel(62,R,G,B);
  pixels.setPixel(80,R,G,B);
}

void led_three() {
  pixels.setPixel(37,R,G,B);
  pixels.setPixel(100,R,G,B);
  pixels.setPixel(118,R,G,B);
  
  pixels.setPixel(151,R,G,B);
  pixels.setPixel(61,R,G,B);
  pixels.setPixel(79,R,G,B);
}

void led_four() {
  pixels.setPixel(38,R,G,B);
  pixels.setPixel(101,R,G,B);
  pixels.setPixel(119,R,G,B);
  
  pixels.setPixel(150,R,G,B);
  pixels.setPixel(60,R,G,B);
  pixels.setPixel(78,R,G,B);
}

void led_five() {
  pixels.setPixel(39,R,G,B);
  pixels.setPixel(102,R,G,B);
  pixels.setPixel(120,R,G,B);
  
  pixels.setPixel(149,R,G,B);
  pixels.setPixel(59,R,G,B);
  pixels.setPixel(77,R,G,B);
}

void led_six() {
  pixels.setPixel(40,R,G,B);
  pixels.setPixel(103,R,G,B);
  pixels.setPixel(121,R,G,B);
  
  pixels.setPixel(148,R,G,B);
  pixels.setPixel(58,R,G,B);
  pixels.setPixel(76,R,G,B);
}

void led_seven() {
  pixels.setPixel(41,R,G,B);
  pixels.setPixel(104,R,G,B);
  pixels.setPixel(122,R,G,B);
  
  pixels.setPixel(147,R,G,B);
  pixels.setPixel(57,R,G,B);
  pixels.setPixel(75,R,G,B);
}

void led_eight() {
  pixels.setPixel(42,R,G,B);
  pixels.setPixel(105,R,G,B);
  pixels.setPixel(123,R,G,B);
  
  pixels.setPixel(146,R,G,B);
  pixels.setPixel(56,R,G,B);
  pixels.setPixel(74,R,G,B);
}

void led_nine() {
  pixels.setPixel(43,R,G,B);
  pixels.setPixel(106,R,G,B);
  pixels.setPixel(124,R,G,B);
  
  pixels.setPixel(144,R,G,B);
  pixels.setPixel(55,R,G,B);
  pixels.setPixel(73,R,G,B);
}

void led_ten() {
  pixels.setPixel(44,R,G,B);
  pixels.setPixel(107,R,G,B);
  pixels.setPixel(125,R,G,B);
  
  pixels.setPixel(143,R,G,B);
  pixels.setPixel(54,R,G,B);
  pixels.setPixel(72,R,G,B);
}

void led_eleven() {
  for(byte n=0; n<9; n++){
    pixels.setPixel(45+n,R,G,B);
    pixels.setPixel(63+n,R,G,B);
    pixels.setPixel(108+n,R,G,B);
    pixels.setPixel(135+n,R,G,B);
  }
}

void led_twelve() {
  pixels.setPixel(153,R,G,B);
  pixels.setPixel(126,R,G,B);
  pixels.setPixel(81,R,G,B);
  pixels.setPixel(207,R,G,B);

  pixels.setPixel(206,R,G,B);
  pixels.setPixel(98,R,G,B);
}

void led_thirteen() {
  pixels.setPixel(154,R,G,B);
  pixels.setPixel(127,R,G,B);
  pixels.setPixel(82,R,G,B);
  pixels.setPixel(208,R,G,B);

  pixels.setPixel(205,R,G,B);
  pixels.setPixel(97,R,G,B);
}

void led_fourteen() {
  pixels.setPixel(155,R,G,B);
  pixels.setPixel(128,R,G,B);
  pixels.setPixel(83,R,G,B);
  pixels.setPixel(209,R,G,B);

  pixels.setPixel(204,R,G,B);
  pixels.setPixel(96,R,G,B);
}

void led_fifteen() {
  pixels.setPixel(156,R,G,B);
  pixels.setPixel(129,R,G,B);
  pixels.setPixel(84,R,G,B);
  pixels.setPixel(210,R,G,B);

  pixels.setPixel(203,R,G,B);
  pixels.setPixel(95,R,G,B);
}

void led_sixteen() {
  pixels.setPixel(157,R,G,B);
  pixels.setPixel(130,R,G,B);
  pixels.setPixel(85,R,G,B);
  pixels.setPixel(211,R,G,B);

  pixels.setPixel(202,R,G,B);
  pixels.setPixel(94,R,G,B);
}

void led_seventeen() {
  pixels.setPixel(158,R,G,B);
  pixels.setPixel(131,R,G,B);
  pixels.setPixel(86,R,G,B);
  pixels.setPixel(212,R,G,B);

  pixels.setPixel(201,R,G,B);
  pixels.setPixel(93,R,G,B);
}

void led_eighteen() {
  pixels.setPixel(159,R,G,B);
  pixels.setPixel(132,R,G,B);
  pixels.setPixel(87,R,G,B);
  pixels.setPixel(213,R,G,B);

  pixels.setPixel(200,R,G,B);
  pixels.setPixel(92,R,G,B);
}

void led_nineteen() {
  pixels.setPixel(160,R,G,B);
  pixels.setPixel(133,R,G,B);
  pixels.setPixel(88,R,G,B);
  pixels.setPixel(214,R,G,B);

  pixels.setPixel(199,R,G,B);
  pixels.setPixel(91,R,G,B);
}

void led_twenty() {
  pixels.setPixel(161,R,G,B);
  pixels.setPixel(134,R,G,B);
  pixels.setPixel(89,R,G,B);
  pixels.setPixel(215,R,G,B);

  pixels.setPixel(198,R,G,B);
  pixels.setPixel(90,R,G,B);
}

void led_twentyone() {
  for(int n=0; n<9; n++){
    pixels.setPixel(162+n,R,G,B);
    pixels.setPixel(171+n,R,G,B);
    pixels.setPixel(180+n,R,G,B);
    pixels.setPixel(189+n,R,G,B);
  }
}


uint32_t Wheel(byte WheelPos) {
  Serial.print("WheelPos: ");
  Serial.print(WheelPos);
  WheelPos = 255 - WheelPos;
  Serial.print(" : ");
  Serial.println(WheelPos);
  if(WheelPos < 85) {
    R = 255 - WheelPos * 3;
    G = 0;
    B = WheelPos *3;
    set_bright();
    return;
    //return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    R = 0;
    G = WheelPos * 3;
    B = 255 - WheelPos * 3;
    set_bright();
    return;
    //return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  R = WheelPos *3;
  G = 255 - WheelPos * 3;
  B = 0;
  set_bright();
  return;
  //return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

void set_bright() {
      R = (R * Brightness) >> 8;
      G = (G * Brightness) >> 8;
      B = (B * Brightness) >> 8;
}

Look at all those functions and the numbers inside, from one function to the next there is a big pattern that repeats, often by 1 digit +/-

You can get that down a lot by turning that into one function andadjusting the variable values

You've got some different formatting in the later functions, and two are quite different, at a glance…

but it looks like there is a huge opportunity for seeing the pattern and making the code much shorter by exploiting the essential same-ness of about 20 functions…

I think you will like arrays when you get to them, but even simple maths might be enough to make this way shorter.

At the loss of the complete flexibility that your literal approach gives you.

Can you make a video and put it on YouTube? I am just now without the ability to make this run for myself to see what you have wrought.

a7

The different formating of the functions actually reflects to different orientation of the LED strips, and the 3 completely different ones reflect that they are larger (36 instead of 9)
Arrays are something that is slated to the future.
The number on each setPixel is the address of the LED on the strip, while each function is the physical represntation of each group as a single unit

This is the early stages of build a rhombic dodecahedron infinity mirror.

Right. Yes it really looks like you don't need the thing you asked for. In fact, it's a terrible idea under these circumstances. So just factor your code instead.

28 June 2022 - YouTube
During testing before the wheel code was inserted.
The wheel code actually moves very subtly between colours

1 Like

First off... I apologise sincerely for the lack of proper variable names here... I don't know how these things relate to your project, so PLEASE replace them all (including any 'magic numbers' i've used) with something that has real meaning.

Secondly, I don't claim this is the right or best way... I just wanted to show a basic approach to getting the same result as in those 21 functions, but in less code.

Here's the 'serial print' version so you can see that it gives a good output for the pixel numbers:

int first = 36;
int second = 152;
int third = 153;
int fourth = 206;

int offsetsFirst[6] = { 0, 63, 81, 0, -90, -72 };
int offsetsSecond[6] = { 0, -27, -72, 54, 0, -108 };

int offsetsThird[4] = { 0, 18, 63, 90 };
int offsetsFourth[4] = { 0, 9, 18, 27 };

void funcOne(int valOne, int valTwo, int* offsets, int switchAt) {
  for (int i = 0; i < 6; i++)
    Serial.println((String)"pixels.setPixel(" + ((i < switchAt ? valOne : valTwo) + offsets[i]) + ", R, G, B);");

  Serial.println();
}

void funcTwo(int startVal, int* offsets) {
  for (int n = 0; n < 9; n++) {
    for (int m = 0; m < 4; m++) {
      Serial.println((String) "pixels.setPixel(" + (startVal + n + offsets[m]) + ", R, G, B);");
    }
    Serial.println();
  }
}

void setup() {
  Serial.begin(115200);

  for (int i = 1; i < 22; i++) {
    Serial.println((String) "i is: " + i);
    if (i == 1) {
      for (byte n = 0; n < 36; n++) {
        Serial.println((String) "pixels.setPixel(n, R, G, B);");
      }
      Serial.println();
    }
    else if (i > 1 && i < 11) {
      funcOne(first++, second--, offsetsFirst, 3);
    }
    else if (i == 11) {
      funcTwo(45, offsetsThird);
    }
    else if (i > 11 && i < 21) {
      funcOne(third++, fourth--, offsetsSecond, 4);
    }

    else if (i == 21) {
      funcTwo(162, offsetsFourth);
    }
  }
}

void loop() { }

I 'think' I've shoehorned it back into your original code here but I can't test yours:

#include <OctoWS2811.h>

const int ledsPerStrip = 216;
DMAMEM int displayMemory[ledsPerStrip * 6];
int drawingMemory[ledsPerStrip * 6];

const int config = WS2811_GRB | WS2811_800kHz;
OctoWS2811 pixels(ledsPerStrip, displayMemory, drawingMemory, config);

uint16_t R = 255;
uint16_t B = 0;
uint16_t G = 0;

byte Brightness = 35;

uint16_t i = 0;
uint16_t j = 0;

int first = 36;
int second = 152;
int third = 153;
int fourth = 206;

int offsetsFirst[6] = { 0, 63, 81, 0, -90, -72 };
int offsetsSecond[6] = { 0, -27, -72, 54, 0, -108 };

int offsetsThird[4] = { 0, 18, 63, 90 };
int offsetsFourth[4] = { 0, 9, 18, 27 };

#define DELAYVAL 1 // Time (in milliseconds) to pause between pixels

void setup() {
  pixels.begin();
  pixels.show();
  Serial.begin(115200);
  delay(1000);
  Serial.println("Starting");
}

void loop() {
  for (j = 0; j < 255; j++) {
    for (int i = 1; i < 22; i++) {
      Wheel((i + j) & 255);
      if (i == 1) {
        for (byte n = 0; n < 36; n++)
          pixels.setPixel(n, R, G, B);
      }
      else if (i > 1 && i < 11) {
        funcOne(first++, second--, offsetsFirst, 3);
      }
      else if (i == 11) {
        funcTwo(45, offsetsThird);
      }
      else if (i > 11 && i < 21) {
        funcOne(third++, fourth--, offsetsSecond, 4);
      }

      else if (i == 21) {
        funcTwo(162, offsetsFourth);
      }
      delay (DELAYVAL);
    }
    /*
      if (R == 255){
      R = 0;
      B = 255;
      }else if (B == 255){
      B = 0;
      G = 255;
      }else{
      G = 0;
      R = 255;
      }
    */
  }
}

void funcOne(int valOne, int valTwo, int* offsets, int switchAt) {
  for (int i = 0; i < 6; i++)
    pixels.setPixel((i < switchAt ? valOne : valTwo) + offsets[i], R, G, B);
}

void funcTwo(int startVal, int* offsets) {
  for (int n = 0; n < 9; n++)
    for (int m = 0; m < 4; m++)
      pixels.setPixel(startVal + n + offsets[m], R, G, B);
}

uint32_t Wheel(byte WheelPos) {
  Serial.print("WheelPos: ");
  Serial.print(WheelPos);
  WheelPos = 255 - WheelPos;
  Serial.print(" : ");
  Serial.println(WheelPos);
  if (WheelPos < 85) {
    R = 255 - WheelPos * 3;
    G = 0;
    B = WheelPos * 3;
    set_bright();
    return;
    //return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if (WheelPos < 170) {
    WheelPos -= 85;
    R = 0;
    G = WheelPos * 3;
    B = 255 - WheelPos * 3;
    set_bright();
    return;
    //return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  R = WheelPos * 3;
  G = 255 - WheelPos * 3;
  B = 0;
  set_bright();
  return;
  //return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

void set_bright() {
  R = (R * Brightness) >> 8;
  G = (G * Brightness) >> 8;
  B = (B * Brightness) >> 8;
}

I've only changed the bits that match the top of my post.

I'll leave with a final plea to update my variable and function names to something meaningful :smiley:

Maybe it's useful, maybe others can see even better ways to cut what I've changed down more.

1 Like

That code looks great, I was lazing in bed think about doing something similar. It should work providing only linear patterns (at least on first study) are used ie: from top to bottom or bottom to top.
But lets say i want to go from thje middle and work outward, or switch between the top and bottom work inwards to the centre. Or maybe first group on the bottom, then first group at the top, then second group on the bottom, second group at the top... you get the idea.

Now don't get me wrong, I greatly apprieciate your code and it may well be incorperated either partially or in complete form in the final itteration the project, but it lacks a certian flexibilty that is needed to manipulate the sequence of the LED groups in whatever pattern comes to mind.
I think overall the idea of this part of the project was to find a way to be able to control each group of LEDs as if they were individual LEDs. My veiw was that getting a smooth transition on the wheel function was going to be one of the harder tasks to achieve so seemed like a good place to start.

I have started to refer to each of these groups of LEDs as "faux LEDs", which has made it a little easier to understand.
There are other improvements that need to be made. The OctoWS2811 library does not have a brightness control, which is why that function exists. If i were to call that function and add the pixels.show() command there instead of in the main code I would no longer have to have both a call that and a call to set_bright everytime a faux LED, or for that matter a single LED is updated.

There are alot of improvments to be made and a long way to go. I really appreciate the input of people who have more experience to than I do.

I really don't know why in the world you would need something like this but, you could use the preprocessor directive specially created for this:

#define FUNC_ID(id) function_##id()
...
for (i=0; i<21; i++){
    FUNC_ID(i);
  }

And, of course, you'll have to define all those functions, from 0 to 20.

More details: Replacing text macros - cppreference.com
Search for "##" and read.

After an admitidly quick read, my understanding is that it would replace every instance of FUNC_ID(i) with the matching function. So if i call the second group of LEDs 10 times I would end up with the code "copy and pasted" to every postion I called that function - 10 pieces of identicle code.
I will look into it a further and try and unserstand better, but it seems to me that it would take a lot of code space needlesly - maybe this is not an issue in the grand scheme of things. I have heard some people refer to this as lazy programming, personally I am not experienced enough to have an opinion.
The up side is that I would make manipulating each faux LED in whatever order eacy and make the code look very neat and tidy versus a string of switch...case iterations.