Push Button de tres estados y dos pulsadores (Solucionado)

Hola el siguiente codigo es para tres estado con dos pulsadores, el primer estado prende el rojo con un push button y
los otros dos estados es con otro push button el problema es que copie el codigo tal cual desde un tutorial de you tube
y no me funciona, si alguien me ayudara lo agradeceria.

Saludos.

Este es el link del tutorial:

Este es el codigo:

 //Pines
 const int PIN_LED_VERDE=2;
 const int PIN_LED_AMARILLO=3;
 const int PIN_LED_ROJO=12;
 const int PIN_PULSADOR_CAMBIO=5;
 const int PIN_PULSADOR_ONOF=11;

 // Estados
 const int ESTADO_OFF=0;
 const int ESTADO_VERDE=1;
 const int ESTADO_AMARILLO=3;

 //Variables
int estado=ESTADO_OFF;
int pulsadorCambioAntes=LOW;
int pulsadorCambioAhora=LOW;
int pulsadorOnOffAntes=LOW;
int pulsadorOnOffAhora=LOW;

//Inicializamos
void setup(){
pinMode(PIN_LED_VERDE,OUTPUT);
pinMode(PIN_LED_AMARILLO,OUTPUT);
pinMode(PIN_LED_ROJO,OUTPUT);
pinMode(PIN_PULSADOR_CAMBIO,INPUT);
pinMode(PIN_PULSADOR_ONOF,INPUT);
 
}



void loop(){
  obtenerDatos();
  controlarCircuito();
}





//Funcionalidad


void obtenerDatos(){
  pulsadorCambioAntes=pulsadorCambioAhora;
  pulsadorCambioAhora=digitalRead(PIN_PULSADOR_CAMBIO);
  pulsadorOnOffAntes=pulsadorOnOffAhora;
  pulsadorOnOffAhora=digitalRead(PIN_PULSADOR_ONOF);
  delay(50);
}


void controlarCircuito()
{
  switch (estado){

    case ESTADO_OFF:
    controlarEstadoOff;
    break;

    case ESTADO_VERDE:
    controlarEstadoVerde;
    break;

    case ESTADO_AMARILLO:
    controlarEstadoAmarillo;
    break;
    }
}



void controlarEstadoOff(){

  if( (pulsadorOnOffAntes==HIGH) && (pulsadorOnOffAhora==LOW)){
  encenderVerde();
}
}

void controlarEstadoVerde(){

    if( (pulsadorOnOffAntes==HIGH) && (pulsadorOnOffAhora==LOW) ){
          apagar();
    }
    else if ((pulsadorCambioAntes==HIGH) && (pulsadorCambioAhora==LOW)){
          encenderAmarillo();
          }
}
void controlarEstadoAmarillo(){

if( (pulsadorOnOffAntes==HIGH) && (pulsadorOnOffAhora==LOW) )
{
  apagar();
}
else if ((pulsadorCambioAntes==HIGH) && (pulsadorCambioAhora==LOW))
{
  encenderVerde();
}

}


void encenderVerde(){
  digitalWrite(PIN_LED_VERDE,HIGH);
  digitalWrite(PIN_LED_AMARILLO,LOW);
  digitalWrite(PIN_LED_ROJO,LOW);
  estado=ESTADO_VERDE;
}

void encenderAmarillo(){
  digitalWrite(PIN_LED_VERDE,LOW);
  digitalWrite(PIN_LED_AMARILLO,HIGH);
  digitalWrite(PIN_LED_ROJO,LOW);
  estado=ESTADO_AMARILLO;
}

void apagar(){
  digitalWrite(PIN_LED_VERDE,LOW);
  digitalWrite(PIN_LED_AMARILLO,LOW);
  digitalWrite(PIN_LED_ROJO,HIGH);
  estado=ESTADO_OFF;
}

Que es lo que no funciona?

surbyte:
Que es lo que no funciona?

Saquemos la bola de cristal :stuck_out_tongue:

Bromas apartes. Hola odalis2786.

Por partes y sin que tomes esto de forma ofensiva, sólo razónalo:

  • Si no te funciona y no nos dice que error te da (si te da alguno) ¿Cómo vamos a saberlo? ¿Tenemos que revisarlo todo por ti?
  • Tampoco sabemos como tienes la conexión
  • Código copiado de un vídeo ¿Quieres que nos lo veamos?
  • Ya que la fuente es un vídeo ¿Has revisado tenerlo todo?

Ningún problema en ayudarte, pero yo me mareé con ese ejemplo y tantas líneas. Si pongo algo que funciona, a mi manera entonces, no pienso mirar todo ese ejemplo para 3 leds, miré el esquema hecho Autodesk y mucho fue.
Si también haces copy and paste de mi código, al menos intenta entenderlo, si no, nunca podrás desarrollar nada por ti mismo y llegará el día en el que "no te hagan la tarea".

const byte rojo = 12;
const byte amarillo = 3;   
const byte verde = 2;

byte btn1[] = {11,1,0}; 
byte btn2[] = {5,0,0};

long tiempo = 0, debounce = 50;  

void setup(){
  pinMode(rojo, OUTPUT);
  pinMode(amarillo, OUTPUT);
  pinMode(verde, OUTPUT);
  pinMode(btn1[0], INPUT);
  pinMode(btn2[0], INPUT);
}

void loop(){
  *btn1 = check_pulsador(btn1);
  *btn2 = check_pulsador(btn2);
  
  if(btn1[1]){
    btn2[1] = false;
  }
  digitalWrite(rojo, btn1[1]);

  digitalWrite(amarillo, (! btn1[1] && !btn2[1] ) ? true : false);
  digitalWrite(verde, (! btn1[1] && btn2[1] ) ? true : false);
}

byte check_pulsador(byte *btn){
  byte esta_pulsado = digitalRead(btn[0]);

  if (esta_pulsado && !btn[2] && millis() - tiempo > debounce) { 
    btn[1] = !btn[1];
    tiempo = millis();  
  }
  btn[2] = esta_pulsado;
  return *btn;	
}

Habría quitado las variables de los leds (de maniático), pero creo que así te será mejor.
Si te sirve genial, si tienes duda, pregunta.

Gracias por ayudar Surbyte && Arduinito.

Primero: El señor Surbyte el circuito esta montado tal cual como muestra "Arduinito", cuando digo que el codigo no hace nada, me refiero a que se compila bien pero no prende ni un solo led.

Segundo Arduinito: me referire a los 4 puntos anteriores iniciados por usted.

1-Tienes razon, no espesifique el error, ya lo hice mas arriba.

2-La conexion es la misma que subiste, tambien tienes razon devi subirla

3-El video en la introduccion el autor explica bien lo que hace el codigo,eso es por si no me doy a entender

4-Tengo dos dias copiando en la mascota y compilando y revisando el codigo y no me funciona.

Si el codigo esta super largo pero quiero que me funcione para luego razonarlo.

Hice un copy paste de tu codigo pero no funciona como quiero el solo hace interaccion con dos led y no es estable, osea, aveces lo hace y aveces no.

Tambien tu codigo esta muy avanzado para mi tengo poco en el mundo de arduino.

Y por ultimo lo primero: y es que no me ofendo con lo que me dices siempre me gustan las criticas, asi puedo ver como los demas me ven ami, entonces luego me puedo expresar bien o por lo menos intentarlo.

Coordiales saludos nuevamente. Espero me ayuden

odalis2786:
3-El video en la introduccion el autor explica bien lo que hace el codigo,eso es por si no me doy a entender

No he visto el vídeo más allá del primer minuto pero el código me parece un (...) por lo largo y tedioso para guardar el estado de un botón y tener en cuenta el debounce.

odalis2786:
Hice un copy paste de tu codigo pero no funciona como quiero el solo hace interaccion con dos led y no es estable, osea, aveces lo hace y aveces no.

Nos vamos acercando, creo que lo que buscas es que el pulsador funcione como un botón interruptor.
Después te busco el enlace y lo pongo al final del post.

odalis2786:
Tambien tu codigo esta muy avanzado para mi tengo poco en el mundo de arduino.

Yo llevo sobre un mes o así con Arduino, lo único que quizás te deje :sleeping: :sleeping: :sleeping: son los punteros, pero yo mismo ni m acordaba como eran en C, san google al rescate y listo. De paso podrías echarle un ojo y aprender algo nuevo.

odalis2786:
Hice un copy paste de tu codigo pero no funciona como quiero el solo hace interaccion con dos led y no es estable, osea, aveces lo hace y aveces no.

Mi código funciona en https://circuits.io/ :confused: , has un copy and paste en tu https://circuits.io/. No le pidas mucho a la web, llevan todo el día con el servidor fatal, recuerda comprobar que se ilumine la luz verde en el componente del pulsador (cuando realmente coge el evento click), porque está yendo tan lento que los eventos los coge cuando quiere. Ahora ni siquiera carga los perfiles. Enserio, está probado, hace lo mismo que la parte inicial del vídeo.

odalis2786:
Y por ultimo lo primero: y es que no me ofendo con lo que me dices siempre me gustan las criticas, asi puedo ver como los demas me ven ami, entonces luego me puedo expresar bien o por lo menos intentarlo.

Me alegro, sólo queríamos saber más detalles de tu duda, y tranquilo nadie nació aprendido además el concepto propio de arduino es la enseñanza y el libre conocimiento.


Ahora al tema:

Si tu duda está en cómo usar el pulsador a modo de interruptor, mira este ejemplo:
https://www.arduino.cc/en/Tutorial/Switch

Además el ejemplo es con millis() no con los delays que pararían tu arduino si tuvieses que ejecutar otra cosa aparte de los leds.

Copia y pega, si eso tampoco te funciona... mal asunto porque está perfecto.
Si no es esa tu duda, ya nos comentas, pero encender leds no tiene mucho más.

Un saludo.

Gracias por responder.

Tienes razon la paguina virtual para simular los circuitos, asi que lo arme fisico y tu codigo esta perfecto solo cambie el debounce de 50 a 500 y todo esta perfecto. Ahora me toca estudiar todos los terminos nuevos que estan en el, muchas gracias por la ayuda.

Saludos

Me alegro que te sirviese.

Por si te ayuda a comprenderlo, en mi ejemplo hago lo mismo que el enlace que te pasé del "Tutorial/Switch".
La diferencia es que creé un array para cada botón.

Índice 0 (primera posición): el pin al que están conectado.
Índice 1 (segunda posición): el estado actual del led.
Índice 2 (tercera posición): el estado anterior.

Los estados los puse como byte, para añadir también los índices, pero es lo mismo:
encendido/apagado (1=true=HIGH) (0=false=LOW).

check_pulsador() pasa por parámetro el array de cada botón y hacemos lo mismo que puedes ver en el ejemplo del switch citado anteriormente, pero en este caso además retorno el array para asignar los cambios.

Y aquí entramos con el tema de los punteros, lo que ves con el asterisco * .
Para no repetir ese código por caaaada botón que tengamos, usamos el puntero.

De forma simple:
Pasamos el array a la función por parámetro, modificarlo, retonarlo, asignarlo.

Y la parte de los encendido y apagados que son simples te lo comento en el code por si el uso de () ? : en vez de if else te complican la visualización.

  //Si el led rojo está activo, ponemos el estado del segundo botón inactivo
  //de esta forma nos aseguramos que empiece por el led amarillo.
  //si se quitase, al desactivar rojo empezaría por el último led en el que se quedó.
  if(btn1[1]){
    btn2[1] = false;
  }

  //El led rojo está activo o no dependiendo del estado del pulsador 1.
  digitalWrite(rojo, btn1[1]);

  //El led amarillo se enciende si el pulsador 1 está inactivo y el segundo como inactivo.
  digitalWrite(amarillo, (! btn1[1] && !btn2[1] ) ? true : false);

  //El led verde se enciende si el pulsador 1 no está activo yel segundo sí.
  digitalWrite(verde, (! btn1[1] && btn2[1] ) ? true : false);

Resuelto con tu propio código, acá el enlace en Autodesk Circuits

El codigo

 //Pines
 const byte PIN_LED_VERDE       = 2;
 const byte PIN_LED_AMARILLO    = 3;
 const byte PIN_LED_ROJO        = 12;
 const byte PIN_PULSADOR_CAMBIO = 5;
 const byte PIN_PULSADOR_ONOF   = 11;

 // Estados
 const byte ESTADO_OFF      = 0;
 const byte ESTADO_VERDE    = 1;
 const byte ESTADO_AMARILLO = 3;

 //Variables
byte estado                 = ESTADO_OFF;
bool pCambioAnt             = LOW;
bool pCambio                = LOW;
bool pOnOffAnt              = LOW;
bool pOnOff                 = LOW;

//Inicializamos
void setup(){
  Serial.begin(9600);
  Serial.println("Iniciando programa.");
  pinMode(PIN_LED_VERDE,OUTPUT);
  pinMode(PIN_LED_AMARILLO,OUTPUT);
  pinMode(PIN_LED_ROJO,OUTPUT);
  pinMode(PIN_PULSADOR_CAMBIO,INPUT);
  pinMode(PIN_PULSADOR_ONOF,INPUT);
  digitalWrite(PIN_LED_VERDE,HIGH);
  digitalWrite(PIN_LED_AMARILLO,HIGH);
  digitalWrite(PIN_LED_ROJO,HIGH);
  delay(100);
  digitalWrite(PIN_LED_VERDE,LOW);
  digitalWrite(PIN_LED_AMARILLO,LOW);
  digitalWrite(PIN_LED_ROJO,LOW);
}



void loop(){
  obtenerDatos();
  controlarCircuito();
}





//Funcionalidad


void obtenerDatos(){
  pCambioAnt = pCambio;
  pCambio = digitalRead(PIN_PULSADOR_CAMBIO);
  pOnOffAnt  = pOnOff;
  pOnOff  = digitalRead(PIN_PULSADOR_ONOF);
  //delay(50);
}


void controlarCircuito()
{
  switch (estado){

    case ESTADO_OFF:      controlarEstadoOff();
                          break;

    case ESTADO_VERDE:    controlarEstadoVerde();
                          break;

    case ESTADO_AMARILLO: controlarEstadoAmarillo();
                          break;
  }
}



void controlarEstadoOff(){

  if (pOnOff && !pOnOffAnt ) 
      encenderVerde();

}

void controlarEstadoVerde(){

    if (pOnOff && !pOnOffAnt){
        apagar();
    }
    else 
    if (pCambio && !pCambioAnt){
        encenderAmarillo();
    }
}

void controlarEstadoAmarillo(){

  if (pOnOff && !pOnOffAnt)
      apagar();
  else 
  if (pCambio && !pCambioAnt)
      encenderVerde();
}


void encenderVerde(){
  digitalWrite(PIN_LED_VERDE,HIGH);
  digitalWrite(PIN_LED_AMARILLO,LOW);
  digitalWrite(PIN_LED_ROJO,LOW);
  estado = ESTADO_VERDE;
  Serial.println("Encender verde.");
}

void encenderAmarillo(){
  digitalWrite(PIN_LED_VERDE,LOW);
  digitalWrite(PIN_LED_AMARILLO,HIGH);
  digitalWrite(PIN_LED_ROJO,LOW);
  estado = ESTADO_AMARILLO;
  Serial.println("Encender amarillo.");
}

void apagar(){
  digitalWrite(PIN_LED_VERDE,LOW);
  digitalWrite(PIN_LED_AMARILLO,LOW);
  digitalWrite(PIN_LED_ROJO,HIGH);
  estado = ESTADO_OFF;
  Serial.println("Apagar.");
}

Tenías un par de errores.

  1. case ESTADO_OFF:      controlarEstadoOff();
    no tenía paréntesis al final

  2. tenías invertido los pulsadores, o sea.. o son pull up como estaba programado o pull down como esta dibujado. Para pull down corresponde este dibujo y para pull up corresponde el otro código

Genial, muchas gracias por arreglar mi codigo. Esos errores creo nunca me podria dar cuenta. Este codigo aunque es largo pero es mucho mas facil para mi aprenderlo.

Cordiales Saludos

Perdon, no comente agradecerte tambien por las mejoras del codigo como comprovar los estados de los led antes de iniciar el programa y la imprecion por pantalla de los estado del programa,esta cool,gracias.

Aprobecho y te comento que tengo un arduino fisico y en la funcion optener datos, el programa es mas estable con el "delay(50)" aunque el delay te para todo el programa en este caso es mas estable.

En estable me refiero a que cuando pulsamos el boton pasa al otro estado sin cometer errores,sin "delay(50)" aveses no pasa el siguiente estado muy limpio y ademas tambien se debuelbe de estado, osea de color los led.

Saludos

:grin: surbyte, qué dedicación, en mi caso es ver muchas líneas y ya me entra la vagancia :astonished:

surbyte, Pregunta rápida para evitar un offtopic en la parte de software. Veo que no usas en el cátodo de los leds resistencias de 220 ‎Ω ¿Es por algo del pull down?

Use Resistencias de 330 ohms y estoy en un simulador... no hay mucho de que preocuparse.