Reputation: 1381
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
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:
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
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
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