Improve a long list of if-statements

Hi all,

Let me begin by telling you I'm on a learning curve and that my question might seem stupid. In that case, I apologize in advance and please tell me so!

So, I've done my fair share of searching and trying out, but I'm stuck on something I can't get my head around. This is the case:

I control (in this example) a serie of 5 DMX controlled LED pars. Something like this. Each par takes 6 channels for which the first 3 are to control the R,G and B levels per par.
I control DMX via the Tinkerkit DMX shield. It's fairly easy.

DmxMaster.write(channel, value)

So to control one par I could do

for (i=0;i<3;i++) {
DmxMaster.write(i,255);
}

And I would have one light with all LED's full on. Please, understand, this was a breakthrough for me :wink:

I can do the same thing off course for multiple par's as long as I skip the extra channels. Those are used to alter the mode, strobe effect, and RGB simultaneous. So the second par would start on channel number 7.

My goal is to make a simple VU meter, with soundlevels measured via microphone. I have some thing working, but it's not pretty. I have 5 par's, but need 6 channels, because the 4th par needs to be yellow. The microphone value's are scaled to 0...255. I use a dirty fix I guess to make the par's go from green at the bottom to red on top. The channels are in reversed order here, the light with channel one is actually on top.

 if (inten < 20) { //lowest value
    DmxMaster.write(26,inten);
    DmxMaster.write(20,0);
    DmxMaster.write(14,0);
    DmxMaster.write(8,0);
    DmxMaster.write(7,0);
    DmxMaster.write(1,0);
  } 
  else if (inten < 40) {
    DmxMaster.write(26,inten);
    DmxMaster.write(20,inten);
    DmxMaster.write(14,inten/2);
    DmxMaster.write(8,0);
    DmxMaster.write(7,0);
    DmxMaster.write(1,0);
  } 
  else if (inten < 80) {
    DmxMaster.write(26,inten);
    DmxMaster.write(20,inten);
    DmxMaster.write(14,inten);
    DmxMaster.write(8,inten);
    DmxMaster.write(7,inten/2);
    DmxMaster.write(1,0);
  } 
  else if (inten < 120) {
    DmxMaster.write(26,inten);
    DmxMaster.write(20,inten);
    DmxMaster.write(14,inten);
    DmxMaster.write(8,inten);
    DmxMaster.write(7,inten);
    DmxMaster.write(1,inten/2);
  } 
  else if (inten < 160) { //highest value
    DmxMaster.write(26,inten);
    DmxMaster.write(20,inten);
    DmxMaster.write(14,inten);
    DmxMaster.write(8,inten);
    DmxMaster.write(7,inten);
    DmxMaster.write(1,inten);
  }

The problem with this method is the lack of possibilities to ease values, and it takes so much code. I bet I can do this better. The final result will use over 30 par's and multiple sensors, I need to write it as effecient as possible. What I can't seem to manage is the fact that it needs to change color above a certain value, but only in one light, not all.

I'm looking for some good advice on this matter, as it will help me a great deal in the rest of the project!

For this you can use Case statements and the ellipses (...)

switch(myValue)
{
case 0 ... 5: // if the value is between 0 - 5 it will do this case
 //something here
 break;
case 6 ... 10:// if the value is between 6 - 10 it will do this case
 // something else
 break;
.
.
.
case 95 ... 100:

default: // something not in value range
}

So,
inten < 20 will be from 0 to 19
inten < 40 will be from 20 to 39
and so on.

Yes, that's something I tried. It was supposed to be faster as well, since it would not follow all the if-statements once it found one of the cases to be true, I believe.
But even in this way, I would still need to write all the data for each light in each case. That's still 6 lines per case.
Maybe I'm just thinking too hard, but is my way of stating the lights the way to go?

When I look at one case I get this feeling it could be much more efficient besides the if-statements.

You might be able to use a FOR loop and either write a 0, inten or inten/2 depending on inten's value.
I'm not just sure how you would do that at the moment.

Can you determine the value to write based on the value you are comparing, in an equation?
ie.

DmxMaster.write(26,  inten );
DmxMaster.write(20,  (inten >=20 ) ? inten : 0 );
DmxMaster.write(14,  (inten >=40 ) ? ( (inten >= 80) ? inten : inten/2 ) : 0 );
    DmxMaster.write(26,inten);
    DmxMaster.write(20,inten);
    DmxMaster.write(14,inten);
    DmxMaster.write(8,inten);
    DmxMaster.write(7,inten/2);
    DmxMaster.write(1,0);

Why not make that into a function and call it with the 6 values to be written ? That way the code only exists once but you can call it as many times as necessary.

Create a struct that has intensity threshold and an array of intensity multipliers (1, 0.5 or 0) - one for each channel. Create an array of them and populate the data in order of increasing intensity thresholds.

Use a for loop to run through the array of structs to find the appropriate settings and then loop through the channels using the multiplier for each on the current intensity to calculate the setting to send the DMX.

Then the sending code is trivial - all the smarts is in the data.

LOL - wildbill just beat me to it. Leveraging data structures to carry the load off the code is a vanishing art.

The below will NOT compile - it's ideas on a theme.

//channels or whatever
byte chan[] = {26, 20, 14, 8, 7, 1};

//the main driver table - this holds the "logic"
float stuff [][7] =
{
 20.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0,
 40.0, 1.0, 1.0, 0.5, 0.0, 0.0, 0.0,
 80.0, 1.0, 1.0, 1.0, 1.0, 0.5, 0.0,
120.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.5,
160.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0
};

//"data-ize" all the ifs
byte i=0;
while (inten > stuff[i][0])
 i++;

//write the magic numbers
for (byte j=0; j<6; j++)
{
 DmxMaster.write(chan[j], (byte)(inten * stuff[i][j+1]);
}

Ah yes guys, do I love these places on the internet or what?!

There are so many ways to think about these kind of things.
Most of your suggestions I can follow, just have to give it a try. But Wildbill and yaafm got me lost. It does look like a decent solution but it will take me some time to figure it out.

yaafm:
Leveraging data structures to carry the load off the code is a vanishing art.

Isn't this a necessity? Especially with micro controllers where resources are limited?

As you're writing 26 with inten in every case, put this line once before your if statement to save 4 lines of code.

DmxMaster.write(26,inten);