Control de un led con 4 pulsadores

Buen día.
Estoy intentando controlar un led con 4 pulsadores; 3 de los pulsadores están destinados a controlar la forma en la que el led parpadea y el restante apaga el led:

Quiero hacer que al presionar un pulsador el led parpadee por siempre (sin mantener presionado el pulsador), hasta que otro pulsador sea presionado, y cuando este otro pulsador sea presionado el led debe parpadear de diferente forma (también por siempre hasta que otro pulsador sea presionado). Caundo el botón de apagado sea presionado entonces el led se debe apagar.
He intentado agregar While, pero al presionar un pulsador el led parpadea de la forma que se le haya indicado a ese botón y ya no cambia la forma de parpadear aunque yo presione otro pulsador. Apreciaría mucho su ayuda.

Uso Arduino UNO, es para un proyecto escolar.
Aquí mi código, con esta programación el led parpadea pero si mantengo el pulsador presionado, y necesito, como ya mencioné, que los pulsadores solo se presionen una vez para mantener el led parpadeando de acuerdo a la configuración de cada pulsador.

int BOTON1=2;
int BOTON2=3;
int BOTON3=4;
int BOTON4=5;
int LED=13;
int EB1=0;
int EB2=0;
int EB3=0;
int EB4=0;

void setup() {
  // put your setup code here, to run once:
pinMode(BOTON1, INPUT);
pinMode(BOTON2, INPUT);
pinMode(BOTON3, INPUT);
pinMode(BOTON4, INPUT);
pinMode(LED, OUTPUT);
}

void loop (){
  EB1 = digitalRead(BOTON1);
  EB2 = digitalRead(BOTON2);
  EB3 = digitalRead(BOTON3);  
  EB4 = digitalRead(BOTON4);
  
 //!!!!!Botón 1!!!!!// 
  if (EB1==HIGH)                    //Al presionar el pulsador 1 el led debe parpadear de cierta forma
    {                               //por siempre hasta que otro pulsador sea presionado.
    digitalWrite(LED, HIGH);
    delay(1500);
    digitalWrite(LED, LOW);
    delay(1500);   
    }

  //!!!!!Botón 2!!!!!//
  if (EB2==HIGH)                    //Al presionar el pulsador 2 el led debe parpadear de otra forma 
   {                                //por siempre hasta que otro pulsador sea presionado.
    digitalWrite( LED, HIGH);
    delay(700);
    digitalWrite(LED, LOW);
    delay(700);
   }

    //!!!!!Botón 3!!!!!//
  if (EB3==HIGH)                    //Al presionar el pulsador 3 el led debe parpadear de manera diferente
   {                                //por siempre hasta que otro pulsador sea presionado.
    digitalWrite(LED, HIGH);
    delay(300);
    digitalWrite(LED, LOW);
    delay(300);
    }    

    //!!!!!Botón 4!!!!!//           //Al presionar el pulsador 4 el led debe apagarse totalmente
  if (EB4==HIGH)                    //y se debe encender cuando cualquiera de los otros 3 pulsadores
    {                               //sea presionado.
    digitalWrite(LED, LOW);
    }
}

Te cuento como lo haría a ver si lo puedes adaptar.
Pondría una variable que guarde el botón que pulses, suponte "boton_pulsado", por ej., que valga 1 para el botón 1, 2 para el 2 y asi para los otros

Luego con un switch/case o con 4 if() consultas el valor de boton_pulsado y haces el efecto que corresponda.
Así boton_pulsado cambia solo cuando pulsas algún boton, sino se conserva indefinidamente.

Saludos

PD: Pista: en tu código, en cada if() en lugar de hacer el efecto, asignas el valor a boton_pulsado. Luego haces lo demás.

Intenté hacer algo parecido a eso pero los parpadeos de cada botón se combinaban, se ejecutaban al mismo tiempo, pero intentaré hacer eso de nuevo. Muchas gracias amigo.

Entonces si se combinan, lo que debes hacer es que cuando se detecta la presión de un pulsador se inhiban los demás.
Cada botón debe funcionar solo, por eso una pulsación bloquea las demás.
Y el último pulsador bloquea a todos además de su función de detener toda secuencia y apagar el LED.

Si lo haces bien nunca puedes ejecutar mas de un efecto a la vez. Ojo, boton_pulsado es una sola variable, no son 4.

Primero lees los botones.
Luego te fijas cual se pulsó y lo guardas en la variable asignandole un número (1 si fue el 1ro., 2 si fue el 2do., etc.)
Por último, en base a esa variable, determinas el efecto a realizar.

Imposible hacer más de un efecto al mismo tiempo porque la variable puede tomar 4 valores diferentes (tres para hacer los diferentes parpadeos y el 4to para apagar el LED), nunca va a tener más de un valor al mismo tiempo y el valor va a cambiar solo si pulsas un botón sino no cambia.

Más pistas no te puedo dar, sino ya te tendría que pasar el código pero se supone que lo tienes que hacer tú.

Si lees con atención lo que te dije antes y lo que te digo ahora, lo resuelves si o si. :wink:

Ya voy entendiendo, al parecer estoy haciendo 4 variables de botón_pulsado, probablemente ese haya sido mi error, gracias.

Me lo imaginé por eso te lo aclaré. :slight_smile:

Te lo "digo" sencillamente:

  • Miras cada boton si está pulsado (eso lo tienes)
  • Si se pulsó el 1ro. boton_pulsado =1, si se pulsó el 2do. boton_pulsado = 2, etc.
  • Si boton_pulsado == 1 hago un efecto, si boton_pulsado == 2 hago otro, ... , si es 4 apago el led.

¿Se entiende? :smiley:

Muchas gracias

De nada.
Después sube el código y lo revisamos. ¿Te parece?

Claro amigo, tan pronto lo tenga lo subo

Aún no me funciona, creo que hice algo mal además de el error que anteriormente me habían mencionado

int BOTON1=2;
int BOTON2=3;
int BOTON3=4;
int BOTON4=5;
int LED=13;
int BOTON_PULSADO = 0;
int EB1=0;
int EB2=0;
int EB3=0;
int EB4=0;

void setup() {
  // put your setup code here, to run once:
pinMode(BOTON1, INPUT);
pinMode(BOTON2, INPUT);
pinMode(BOTON3, INPUT);
pinMode(BOTON4, INPUT);
pinMode(LED, OUTPUT);
}

void loop (){
  EB1 = digitalRead(BOTON1);
  EB2 = digitalRead(BOTON2);
  EB3 = digitalRead(BOTON3);  
  EB4 = digitalRead(BOTON4);
  BOTON_PULSADO = EB1;
  BOTON_PULSADO = EB2;
  BOTON_PULSADO = EB3;
  BOTON_PULSADO = EB4;
  
 //!!!!!Botón 1!!!!!// 
  if (EB1==HIGH)                    //Al presionar el pulsador 1 el led debe parpadear de cierta forma
    {                               //por siempre hasta que otro pulsador sea presionado.
    digitalWrite(LED, HIGH);
    delay(1500);
    digitalWrite(LED, LOW);
    delay(1500);   
    }

  //!!!!!Botón 2!!!!!//
  if (EB2==HIGH)                    //Al presionar el pulsador 2 el led debe parpadear de otra forma 
   {                                //por siempre hasta que otro pulsador sea presionado.
    digitalWrite( LED, HIGH);
    delay(700);
    digitalWrite(LED, LOW);
    delay(700);
   }

    //!!!!!Botón 3!!!!!//
  if (EB3==HIGH)                    //Al presionar el pulsador 3 el led debe parpadear de manera diferente
   {                                //por siempre hasta que otro pulsador sea presionado.
    digitalWrite(LED, HIGH);
    delay(300);
    digitalWrite(LED, LOW);
    delay(300);
    }    

    //!!!!!Botón 4!!!!!//           //Al presionar el pulsador 4 el led debe apagarse totalmente
  if (EB4==HIGH)                    //y se debe encender cuando cualquiera de los otros 3 pulsadores
    {                               //sea presionado.
    digitalWrite(LED, LOW);
    }
}

Y no va a funcionar porque sigues haciendo lo mismo...

BOTON_PULSADO = EB1;

y etc, está mal.
Tienes que hacer

if(EB1 == HIGH) boton_pulsado = 1;

Y lo mismo para los otros 3. Obviamente EB2 asignará 2 y EB3, 3 y EB4, 4.
Luego

if(boton_pulsado == 1) {
// el efecto que quieres que haga el boton 1
}

Lo mismo para 2; 3 y 4.

Son 4 lecturas de botones.
4 if() para darle valor a boton_pulsado según cada botón.
4 if() para hacer cada efecto según el valor de boton_pulsado.
Nada más

Al margen: No está mal pero, por convención, las variables se nombran en minúsculas y las constantes en mayúsculas.

Bueno, yo estaba pensando como el piensa. Una variable por botón.
La idea de @gatul es mas simple y eficiente.

Si usas una variable como sugiere @gatul entonces cada boton produce una acción. Es claramente el mejor camino.

Mi sugerencia era que cada botón accionaba sobre una variable diferente (EB1 a EB4).

Ahora esto

BOTON_PULSADO = EB1;
  BOTON_PULSADO = EB2;
  BOTON_PULSADO = EB3;
  BOTON_PULSADO = EB4;

tu mismo debes comprender que es accionar lo mismo.

Para hacer lo que @gatul sugirió debes armar boton pulsado con algo diferente.

boton_pulsado = digitalRead(BOTON1);
boton_pulsado = digitalRead(BOTON2)*2;
boton_pulsado = digitalRead(BOTON3)*3; 
boton_pulsado = digitalRead(BOTON4)*4;

Una forma simple es esta
cada boton será 1 a 4 si se presiona

y con eso vas a un switch() case donde cada case o caso determina la secuencia que se ejecuta.

switch(boton_pulsado) {
    case 1: // secuencia 1
                 break;   // todos los casos terminan con break
    case 2: // secuencia 2
                 break;   // todos los casos terminan con break
    case 3: // secuencia 3
                 break;   // todos los casos terminan con break
    case 4: // detengo todo
                 break;   // todos los casos terminan con break

}

El código está presentado, solo es cuestión de copiar y pegar 4 veces cada línea y modificar un número en cada una y agregar las lineas que manejan los LED.

Lo pensé en base a lo que presentó el PO porque desconozco si, por ej., sabe usar switch/case.
Claramente no podría presentar un programa con instrucciones que todavía no ha aprendido.

La solución

boton_pulsado = digitalRead(BOTONn)*n;

no sirve en este caso porque siempre reflejaría el estado del 4to botón, además se perdería el valor de la "pasada" anterior que es necesario para que se repita la secuencia seleccionada si no se pulsa ningún boton nuevamente.

gatul:
La solución

boton_pulsado = digitalRead(BOTONn)*n;

no sirve en este caso porque siempre reflejaría el estado del 4to botón, además se perdería el valor de la "pasada" anterior que es necesario para que se repita la secuencia seleccionada si no se pulsa ningún boton nuevamente.

No entiendo porque decís esto, si el autor del hilo dice

Caundo el botón de apagado sea presionado entonces el led se debe apagar.

Donde dice que debe quedar la secuencia ejecutándose por siempre?

En serio? :o

Quiero hacer que al presionar un pulsador el led parpadee por siempre (sin mantener presionado el pulsador), hasta que otro pulsador sea presionado, y cuando este otro pulsador sea presionado el led debe parpadear de diferente forma (también por siempre hasta que otro pulsador sea presionado). Cuando el botón de apagado sea presionado entonces el led se debe apagar.

Ok, no lo vi.

Podemos quitar entonces la última opción de *4, que solo apague el led y no modifique las otras secuencias para que queden por siempre.

En realidad ambos sabemos que se pueden hacer 10mil cosas distintas.

Creo que no ves el error...

boton_pulsado = digitalRead(BOTON1);
boton_pulsado = digitalRead(BOTON2)*2;
boton_pulsado = digitalRead(BOTON3)*3;
boton_pulsado = digitalRead(BOTON4)*4;

¿Qué valor toma boton_pulsado cuando pulso el BOTON1, sabiendo que el estado pulsado es HIGH?
Si querés ignorá la lectura de BOTON4 (igual no modifica la respuesta).

Rta: La variable boton_pulsado termina conteniendo el valor 0 (cero) cuando debería contener 1(uno).
Y si pulso el BOTON2 también devolvería 0 cuando debería ser 2.

Saludos

Te entiendo @gatul pero deja que piense un poco el autor de la consulta!!

Que saque boton_pulsado de ahi y que haga otra cosa.

Ya dije que haga una accion directa con digitalRead(BOTON4);

Esta claro que mi comentario apunta a quitar el *4 pero si lo haces y te das cuenta que no funciona entonces trabajá un poquito la idea.

Desde #11 que ya ni tiene que pensar, solo copiar pegar.

Igual la intención no fue generar un debate, de hecho no lo hice, sino ayudar al PO a resolver su problema.

Saludos