Randomly light leds with a button

Hi guys, I'm new in the programing field and I'm trying to light 1 random led out of 3 by pushing a button. So that when the button's pressed on led turn on randomly, when I release the button it turns off, and the next time another leds turns on randomly.

Here's my code so far. I know there is just 2 Leds for now…

#define LED_PIN 8
#define LED_PIN1 9
#define BUTTON_PIN 7

void setup() {
  pinMode(LED_PIN, OUTPUT);
  pinMode(LED_PIN1, OUTPUT);
  pinMode(BUTTON_PIN, INPUT);
}

void loop() {
  if (digitalRead(BUTTON_PIN) == HIGH) {
    digitalWrite(LED_PIN, HIGH);
  }
  else {
    digitalWrite(LED_PIN, LOW);
  }

    if (digitalRead(BUTTON_PIN) == HIGH) {
    digitalWrite(LED_PIN1, HIGH);
  }
  else {
    digitalWrite(LED_PIN1, LOW);
  }
}

Can anyone help me, thanks guys

ps: sorry for my English, I'm French

Look at the random() function

Welcome to the forum

Start with the basics.
For instance, what is keeping the button pin LOW when the button is not pressed ?

Consider using INPUT_PULLUP in the button pin pinMode() to keep it normally HIGH, and wiring the button to take the pin LOW when it is pressed. Detect the LOW as a button press

When you detect a button has become pressed (not is pressed) choose a random number between 0 and 2 using the random() function. Depending on the number turn on the associated LED, otherwise turn them all off.

There are smart ways to turn on the associated LED but if/else will do the job. Later you can use an array to hold the LED pin numbers and eliminate the is/else tests and reduce code

To see how to detect when a button becomes pressed see the StateChangeDetection example in the IDE

This may appear to work to turn on and off the one LED it handles:

  if (digitalRead(BUTTON_PIN) == HIGH) {
    digitalWrite(LED_PIN, HIGH);
  }
  else {
    digitalWrite(LED_PIN, LOW);
  }

and it may not matter that in fact the LED will probably go on and off many times before staying on as you hold the button, and go off and on many times before staying off when you get off the button.

If the button is controlling some random LED, again it may not matter but many choices will be made, and many LEDs will get a brief stab of being on then off.

When you are turning on and off with your three LEDs, you'll also have to keep track of which one you ended up turning in so you can turn off the one that was on.

@UKHeliBob identifies "state change detection" or "edge detection" as a means to cleanly just turn on and off one LED and rightly suggests worrying about the other part (multiple LEDs) be handled as part two.

But you can cheat on part one… and although it is kinda lame, simply slowing down the loop so that button bouncing is too fast for the code to see is a handy trick that can be employed when circumstances allow, viz:

void loop() {
  if (digitalRead(BUTTON_PIN) == HIGH) {
    digitalWrite(LED_PIN, HIGH);
  }
  else {
    digitalWrite(LED_PIN, LOW);

  delay(20);  // poor man's debounce delay
}

When you add edge detection, leave the poor man's debouncing in there. Or move on up the curve and look into true debouncing.

With a random choice you would not notice the bouncing, but if you were picking the next LED in sequence, bouncing would make it frustrating as the sequence woukd skitter N steps ahead through the cycle and make the choice kinda… random.

a7

Hi UkHeliBob, thanks for your answer.
Do I absolutely have to use INPUT_PULLUP as I already wired an external resistor between one leg of the button to VCC and so the default state for the button is HIGH, and when I press it, its states goes to LOW ?

It is OK to use an external pullup resistor rather than INPUT_PULLUP.

How are your LEDs wired ? Do they turn on when the LED pin goes HIGH or when it goes LOW ?

Please post a schematic of your project showing how all of the components are connected and powered. A 'photo of a hand drawn circuit is good enough

I ended up using INPUT_PULLUP

But presumably not with that circuit

Bonjour @emilierdt
Is this for a class project, work or personal enrichment?

Hello emilierdt

Welcome to the best Arduino forum ever :slight_smile:

Consider this code example for your studies.

enum ButtonState {Pressed, Released};
constexpr uint8_t LedPin[] {9, 10, 11};
constexpr uint8_t ButtonPin {A0};
void setup()
{
  for (auto Led : LedPin) pinMode(Led, OUTPUT);
  pinMode(ButtonPin, INPUT_PULLUP); //  Wire the switches between the pin and ground only
}
void loop()
{
  static uint8_t stateOld = Released;
  uint8_t stateNew = digitalRead(ButtonPin);
  if (stateOld != stateNew)
  {
    if (digitalRead(ButtonPin) == stateNew)
    {
      delay(50);
      stateOld = stateNew;
      switch (stateNew)
      {
        case Released:
          for (auto Led : LedPin) digitalWrite(Led, LOW);
          break;
        case Pressed:
          digitalWrite(LedPin[random(0, sizeof(LedPin))], HIGH);
          break;
      }
    }
  }
}

You don't need to read the button a second time:

enum ButtonState {Pressed, Released};
constexpr uint8_t LedPin[] {9, 10, 11};
constexpr uint8_t ButtonPin {2};
void setup()
{
  for (auto Led : LedPin) pinMode(Led, OUTPUT);
  pinMode(ButtonPin, INPUT_PULLUP); //  Wire the switches between the pin and ground only
}
void loop()
{
  static uint8_t stateOld = Released;

  uint8_t stateNew = digitalRead(ButtonPin);

  if (stateOld != stateNew)
  {
    delay(50);
    stateOld = stateNew;
    switch (stateNew)
    {
      case Released:
        for (auto Led : LedPin) digitalWrite(Led, LOW);
        break;
      case Pressed:
        digitalWrite(LedPin[random(0, sizeof(LedPin))], HIGH);
        break;
    }
  }
}

a7

1 Like

Are you trying to confuse @emilierdt ?

There are a number of techniques used in your sketch that need to be understood but he/she is probably not ready for them. Things need to be kept simple at the moment

The sort of things that I have in mind are enum, arrays, auto, static and switch/case

Whilst all of these have their place I don't think that they belong here, at least not yet

Thank you very much for your tip, which I will gladly take into consideration. That's what happens when you programme a dirty debounce in an unusual way :slight_smile:

Is your middle name Stefan?

That's for the TO play around and learn new things by making errors.
I don't know his level of knowledge.

Exactly

Okay so after many hours deep into forums I managed to make it work.
I'm sure the code is messy and not really professional…but it works for now. I'm gonna try to make it prettier.
It's composed of multiple parts of code put together, anyway the final code is below :

#define LED_PIN 8
#define LED_PIN1 9
#define LED_PIN2 10
#define BUTTON_PIN 7

int lastButtonState = HIGH; 
int currentLED = -1; 

void setup() {
  pinMode(LED_PIN, OUTPUT);
  pinMode(LED_PIN1, OUTPUT);
  pinMode(LED_PIN2, OUTPUT);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  randomSeed(analogRead(0)); // Initialisation du générateur aléatoire
}

void loop() {
  int buttonState = digitalRead(BUTTON_PIN);

  
  if (buttonState == LOW && lastButtonState == HIGH) {
    delay(50); // Petit délai pour éviter les rebonds
    while (digitalRead(BUTTON_PIN) == LOW); 

    // Éteindre toutes les LEDs
    digitalWrite(LED_PIN, LOW);
    digitalWrite(LED_PIN1, LOW);
    digitalWrite(LED_PIN2, LOW);

    // Sélection d'une LED au hasard
    int newLED = random(3); // Valeurs possibles : 0, 1, 2

    // Allumer la LED choisie
    if (newLED == 0) {
      digitalWrite(LED_PIN, HIGH);
    } else if (newLED == 1) {
      digitalWrite(LED_PIN1, HIGH);
    } else {
      digitalWrite(LED_PIN2, HIGH);
    }
  }

  lastButtonState = buttonState; // Mise à jour de l'état du bouton
}

tell me what you think

In the end I also used 3 Leds with 3 1K ohm Resistor and a button

And yes I'm working on that for a personal and school project. It's for my diploma project in order to graduate from my master in graphic design !

I'm running late, but does that do what you asked for in your original post?

It looks like it just picks a random LED to be on, there will always be one on.

If so it's ironic as I was thinking the problem would be a better learning exercise if that's what you had asked for...

a7

I mostly wanted to turn on randomly a led with a button, the next step is indeed to make the led turns off when the button is released…but I havent figured that yet

You've found or recreated state change logic, but in a way that just isn't quite right.

And in doing have committed a cardinal sin, here

while (digitalRead(BUTTON_PIN) == LOW); 

which literally stops progress in its tracks until you get off the button. So nothing else can happen. It doesn't matter here, perhaps, but one day you may want to walk and chew gum at the same time, so to speak, and hanging up waiting like this kills your abilities to do.

The pattern you want looks like this pseudocode:

    set button got pressed false

    if the button is different to last time (different!)
 
       if the button is now down
            the button just got pressed!
            do stuff you wanna because the button became pressed
(else)
       if the button is now up
            the button just got released!
            do stuff you wanna because the button became un-pressed

       remember the button for next time
       delay a bit

I'm at the beach and just copied this from another post and tweaked it, so I reserve the right to have missed a detail or two. The essence of it is that you are detecting both edges, not just when it went from HIGH to LOW.

Adding printing to the stuff that gets done in each case (each edge) is illustrative. I am thinking you are clever enough to see how to hang your "random select and turn on" code on one edge, and your "turn 'em all off" code on the other.

And nowhere do you need a while loop burning cycles needlessly waiting for the finger to get off the button.

HTH and when I can I'll make sure I got it right. :expressionless:

a7

This is your last sketch fixed like I said

# define LED_PIN 8
# define LED_PIN1 9
# define LED_PIN2 10
# define BUTTON_PIN 7

int lastButtonState = HIGH; 
int currentLED = -1; 

void setup() {
  Serial.begin(115200);
  Serial.println("\ndétection de changement d'état sans blocage\n");

  pinMode(LED_PIN, OUTPUT);
  pinMode(LED_PIN1, OUTPUT);
  pinMode(LED_PIN2, OUTPUT);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
//   randomSeed(analogRead(0)); // Initialisation du générateur aléatoire
}

void loop() {
  int buttonState = digitalRead(BUTTON_PIN);

  if (buttonState!= lastButtonState) {
    delay(50); // Petit délai pour éviter les rebonds

//...    while (digitalRead(BUTTON_PIN) == LOW); 
//...
    if (buttonState == LOW) {
       Serial.println("one edge");
  
    // Éteindre toutes les LEDs
      digitalWrite(LED_PIN, LOW);
      digitalWrite(LED_PIN1, LOW);
      digitalWrite(LED_PIN2, LOW); 
 
    // Sélection d'une LED au hasard
      int newLED = random(3); // Valeurs possibles : 0, 1, 2

      // Allumer la LED choisie
      if (newLED == 0) {
        digitalWrite(LED_PIN, HIGH);
      } else if (newLED == 1) {
        digitalWrite(LED_PIN1, HIGH);
      } else {
        digitalWrite(LED_PIN2, HIGH);
      }
    }
    else {  // buttonState == HIGH
      Serial.println("              the other edge");
    }
  }

  lastButtonState = buttonState; // Mise à jour de l'état du bouton
}

HTH

a7