Nimjox
Nimjox

Reputation: 1381

Making a better loop in Arduino

I've written code in Arduino that cycles through 3 LED color lights but it seems (code) bug prone so I'm trying to come up with a new way to write it. Due to the complexity I'm going to stick with the phesdo code of what I'm trying to do. Here it is:

If (red LED isn't max and green LED is 0 and blue LED is 0)
  {inc red LED; update dot matrix}
If (red LED is max and green LED isn't max and blue LED is 0)
  {inc green LED; update dot matrix}
If ((red LED is/has-been max but not 0 ) and green LED is max and blue LED is 0)
  {dec red; update dot matrix}
If (red LED is 0 and green LED is max and blue LED isn't max)
  {inc blue; update dot matrix}
If (red LED is 0 and (green LED is/has-been max but not 0) and blue LED is max)
  {dec green; update dot matrix}
If (red LED isn't Max and green LED is 0 and blue is Max )
  {inc red; update dot matrix}
If (red LED is Max and green LED is 0 and (blue LED is/has-been Max but not 0))
  {dec blue; update dot matrix}

Update LED Driver;

Note: For a visual it's a color wheel going red->orange->green->teal->blue->pink->repeat

The caveat is, all this is in a loop that is only run once before exiting to fetch other data. It then has to return to this loop and remember the color location it left off. Other wise it would be very easy to wrap all this in for loops and execute it linearly. As it is it has to inc or dec one color, understand it's color position if you will, update the led driver and then come back to inc or dec remembering where it left off. So does anyone have a better code methodologically, pseudo style, I can use besides this complex if statements style.

Upvotes: 1

Views: 709

Answers (3)

Jack
Jack

Reputation: 133609

With a simple drawing of the situation you are able to find a formula that applies the intensity directly to the single component according to a global counter that you increment on every tick, the code is the following (I wrote it just now and haven't tested but should be enough for you to understand how it works):

int counter = 0; // counter you should increment on each tick
int phases = 6; // total phases in a cycles
int cycleLength = max_steps * phases; // total ticks in a cycle

int currentStepOfCycle = counter % cycleLength;
int currentPhase = currentStepOfCycle / max_steps;
int currentStepOfPhase = currentStepOfCycle % max_steps;

// this is how much phase shifts are performed for each primary color to have the raising line in phase 0
int phase_shifts[3] = {2, 0, 4}; 

// for each color component
for (int i = 0; i < 3; ++i) {
  // shift the phase so that you have / at phase 0
  int shiftedPhase = (currentPhase+phase_shifts[i])%phases;

  if (shiftedPhase == 1 || shiftedPhase == 2)
    intensity[i] = MAX;
  else if (shiftedPhase == 0)
    intensity[i] = currentStepOfPhase;
  else if (shiftedPhase == 3)
    intensity[i] = MAX - currentStepOfPhase;
  else
    intensity[i] = 0;
}

The idea follows from this:

enter image description here

The shift is needed because by adding an increment to the current phase for a different color component it is possible to consider always phase 0, 1, 2 and 3 to understand is intensity should be raising, dropping or set to max for each component.

This should be adaptable to whatever step of intensity you want to apply easily.

Upvotes: 2

Grady Player
Grady Player

Reputation: 14549

yeah that is not great... I would do something like..

typedef struct{ //maybe stick this in a union, depending on what the compiler does to it.
    unsigned char r:2;
    unsigned char g:2;
    unsigned char b:2;
}color;
const int numOfColors = 3;
color colors[numOfColors] = {
    {2,0,0},//r
    {1,1,0},//o
    {0,2,0}//g
};

for(int i = 0 ; 1 ; i++)
{
    color c = colors[i%numOfColors];
    //set color
    //update
    //wait
}

Upvotes: 2

Jerry Coffin
Jerry Coffin

Reputation: 490338

At least as I read your if statements, you have 7 distinct states (maybe it should be 8?), and when you reach the last, it wraps back around to the first.

That's pretty easy to implement as a counter with a small lookup table to map from a state number to which LED(s) should be lit for a state.

Upvotes: 2

Related Questions