Problem with 3 buttons that control a different number of LED's

Hello everyone, I’m new to Arduino and I would appreciate it if there’s someone out there that could help me with this problem.

For my project I needed 3 buttons that control a different number of LED’s. So, 3 LED’s will light up when I push the first button. then, when the second button is being pushed while the first button is also being pushed at the same time, 5 LED’s will light up and finally when I push the third button along with the first button, 7 LED’s will light up.
So, just to make things easy to understand, the first button needs to be pushed every time.

I guess that it’s important to mention that I’m working with an addressable LED Strip WS2812.
And that I wired all my buttons without any resistors, so just the signal and the ground.

I really do hope that my problem has come to it’s end. And I will appreciate every answer.

Here’s my code:

const int pushButton1 = 4;
const int pushButton2 = 5;
const int pushButton3 = 6;
int count = 0;
int firstTime = 1;
#include <FastLED.h>
#define NUM_LEDS 7
#define DATA_PIN 3
CRGB leds[NUM_LEDS];

void setup() { 
    FastLED.addLeds<WS2812, DATA_PIN, RGB>(leds, NUM_LEDS);  
    
     pinMode(pushButton1, INPUT_PULLUP);
     pinMode(pushButton2, INPUT_PULLUP);
     pinMode(pushButton3, INPUT_PULLUP);
  
   delay(50);
}

 void loop(){
  while (!digitalRead(pushButton1)== HIGH) {
    if (firstTime) {
      if (count <3) {
         count++;
    }
   }
    firstTime = 0;
  }  
   if (!firstTime) {
    if (count == 1) {
      leds[0] = CRGB::Green;
      FastLED.show(); 
      leds[3] = CRGB::Black;
    } else if (count == 2) {
      leds[2] = CRGB::Green;
      FastLED.show(); 
      leds[1] = CRGB::Black;
      FastLED.show();
    } else if (count == 3) {
      leds[3] = CRGB::Green;
      FastLED.show(); 
      leds[2] = CRGB::Black;
      FastLED.show();
    } 
  firstTime = 1;
 }
 
  while (!digitalRead(pushButton1)== HIGH && digitalRead(pushButton2)== HIGH) {
    if (firstTime) {
      if (count  <5) {
         count++;
      }
    }
    firstTime = 0;
  }  
   if (!firstTime) {
    if (count == 1) {
      leds[0] = CRGB::Green;
      FastLED.show(); 
      leds[4] = CRGB::Black;
      FastLED.show(); 
    } else if (count == 2) {
      leds[1] = CRGB::Green;
      FastLED.show(); 
      leds[0] = CRGB::Black;
      FastLED.show();
    } else if (count == 3) {
      leds[2] = CRGB::Green;
      FastLED.show(); 
      leds[1] = CRGB::Black;
      FastLED.show();
    } else if (count == 4) {
      leds[3] = CRGB::Green;
      FastLED.show(); 
      leds[2] = CRGB::Black;
      FastLED.show();
    } else if (count == 5) {
      leds[4] = CRGB::Green;
      FastLED.show(); 
      leds[3] = CRGB::Black;
      FastLED.show();
    }
     
    firstTime = 1;
  }
while (!digitalRead(pushButton1)== HIGH && digitalRead(pushButton3) == HIGH) {
    if (firstTime) {
      if (count <7) {
         count++;
     }
   }
    firstTime = 0;
  }  
   if (!firstTime) {
    if (count == 1) {
      leds[0] = CRGB::Green;
      FastLED.show(); 
      leds[6] = CRGB::Black;
      FastLED.show(); 
    } else if (count == 2) {
      leds[1] = CRGB::Green;
      FastLED.show(); 
      leds[0] = CRGB::Black;
      FastLED.show();
    } else if (count == 3) {
      leds[2] = CRGB::Green;
      FastLED.show(); 
      leds[1] = CRGB::Black;
      FastLED.show();
    } else if (count == 4) {
      leds[3] = CRGB::Green;
      FastLED.show(); 
      leds[2] = CRGB::Black;
      FastLED.show();
    } else if (count == 5) {
      leds[4] = CRGB::Green;
      FastLED.show(); 
      leds[3] = CRGB::Black;
      FastLED.show();
    } else if (count == 6) {
      leds[5] = CRGB::Green;
      FastLED.show(); 
      leds[4] = CRGB::Black;
      FastLED.show();
     } else if (count == 7) {
      leds[6] = CRGB::Green;
      FastLED.show(); 
      leds[5] = CRGB::Black;
      FastLED.show();
  }
    firstTime = 1;
 }
}

You only talked about what you need. What does the program that you posted actually do? Does it work differently than you expect, and if so, how does the behaviour differ from what you need?

Hello,

If I understood what you wrote:

  • Button 1 pushed : light up leds 0 to 2 (3 leds)
  • Buttons 1 and 2 pushed: light up leds 0 to 4 (5 leds)
  • Buttons 1 and 3 pushed: light up leds 0 to 6 (7 leds)
  • Any other combination: no lights /* not sure about this assumption */

Small question about the design: why do you want the button 1 to be always pushed?

I think the logic in your setup function is quite OK:

  • Initialize FastLED
  • Initialize the pins of your buttons

The loop function has many problems in it:

  • Include statements are usually at the beginning of your code
  • Your approach with while loops is not the best one: you should go through the loop() function and not stay in it long.
  • I don’t understand exactly what you want to achieve with the blocks “if(firsttime)…”: I guess you only want one led to be lit up at a time? /* For the explanation, I will not consider that */
  • Since the button 1 must be pushed for all your cases, you are blocked in the first while loop: the only way to exit is to release button 1 but then, you never enter in your while loops
  • With FastLED, you build the result and finally apply then with the show() function. You could make only one call at the end of the loop.

The approach I would suggest for the loop() function is:

  • Read all button states
  • Reset the leds array to 0
  • Combine all buttons states together in order to convert the if statements into a switch statement: each button could be a bit with 0 for OFF and 1 for ON → When ON, button 1 has value 1n button 2 value 2 and Button 3 value 4
  • 7 combinations are possible (all off to all on): I just have to group the cases together in order to fill the leds array correctly
  • I call the show() function

The following code illustrates that. Please note, that since I did not understand what you wanted to do exactly (firsttime), the result might not 100% meet your expectations.

#include <FastLED.h>

#define PIN_BUTTON_1 4
#define PIN_BUTTON_2 5
#define PIN_BUTTON_3 6

#define NUM_LEDS 7
#define DATA_PIN 3

CRGB leds[NUM_LEDS];
int currentLed = 0;

void setup()
{
  FastLED.addLeds<WS2812, DATA_PIN, RGB>(leds, NUM_LEDS);

  pinMode(PIN_BUTTON_1, INPUT_PULLUP);
  pinMode(PIN_BUTTON_2, INPUT_PULLUP);
  pinMode(PIN_BUTTON_3, INPUT_PULLUP);

  // Reset the leds array
  eraseArray();
}

void loop()
{
  // Button 1 -> 1 when ON
  // Button 2 -> 2 when ON
  // Button 3 -> 4 when ON
  int state = (digitalRead(PIN_BUTTON_1) == LOW ? 0 : 1) +
              (digitalRead(PIN_BUTTON_2) == LOW ? 0 : 2) +
              (digitalRead(PIN_BUTTON_3) == LOW ? 0 : 4) ;

  // If you want to leave leds as they are when no correct button combination is done, comment this line
  eraseArray();

  switch (state)
  {
    case 1: // Only button 1 pushed
      // Light up the current led, starting from 0
      leds[currentLed] = CRGB::Green;

      // increment the currentLed in the range 0..2
      if (++currentLed == 3)
        currentLed = 0;

      break;
    case 3: // Buttons 1 and 2 are pushed
      // Light up the current led, starting from 3
      leds[3 + currentLed] = CRGB::Green;

      // increment the currentLed in the range 0..1
      if (++currentLed == 2)
        currentLed = 0;

      break;
    case 5: // Buttons 1 and 3 are pushed
      // Light up the current led, starting from 3
      leds[5 + currentLed] = CRGB::Green;

      // increment the currentLed in the range 0..1
      if (++currentLed == 2)
        currentLed = 0;

      break;
    case 0:
      currentLed = 0; // reset the current led to be lit when all button are released
    default: // all other cases
      // Do nothing special
      break;
  }

  FastLED.show();
}

void eraseArray()
{
  for (int i = 0; i < NUM_LEDS; i++)
    leds[i] = CRGB::Black;
}

Hope this helps
Serge