1

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 ();
 }
}
Edgar Bonet
45.1k4 gold badges42 silver badges81 bronze badges
asked Oct 23, 2020 at 9:10
1
  • simplest reduction .... do not repeat code unnecessarily .... you have if a>0 do x ... else if a>1 do x,y ... else if a>2 do x,y,z ......... instead do if a>0 do x ... if a>1 do y ... if a>2 do z Commented Oct 23, 2020 at 17:58

1 Answer 1

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.

answered Oct 23, 2020 at 9:30
1
  • Brilliant! It worked fine at the first try. Thank you so much for your programming lessons. Best regards from Spain. Commented Oct 23, 2020 at 19:03

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.