I've been working on a level meter with a neopixel strip (WS2812).
The code is very simple: reading a potentiometer, mapping the input and showing the output in the led strip.
So far, so good. The code I include below is working fine but, obviously, ugly and repetitive. Since my knowledge of programming is very weak, I wonder if there is any loop way to cut the code short. Please note that the seven led have different colours. Actually this is the confusing point for me to build a loop. Any idea, folks?
Yes, I also know that using so many delays isn't the mos elegant solution, but it does not compromise the device performance and the bar led appearing is quite nice.
void leveller () {
int millivolts;
int level;
millivolts = analogRead(A3);
level = map(millivolts, 0, 1024, 0, 7);
if (level <=0){
strip.clear();
strip.setPixelColor(0, 128, 0, 0);
strip.show ();
}
else if ((level > 0)&&(level<1)) {
strip.clear();
strip.setPixelColor(0, 128, 0, 0);
delay(30);
strip.show ();
strip.setPixelColor(1, 128, 32, 0);
delay(30);
strip.show ();
}
else if ((level>= 1)&&(level<2)) {
strip.clear();
strip.setPixelColor(0, 128, 0, 0);
delay(30);
strip.show ();
strip.setPixelColor(1, 128, 32, 0);
delay(30);
strip.show ();
strip.setPixelColor(2, 128, 64, 0);
delay(30);
strip.show ();
}
else if ((level>= 2)&&(level<3)) {
strip.clear();
strip.setPixelColor(0, 128, 0, 0);
delay(30);
strip.show ();
strip.setPixelColor(1, 128, 32, 0);
delay(30);
strip.show ();
strip.setPixelColor(2, 128, 64, 0);
delay(30);
strip.show ();
strip.setPixelColor(3, 0, 128, 0);
delay(30);
strip.show ();
}
else if ((level>= 3)&&(level<4)) {
strip.clear();
strip.setPixelColor(0, 128, 0, 0);
delay(30);
strip.show ();
strip.setPixelColor(1, 128, 32, 0);
delay(30);
strip.show ();
strip.setPixelColor(2, 128, 64, 0);
delay(30);
strip.show ();
strip.setPixelColor(3, 0, 128, 0);
delay(30);
strip.show ();
strip.setPixelColor(4, 0, 128, 0);
delay(30);
strip.show ();
}
else if ((level>= 4)&&(level<5)) {
strip.clear();
strip.setPixelColor(0, 128, 0, 0);
delay(30);
strip.show ();
strip.setPixelColor(1, 128, 32, 0);
delay(30);
strip.show ();
strip.setPixelColor(2, 128, 64, 0);
delay(30);
strip.show ();
strip.setPixelColor(3, 0, 128, 0);
delay(30);
strip.show ();
strip.setPixelColor(4, 0, 128, 0);
delay(30);
strip.show ();
strip.setPixelColor(5, 0, 128, 0);
delay(30);
strip.show ();
}
else if ((level>= 5)&&(level<6)) {
strip.clear();
strip.setPixelColor(0, 128, 0, 0);
delay(30);
strip.show ();
strip.setPixelColor(1, 128, 32, 0);
delay(30);
strip.show ();
strip.setPixelColor(2, 128, 64, 0);
delay(30);
strip.show ();
strip.setPixelColor(3, 0, 128, 0);
delay(30);
strip.show ();
strip.setPixelColor(4, 0, 128, 0);
delay(30);
strip.show ();
strip.setPixelColor(5, 0, 128, 0);
delay(30);
strip.show ();
strip.setPixelColor(6, 0, 128, 32);
delay(30);
strip.show ();
}
else if (level>= 6) {
strip.clear();
strip.setPixelColor(0, 128, 0, 0);
delay(30);
strip.show ();
strip.setPixelColor(1, 128, 32, 0);
delay(30);
strip.show ();
strip.setPixelColor(2, 128, 64, 0);
delay(30);
strip.show ();
strip.setPixelColor(3, 0, 128, 0);
delay(30);
strip.show ();
strip.setPixelColor(4, 0, 128, 0);
delay(30);
strip.show ();
strip.setPixelColor(5, 0, 128, 0);
delay(30);
strip.show ();
strip.setPixelColor(6, 0, 128, 32);
delay(30);
strip.show ();
strip.setPixelColor(7, 0, 128, 64);
delay(30);
strip.show ();
}
}
1 Answer 1
First, a small remark:
if ((level > 0)&&(level<1))
level
is an integer, and there is no integer that is both strictly
larger than zero and smaller than one.
if ((level>= 1)&&(level<2))
There is only one integer that verifies this condition. It would be clearer then to just write
if (level == 1)
Now, for your actual question: one trick that often works to shorten repetitive code is to turn code into data, store the data in arrays and run through them with loops. Here the sequence of colors can be stored in an array:
const uint8_t colors[8][3] = {
{128, 0, 0},
{128, 32, 0},
{128, 64, 0},
{ 0, 128, 0},
{ 0, 128, 0},
{ 0, 128, 0},
{ 0, 128, 32},
{ 0, 128, 64},
};
You can then call setPixelColor()
within an loop that runs through the
array. As the end point of the loop depends on the measured level, it
could be written like this:
void leveller() {
int level = map(analogRead(A3), 0, 1024, 1, 9);
strip.clear();
for (int i = 0; i < level; i++) {
const uint8_t *color = colors[i];
strip.setPixelColor(i, color[0], color[1], color[2]);
strip.show();
delay(30);
}
}
Note that, since the output of analogRead()
is always smaller than
1024, the variable level
will always be smaller than 9, i.e. it will
take values between 1 and 8 inclusive. And that is the number of colors
that will be shown.
-
Brilliant! It worked fine at the first try. Thank you so much for your programming lessons. Best regards from Spain.Vidal– Vidal2020年10月23日 19:03:42 +00:00Commented Oct 23, 2020 at 19:03
if a>0 do x
...else if a>1 do x,y
...else if a>2 do x,y,z
......... instead doif a>0 do x
...if a>1 do y
...if a>2 do z