Reconocimiento pulsación corta/larga para el dimmerizado de un LED (SOLUCIONADO)

Muy buenas,

Tengo un problema que me trae de cabeza ya durante un par de dias y no se como solucionarlo.

Mi idea es hacer un dimmer mediante programación para poder controlar la iluminación de un led con un único pulsador. El funcionamiento que pretendo es el siguiente:

Pulsaciones cortas = ON/OFF led
Pulsaciones largas (>= 1 segundo) = Regulación led

#define LED 2
#define BOTON 53

#define ESPERA      0
#define SUBE        1
#define BAJA        2
#define ON          3
#define OFF         4

byte BRILLO = 0;
byte MODO = ESPERA;

unsigned long tiempo;
unsigned long tiempo2;
int retardoPulsacion = 1000;

void setup(){
 pinMode(LED, OUTPUT);
 pinMode(BOTON, INPUT); 
}


void loop(){  
  if(!digitalRead(BOTON)){
    MODO = ESPERA;    
    Serial.println("ESPERA");
    tiempo=millis();
    Serial.println(tiempo);
  }

  else if(digitalRead(BOTON)){
    tiempo2=millis();
    Serial.println(tiempo2);  
    switch(MODO){
      case SUBE:
        BRILLO = min (BRILLO++, 255);
        break;
      
      case BAJA:
        BRILLO = max (BRILLO--, 0);
        break;
      
      case ON:
        BRILLO = 255;
        break;
            
      case OFF:
        BRILLO = 0;
        break;
     
      default:      
        if ((tiempo2-tiempo) < retardoPulsacion){
          MODO = ((BRILLO == 0) ? ON : OFF);
        }
        else if ((tiempo2-tiempo) >= retardoPulsacion){
          MODO = ((BRILLO == 0) ? SUBE : BAJA);  
        }  
    }
  }
  analogWrite(LED,BRILLO);
  delay(10);
}

He probado todo lo que se me a ocurrido incluso la función pulseIn y no he conseguido que funcione. Con dos botones independientes, uno para encender y otro para regular si que he podido hacerlo funcionar, pero con el mismo no.

El problema creo que esta en que la pulsación la reconoce siempre antes como pulsación corta (aunque no haya llegado a soltar el botón). Entonces creo que debería hacer la comparación de los tiempos antes. Pero no se como hacerla.

Agradecería mucho una ayuda.

Un saludo y muchas gracias.

busca en la parte de playground una libreria button. hace lo que buscas

maxid:
busca en la parte de playground una libreria button. hace lo que buscas

Muchas gracias, Ahora mismo me pongo a verlo

Saludos

Quizás algo así:

#define LED 2
#define BOTON 53

int brillo = 0;
int direccion=1; // Brillo aumentando
byte estado_pulsador=LOW;
byte estado_luz=LOW;

unsigned long millis_pulsacion;
const unsigned long retardoPulsacion = 1000;

void setup(){
 pinMode(LED, OUTPUT);
 pinMode(BOTON, INPUT); 
}


void loop(){
      byte pulsacion=digitalRead(BOTON);
      unsigned long millis_actual=millis();
      if (pulsacion!=estado_pulsador){  // Ha habido cambio en el estado del pulsador
            if (pulsacion==HIGH){      // Acabamos de pulsar, guardamos millis
                  millis_pulsacion=millis_actual; 
            } else {
                  if( (millis_actual-millis_pulsacion) < retardoPulsacion) // acabamos de soltar pulsación corta, conmutamos
                       estado_luz = !estado_luz; 
            }
      } else {
            if (pulsacion==HIGH && (millis_actual-millis_pulsacion) >= retardoPulsacion) { // Estado pulsado largo
                  if(brillo==255 || brillo==0) direccion=-direccion; // Si estamos en límite cambiamos la dirección 
                  brillo+=direccion;
            }
      }
  
  analogWrite( LED,estado_luz ? brillo : 0 );
  delay(10);
}

Está sin probar, pero ya me dirás.
Saludos.

Hola noter,

El código no funciona. He tratado de arreglarlo pero no he tenido éxito. De todos modos te agradezco la ayuda.

Nunca me habría imaginado que lograr el reconocimiento del tipo de pulsación me traería tantos dolores de cabeza. =(

Un saludo

Es que me pillas sin arduino y no puedo comprobar, pero creo que no ando lejos de la solución. Prueba a cambiar el valor inicial de brillo a 100 (error haber puesto cero). De paso muestra por serial su valor, a ver que resultado obtienes.

Tranquilo, al final creo que por fin he encontrado la solución. Gracias a tu sketch me has dado la idea de guardar el tiempo en el que se realiza la pulsación y el tiempo en el que se suelta para después compararlos. Y si es menor a 1 segundo ---> ON/OFF. Por otro lado también guardo el momento en el que pulso el botón y lo comparo con millis y si es mayor a 1 segundo ---> Regulación,

Dejo aquí el código por si a alguien le queréis pegar un ojo, o por si a alguien le puede servir, ya que no tengo demasiada experiencia en programación y me a costado días encontrar la solución.

#define LED 2            //Pin al que esta conectado el LED
#define BOTON 53         //Pin al que esta conectado el pulsador 
#define ESPERA      0    //Modo espera (dimmer)
#define SUBE        1    //Modo regulacion ascendente (dimmer)
#define BAJA        2    //Modo regulacion descendente (dimmer)

boolean estadoActual  = 0;   //Estado actual pulsador
boolean estadoUltimo  = 0;   //Estado ultimo pulsador
boolean contadorONOFF = 0;   //Contador de pulsaciones

unsigned long Tinicio;         //Momento en que se pulsa el pulsador
unsigned long Tfin;            //Momento en que se libera el pulsador
unsigned long Tpulsacion;      //Diferencia Tfin-Tinicio
long retardoPulsacion = 1000;  //Tiempo pulsacion larga

byte BRILLO = 0;              //Valor del Brillo 
byte MODODIMMER = ESPERA;     //Modo dimmer (Espera, Sube, baja)

void setup(){
 pinMode(BOTON,INPUT);        //Boton como entrada
 pinMode(LED,OUTPUT);         //LED como salida
 Serial.begin(9600);
}

void loop(){
//PARA CONTROL ON/OFF//
  estadoActual = digitalRead(BOTON);        //Para leer el estado del pulsador
  if(estadoActual != estadoUltimo){         //Si el nuevo estado es distinto al ultimo...
    if(estadoActual == HIGH){               //Si el estado es alto(cuando se aprita el boton) 
      contadorONOFF = contadorONOFF + 1;    //Incrementa 1 al contador
      Tinicio = millis();}                  //Guarda el momento de la pulsacion
    if(estadoActual == LOW){                //Si el estado es bajo(cuando se libera el boton)
      Tfin = millis();}                     //Guarda el momento de la liberacion
    Tpulsacion = (Tfin-Tinicio);            //Calculo de la duracion de la pulsacion
  }
  estadoUltimo = estadoActual;              //Guarda el ultimo estado del boton
  
  if((contadorONOFF % 2 != 0)&&(Tpulsacion<retardoPulsacion)){           //Pulsacion impar enciende el LED
   ONLED();}
  else if((contadorONOFF % 2 == 0)&&(Tpulsacion<retardoPulsacion)){      //Pulsacion par apaga el LED
   OFFLED();}
    
  
//PARA CONTROL DIMMER//
  if(!digitalRead(BOTON)){         //Mientras el boton este en reposo el dimmer estara en espera
    MODODIMMER = ESPERA;
    Tinicio = millis();}           //Guarda el ultimo instante en el dimmer a estado en espera
  else{DIMMER();}                  //Cuando se pulsa boton se activa el dimmer

//CONTROL LED//  
  analogWrite(LED,BRILLO);         //Escritura del valor del led
}        


//ENCENDDIDO ILUMINACION//
void ONLED(){
  if((Tpulsacion) < retardoPulsacion){BRILLO = 255;}
}

//APAGADO ILUMINACION//
void OFFLED(){
  if((Tpulsacion) < retardoPulsacion){BRILLO = 0;}
}

//DIMMER//
void DIMMER(){                                            //Si el tiempo de la pulsacion es mayor a un segundo
  switch(MODODIMMER){                                     //se activara la regulacion, que sera ascendente o descente
    case SUBE:  BRILLO = min (BRILLO++, 255); break;      //dependiendo del valor de BRILLO
      
    case BAJA:  BRILLO = max (BRILLO--, 0); break;

    default:      
      if ((millis()-Tinicio) >= retardoPulsacion){
        MODODIMMER = ((BRILLO == 0) ? SUBE : BAJA);      
      }      
  }
  delay(10);  
}

Se aceptan sugerencias, opiniones, criticas, etc XD

Un saludo y muchas gracias a todos

Enhorabuena! ha costado pero ha salido!! jaja, ahora a por mas cosas! :wink:

Salu2

tambien puedes usar la funcion pulsein. pero tampoco que es imposible.
te quedas en u while hasta que suelte la tecla. antes de eso tomas los milis actuales, al salir del while tomas los milis y comparas el tiempo.
la libreria buttons lo hace. ahora desde el celular no leo bien todo

juanpintom:
Enhorabuena! ha costado pero ha salido!! jaja, ahora a por mas cosas! :wink:

Muchas gracias :slight_smile:

Ahora quiero ver de mostrar en el display LCD el nivel de regulación en tanto por %.

Y a ver si llega pronto el pedido y empiezo a probar el sistema Souliss que ya tengo ganas :wink:

Edito:
Desde que me comentas que podía usar el monitor serie para encontrar errores, se me hace un poco mas sencilla la tarea :slight_smile:

También he estructurado el código por llamadas a funciones y así tengo la menor parte del código posible en el loop, esto hace que el programa vaya mas fluido.

Un saludo

maxid:
tambien puedes usar la funcion pulsein. pero tampoco que es imposible.
te quedas en u while hasta que suelte la tecla. antes de eso tomas los milis actuales, al salir del while tomas los milis y comparas el tiempo.
la libreria buttons lo hace. ahora desde el celular no leo bien todo

Hola maxid,

He estado probando la librería de Button, EasyButton y pulseIn pero aun no me aclaro mucho con las librerías, por eso lo he intentado hacer sin ellas. De todas formas agradezco tu interes.

Un saludo y muchas gracias por tus consejos :wink:

Dabauza:

juanpintom:
Enhorabuena! ha costado pero ha salido!! jaja, ahora a por mas cosas! :wink:

Muchas gracias :slight_smile:

Ahora quiero ver de mostrar en el display LCD el nivel de regulación en tanto por %.

Y a ver si llega pronto el pedido y empiezo a probar el sistema Souliss que ya tengo ganas :wink:

Edito:
Desde que me comentas que podía usar el monitor serie para encontrar errores, se me hace un poco mas sencilla la tarea :slight_smile:

También he estructurado el código por llamadas a funciones y así tengo la menor parte del código posible en el loop, esto hace que el programa vaya mas fluido.

Un saludo

Para mostrarlo en el LCD simplemente mostrando BRILLO es suficiente :slight_smile:

Lo de Souliss ya te digo yo que es mas "cumplido" que programar "a pelo" como en este post, me refiero a que usando las librerias (solo hay que leer el "manual" o referencia de cada una de ellas), en este caso usando Souliss, al tener ya todo o casi todo el codigo hecho, es mucho mas sencillo añadir un boton que haga la funcion de dimmer en pulso largo y de on/off, de hecho ya tengo un boton asi :slight_smile: y luego meter otras muchas cosas es igual de sencillo. Me referia a que es mucho mas "cumplido" a que con poco ves muchos avances y yo al menos, me incentiva mas asi.

Lo de monitor serial es mano de santo! jaja, no se puede vivir sin el XD

Lo de organizar el Loop es mucho mejor a la hora de ser leido por "nosotros", y si, hacen mas eficiente el codigo, aunque en estos codigos "pequeños" es imperceptible.

Salu2

Hola juanpintom,

El caso es que he hecho una regla de tres para que el valor mostrado sea en %.

Tengo unas ganas de que me lleguen ya los MAX485 y el ENC28J60 XD

Ahora, lo siguiente que voy a hacer es añadir un mando a distancia para poder controlar todas las funciones del proyecto principal. Ya he leido los valores hexadecimales de las teclas para poder asignarlas

Lo de organizar el Loop es mucho mejor a la hora de ser leído por "nosotros", y si, hacen mas eficiente el código, aunque en estos códigos "pequeños" es imperceptible.

Ya te digo si es mejor a la hora de entenderlo. XD

Pues yo si que he notado que va mas fluido, aunque tal vez es por que antes estaba un poco arreu y se volvia un poco loco al leer el código XD

Un saludo