Duda acción pulsador

Hola a todos,

He estado probando para hacer que un pulsador en una entrada digital, al hacer una pulsación encienda un led en otra salida digital y que esta se mantenga activa por ejemplo 5 segundos pero que si dentro de ese tiempo se pulsa otra vez el pulsador que apague directamente el led.

He probado un monton de formas pero no doy con la correcta, por eso os pido ayuda.

Saludos

haz probado con los ejemplos?

si no me equivoco, ahi debe estar uno parecido

Esto es lo único que he podido conseguir con los ejemplos, que un pulsador cada vez que pulsas encienda o apague, pero al probarlo parece que tiene bastantes rebotes y veo bastante complicado el código para simplemente encender o apagar mediante cada pulsación.

const int  buttonPin = 8;   
const int ledPin = 2;       

int buttonPushCounter = 0;   
int buttonState = 0;         
int lastButtonState = 0;     

void setup() {
  
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
  
}

void loop() {
  
  buttonState = digitalRead(buttonPin);
  
  if (buttonState != lastButtonState) {
    if (buttonState == HIGH) {
      buttonPushCounter++;
    } 
    lastButtonState = buttonState;
  }
  
  if (buttonPushCounter % 2 == 0) {
    digitalWrite(ledPin, HIGH);
  } else {
   digitalWrite(ledPin, LOW);
  }
  
}

De todas maneras lo que busco es lo que he comentado en el primer post pero veo que no soy capaz :'(

Bueno, pues lo primero y que supongo será mas sencillo no lo he conseguido todavía. :-[

Pero he conseguido, y esto tambien estuve buscando ejemplos durante bastante tiempo, que con una pulsación se encienda un led durante un determinado tiempo, que en este caso he puesto 5 segundos y que si en cualquier momento se pulsa de nuevo durante, en este caso, mas de 800 milisegundos apague el led directamente y como es lógico lo mantenga encendido el tiempo que esté pulsado.

De esta forma he conseguido hacer el típico boton bifuncional que con una pulsación hace una cosa y manteniendolo pulsado hace otra. Lo dejo por aquí por si a alguien le puede ayudar ya que yo no encontré nada en su momento.

Lo que he comprobado es que cuando se mantiene pulsado mas de 5 segundos, la salida da 5 voltios y en el segundo 5 baja a 3 voltios y pico :o

Si alguien pudiera hechar un vistazo al código para hacerlo mas sencillo y/o subsanar el tema de los voltios se lo agradecería.

Saludos

const int buttonPin = 8;     
const int ledPin =  2;      

byte buttonState;             
byte lastButtonState;   

long lastButtonDelay = 0;  
long buttonDelay = 800; 
long actionDelay = 5000;

void setup() {
  
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
  
}

void loop() {
  
  byte reading = digitalRead(buttonPin);
  
  if (reading != lastButtonState) {
    digitalWrite(ledPin, HIGH);
    lastButtonDelay = millis();
  }
  
  if ((millis() - lastButtonDelay) > actionDelay) {
    digitalWrite(ledPin, LOW);
  }
  
  if ((millis() - lastButtonDelay) > buttonDelay) {
    buttonState = reading;
  }
  
  if (buttonState) {
  digitalWrite(ledPin, reading);
  }
  
  lastButtonState = reading;
  
}

Hola,

Una forma sencilla de resolver este tipo de problemas, es dibujarte un diagrama de estados.

Me explico:

--------------------------------------------> ESTADO 1 (Accion: Led off, al salir guardar tiempo)
¦ ¦
¦ ¦
¦ ¦
¦ ¦
¦ ¦
¦ ¦
¦ — (Pulsador)
—(tiempo>5sg OR pulsador) ¦
¦ ¦
¦ ¦
¦ \¦/
--------------------------------------------< ESTADO 2 (Accion: Led on)

Es decir, el programa empieza en el estado 1 (condicion inicial).
Si estando en el estado 1, se me cumple la condicion de activar el pulsador, entonces cambio a estado 2. (En el momento de salir, recojo el tiempo).
Si estando en el estado 2, activo el pulsador o tiempo > 5 segundos, entonces cambio al estado 1.

Accion mientras ESTADO= 1-> Led OFF
Accion mientras ESTADO= 2-> Led ON

Pseudocodigo:
int state=1;
void loop(){
** if (state==1 && pulsador){**
** delay(100); //evitar rebotes**
** state=2;**
** t_start=millis();**
** end**
** if (state==2 && (pulsador OR (millis()-t_start)>5000)){**
** delay(100); //evitar rebotes **
** state=1;**
** end**
** switch (state){**
** case 1:**
** digitalWrite(led,LOW);**
** break;**
** case 2:**
** digitalWrite(led,HIGH);**
** break;**
** }**
}[/b]
No es el codigo tal cual, es pseudocodigo para que se me entienda…
Como lo ves pensandolo asi? se te hace mas facil?
(estoy en un teclado ingles, y no tengo ni acentos, ni apertura de interrogacion,…)
Saludos :wink:
Igor R.

Hola Igor, gracias por contestar, te he visto en varios posts y eres un máquina.

He intentado hacer lo siguiente pero no me funciona y no se para donde tirar.

#define pulsador 8
#define led 2

int state=1;
long t_start;
int temp=5000;

void setup() {
  
  pinMode(pulsador,INPUT);
  pinMode(led,OUTPUT);
}

void loop(){

     if (state==1 && pulsador){
           delay(100); //evitar rebotes
           state=2;
           t_start=millis();
     }
     end;

     if (state==2 && (pulsador || (millis() - t_start) > temp)){
           delay(100); //evitar rebotes            
           state=1;
     }
     end;

     switch (state){
           case 1:
                 digitalWrite(led,LOW);
                 break;
           case 2:
                 digitalWrite(led,HIGH);
                 break;
     }

}

Saludos

Hola,

Te falta leer el pulsador => pulsador=digitalRead(pin_pulsador). O bien sustituir pulsador por digitalRead(pulsador)

Saludos

Igor R.

Otra cosa....

#define pulsador 8
#define led 2

int state=1;
long t_start;
int temp=5000;

void setup() {

  pinMode(pulsador,INPUT);
  pinMode(led,OUTPUT);
}

void loop(){

     if (state==1 && digitalRead(pulsador)){
           delay(100); //evitar rebotes
           state=2;
           t_start=millis();
     }


     if (state==2 && (digitalRead(pulsador) || (millis() - t_start) > temp)){
           delay(100); //evitar rebotes
           state=1;
     }


     switch (state){
           case 1:
                 digitalWrite(led,LOW);
                 break;
           case 2:
                 digitalWrite(led,HIGH);
                 break;
     }

}

Los if, van sin end.

;)

Hola de nuevo Igor,

a quedado algo así:

#define pulsador 8
#define led 2

int state=1;
long t_start;
int temp=5000;

void setup() {

  pinMode(pulsador,INPUT);
  pinMode(led,OUTPUT);
}

void loop(){

     if (state==1 && digitalRead(pulsador)){
           delay(100); //evitar rebotes
           state=2;
           t_start=millis();
     }
     end;

     if (state==2 && (digitalRead(pulsador) || (millis() - t_start) > temp)){
           delay(100); //evitar rebotes
           state=1;
     }
     end;

     switch (state){
           case 1:
                 digitalWrite(led,LOW);
                 break;
           case 2:
                 digitalWrite(led,HIGH);
                 break;
     }

}

Pero al compilar me dice lo siguiente:

In function 'void loop()': error: 'end' was not declared in this scope

Saludos

Lee mi post anterior, que hemos escrito a la vez....je,je,je

;)

Perdoname, parece que hemos posteado casi a la vez jejeje, voy a probar lo que has puesto.

Saludos

Editado: jejejej otra vez...voy a ello...

Perfecto Igor!!!

Lo único que he bajado los delay's a 50 porque hacía cosas rarillas, pero vamos, lo que te digo, eres una máquina.

Por cierto, también te agradezco que no me hallas dado todo hecho al principio para ir quemando coco y aprendiendo.

Por cierto, has visto algo raro en el otro código de pulsando o manteniendo pulsado?

Saludos ;)

La verdad que no me lo he mirado.... Lo que quería explicar es como abordar un programa de otra manera diferente a la habitual.

En mi opinión, resolver un problema pensado en programación de estados (Finite State Machine), es una manera que facilita muchísimo el ponerse luego manos a la obra y tener todos los casos acotados. A parte de ser fácil de escribir con papel y boli para pensar el algoritmo a resolver.

De hecho, en muchos autómatas (grafcet), en Matlab(Stateflow),... se usa este módelo de programación directamente (método gráfico).

Creo que hay algun proyecto para utilizarlo en Arduino...

Como te ha parecido al leerlo...¿lo has entendido? ¿Te parece más fácil de esta manera?

Desde luego, mucho mas claro, la primera vez que vi el switch case empecé a entender y a agregar mas codigo sin mucha complicación.

Me alegro ;)

Hay otras maneras de pasar de diagrama de estados a programación lineal, por ejemplo, sólo usando el switch.... Una vez entendido el concepto, ya es una cosa de traducción....

[u]Pseudocódigo:[/u]

define LED_OFF 1

define LED_ON 2

int estado=0;

void loop(){ swicth(estado){

case LED_OFF: delay(100); //rebotes digitalWrite(led,LOW); if digitalRead(pulsador){ estado=LED_ON; t_start=millis(); } break;

case LED_ON: delay(100); //rebotes digitalWrite(led,LOW); if ((digitalRead(pulsador) || (millis() - t_start) > temp)) estado=LED_OFF; break;

default: estado=LED_OFF break;

}

En default, sería tu condicion inicial.....Podrías utilizarlo para inicializar variables, temporizadores,...

Saludos

Igor R.

He hecho algo así pero no funciona, lo del default no se como va...

#default LED_OFF 1
#default LED_ON 2

#define pulsador 8
#define led 2

int estado=0;
int temp=5000;
long t_start;

void setup(){
  
  pinMode(pulsador,INPUT);
  pinMode(led,OUTPUT);

}

void loop(){
  
     switch(estado){

           case LED_OFF:
                 delay(100); //rebotes
                 digitalWrite(led,LOW);
                     if (digitalRead(pulsador)){      
                     estado=LED_ON;
                     t_start=millis();
                     }
                 break;

           case LED_ON:
                 delay(100); //rebotes
                 digitalWrite(led,LOW);
                 if ((digitalRead(pulsador) || (millis() - t_start) > temp))      
                 estado=LED_OFF;
                 break;
           
           default:
                 estado=LED_OFF
                 break;
     

}

Es #define.... je,je,je. No se en que estaba pensando. He editado el post. ;D

A parte te falta: 1) un } al final. Tienes que cerrar el switch y el void loop. 2) un ;

#define LED_OFF 1
#define LED_ON 2

#define pulsador 8
#define led 2

int estado=0;
int temp=5000;
long t_start;

void setup(){

  pinMode(pulsador,INPUT);
  pinMode(led,OUTPUT);

}

void loop(){

  switch(estado){

    case LED_OFF:
      delay(100); //rebotes
      digitalWrite(led,LOW);
      if (digitalRead(pulsador)){
        estado=LED_ON;
        t_start=millis();
       }
      break;

    case LED_ON:
      delay(100); //rebotes
      digitalWrite(led,LOW);
      if ((digitalRead(pulsador) || (millis() - t_start) > temp))    estado=LED_OFF;
      break;

    default:
      estado=LED_OFF;
      break;


  } 
}

Pues chico, no me funciona, he añadido las llaves al ultimo if y quitado unos parentesis del mismo que parecia que sobraban, compila pero al subirlo al arduino no hace nada.

De todas maneras, en programacion lineal como sería, como lo he puesto yo al principio? o sería menos engorroso.

#define LED_OFF 1
#define LED_ON 2

#define pulsador 8
#define led 2

int estado=0;
int temp=5000;
long t_start;

void setup(){

  pinMode(pulsador,INPUT);
  pinMode(led,OUTPUT);

}

void loop(){

  switch(estado){

    case LED_OFF:
      delay(100); //rebotes
      digitalWrite(led,LOW);
            if (digitalRead(pulsador)){
              estado=LED_ON;
              t_start=millis();
          }
      break;

    case LED_ON:
      delay(100); //rebotes
      digitalWrite(led,LOW);
            if (digitalRead(pulsador) || (millis() - t_start) > temp){    
            estado=LED_OFF;
          }
      break;

    default:
      estado=LED_OFF;
      break;
  }
}

Ahí va mi duda la cual ya he explicado a Igor, en la cual quiero simular una bomba en la qie apretando un botón lanza una cuenta atrás mientras se “arma” y al finalizar explota y que cuando se está armando al presionar el pulsador 2 lance otra cuenta atrás para desarmarla. Vosotros me diréis…

Gracias! :wink:

#define pulsador 8
#define pulsador2 9
#define led 2
#define led2 3
#define led3 4
#define led4 5

int state=1;
long t_start;
long t_start2;
int temparmed=5000;
int tempdisarmed=5000;

void setup() {

  pinMode(pulsador,INPUT);
  pinMode(pulsador2,INPUT);
  pinMode(led,OUTPUT);
  pinMode(led2,OUTPUT);
  pinMode(led3,OUTPUT);
  pinMode(led4,OUTPUT);
  
}

void loop(){

     if (state==1 && digitalRead(pulsador)){
           delay(100); //evitar rebotes
           state=2;
           t_start=millis();
     }


     if (state==2 && (millis() - t_start) > temparmed){
           state=3;
     }
     
     if (state==2 && digitalRead(pulsador2)) {
             delay(100);
             state=4;
             t_start2=millis();
     }
     
     if (state==4 && (millis() - t_start) > tempdisarmed){
             state=1;
     }
               


     switch (state){
           case 1:
                 digitalWrite(led,HIGH);
                 break;
           case 2:
                 digitalWrite(led2,HIGH);
                     delay(100);
                     digitalWrite(led2,LOW);
                     delay(100);
                 break;
             case 3: 
                     digitalWrite(led4,HIGH);
                     break;
             case 4: 
                     digitalWrite(led3,HIGH);
                     delay(100);
                     digitalWrite(led3,LOW);
                     delay(100);                     
     }

}