Go Down

Topic: Duda función millis en domotización para el apagado de un display (SOLUCIONADO) (Read 17943 times) previous topic - next topic

Dabauza

#30
Mar 21, 2014, 12:14 am Last Edit: Mar 21, 2014, 01:59 am by Dabauza Reason: 1
Muchas gracias juanpintom y JohnnyDeauville,

La verdad es que no entiendo mucho vuestros códigos y esto me hace darme cuenta de lo super verde que estoy. Voy a dedicarles mas tiempo a ver si los entiendo (hoy he estado muy liado y no he podido estar en cuanto apenas dedicado a mi placa  =(  ). Voy a poner aquí mi código, (si es que se le puede llamar así XD) por si queréis verla. Ya veréis que ni punto de comparación con los vuestros, ademas ni funciona  =(

Quote

#define pulsadorON 51
#define pulsadorDimmer 53
#define LED 2

int estadoPulsadorON=0;
int estadoActualON=0;
int estadoUltimoON=0;
int contadorON=0;

int estadoPulsadorDimmer=0;
int estadoActualDimmer=0;
int estadoDimmer=0;

unsigned long tiempo;
long pulsCorta=100;

int d=0;

void setup(){
pinMode(pulsadorDimmer,INPUT);
pinMode(pulsadorON,INPUT);
pinMode(LED,OUTPUT);

Serial.begin(9600);
}

void loop(){
//Contador para asignar el estado al boton ON/OFF.
estadoActualON=digitalRead(pulsadorON);
if(estadoActualON != estadoUltimoON){
   if(estadoActualON == HIGH){
     contadorON = contadorON +1;
//    Serial.print("pulsacion nº");
//    Serial.println(contadorON);
   }
}
estadoUltimoON=estadoActualON;


if(contadorON % 2 != 0){ //Pulsacion impar enciende el LED
//   tiempo=millis();
//   Serial.println("prueba repeticion del tiempo");
   if(digitalRead(pulsadorDimmer)){
     tiempo=millis();
//     Serial.println("prueba repeticion del tiempo");
     while(digitalRead(pulsadorDimmer) == HIGH)/*&&(millis()-tiempo) > pulsCorta)*/{
//       if((millis()-tiempo) > pulsCorta){
//        tiempo=millis();
//         Serial.println("Correcto");
         for(d=255;d>=0;d--){
         analogWrite(LED,d);
         estadoDimmer=d;
         }
//       } 
     }
   }
   else{analogWrite(LED,d);}
}

if(contadorON % 2 == 0){analogWrite(LED,0);}
}



El intento de codigo anterior XD tiene muchas lineas que son de prueba que estoy añadiendo y quitando según la marcha para ir viendo lo que pasa.

Mi intención era (y es) manejarlo con un solo pulsador, pero (y aquí viene lo bueno) con el primer pulso corto (pulsación impar) se encendiera al máximo y con otro pulso corto (pulsación par) se apagara. Ademas estado el led apagado, si mantengo pulsado el botón, que el led fuera encendiéndose poco a foco (incrementando la luminosidad). Y estando el led al máximo (o a mitad de la regulación) si mantengo pulsado el botón, que la luminosidad fuera disminuyendo. Y todo esto trataba de hacerlo sin usar la función delay. Y bueno ya os podéis imaginar que para alguien como yo (con conocimientos bastante limitados en la materia) en el lio en el que me he metido. XD

Así que luego se me ocurrió que para ir empezando tal vez fuera mas sencillo hacer que con un pulsador encendiera/apagara y con otro regulara. y en ello estaba.

Saludos y gracias por vuestras respuestas.

Edito:
juanpintom, ahora que has mencionado lo del karma ya se para que sirve. +1 para los dos ;)

juanpintom

Unos consejos (si se me permite) para mejorar tu programacion:

Intenta siempre utilizar variables que "correspondan" con el dato que van a guardar, me explico, es perfectamente valido:
int valor = 0; pero cuando unicamente va a contener el estado de un PIN, cuyo valor sera 0 o 1, es recomendable utilizar una variable tipo boolean: boolean valor = 0;

De esa forma
boolean -> 0 - 1
byte -> 0 - 254
int - 0 - 30 y pico mil
long - una burrada xD (para guardar millis() por ejemplo)

Asi se ahora espacio, que para estos micros viene bien, en sketches pequeños no pasa nada, pero para mas grandes si y es bueno hacerlo por costumbre :)

Otra cosa, debes entender (no solo saber) que el Arduino recorrera el void loop infinitamente, y en un codigo ciclico has de hacer lo que se llama depuracion, es decir, piensa que valor tendra caaada variable en cada "vuelta" del loop.

Por ejemplo, es parecido a lo que corrigio el sketch que te pase antes, si te fijas, es exactamente igual que el que puse en el post anterior pero añadiendo un "delay(50)", este delay lo que hace es que en lugar de recorrer el loop "a toda leche" pare un poco (50 milisegundos) en cada vuelta, lo que a la percepcion del ojo humano hace que el led pase de encenderse y apagarse (como te parecia a ti) a hacer el dimmer "correctamente", porque para subir desde 0 a 255 si en cada paso le pones una parada de 50ms tardara unos 12,75 segundos.
Ahora viene la mala noticia, se intenta minimizar el uso de la funcion delay() porque eso provoca que el Arduino este esperando sin mas, cuando podria (o deberia) estar haciendo otras cosas...  Un ejemplo de buen uso, es en Souliss utilizar las funciones ya implementadas de FAST_70ms() que haria ejecutar dicho codigo cada 70ms.

En tu codigo pasa algo parecido, piensa que si tu pulsas el boton y el arduino recorre el codigo casi cada milisegundo, estaria detectando e incrementando el pulsador muchisimo mas de lo que crees, a no ser, por ejemplo, una vez incrementado el pulsador haz al codigo esperar hasta que se suelte el boton.

En todo caso no seria la mejor forma de hacerlo, lo mejor para hacer detectar si haces 1 o 2 pulsaciones seguidas (y ademas tener en cuenta que puedes mantenerlo pulsado) tienes que replanteartelo.
Para encender con un click y apagar con 2 seria mas sencillo hacerlo con un click que invierta el estado, si aun asi tienes la intencion de hacer el "doble click" lo ideal seria medir el tiempo entre clicks y valorar entonces si es un click o doble click. Y para el tema del pulso es parecido, debes valorar si el click sigue activo mas de x tiempo y entonces empezar a hacer el dimmer. Un problema que te vas a encontrar es que debes valorar el tiempo que vas a invertir a esto.

Salu2
Souliss - Distributed Home Automation and Internet of Things<br /><br />http://www.souliss.net/<br /><br />http://forum.arduino.cc/index.php?topic=223723.0

Dabauza

#32
Mar 21, 2014, 02:42 am Last Edit: Mar 21, 2014, 02:58 am by Dabauza Reason: 1

Unos consejos (si se me permite) para mejorar tu programacion:


!!!Claro que se permiten!!! Cuantos mas mejor, con tal de mejorar en la programacion :)


Intenta siempre utilizar variables que "correspondan" con el dato que van a guardar, me explico, es perfectamente valido:
int valor = 0; pero cuando unicamente va a contener el estado de un PIN, cuyo valor sera 0 o 1, es recomendable utilizar una variable tipo boolean: boolean valor = 0;

De esa forma
boolean -> 0 - 1
byte -> 0 - 254
int - 0 - 30 y pico mil
long - una burrada xD (para guardar millis() por ejemplo)

Asi se ahora espacio, que para estos micros viene bien, en sketches pequeños no pasa nada, pero para mas grandes si y es bueno hacerlo por costumbre :)


De acuerdo, ahora lo veo mas claro, la verdad es que me liaba un poco con los boolean, char, byte, int,  long y toda la retafila de tipos de variables que hay XD. Me memorizare bien la cantidad de valores que puede tomar cada una para así poder signarlas como toca.


Otra cosa, debes entender (no solo saber) que el Arduino recorrera el void loop infinitamente, y en un codigo ciclico has de hacer lo que se llama depuracion, es decir, piensa que valor tendra caaada variable en cada "vuelta" del loop.


Esto si que lo sabia, pero tengo una mini duda XD. El loop Arduino lo recorre infinitamente mientras tenga alimentación, pero... Si yo hago un void aparte, por ejemplo, void escena1, este solamente entrara funcionamiento cuando yo lo llame en el loop. ¿No?


Por ejemplo, es parecido a lo que corrigio el sketch que te pase antes, si te fijas, es exactamente igual que el que puse en el post anterior pero añadiendo un "delay(50)", este delay lo que hace es que en lugar de recorrer el loop "a toda leche" pare un poco (50 milisegundos) en cada vuelta, lo que a la percepcion del ojo humano hace que el led pase de encenderse y apagarse (como te parecia a ti) a hacer el dimmer "correctamente", porque para subir desde 0 a 255 si en cada paso le pones una parada de 50ms tardara unos 12,75 segundos.


Si, los estuve comparando y ya vi que la única diferencia era el delay del final. Lo que me pareció extraño es que siempre que pulsaba encendía y cuando volvía a pulsar apagaba. Seria coincidencia.


Ahora viene la mala noticia, se intenta minimizar el uso de la funcion delay() porque eso provoca que el Arduino este esperando sin mas, cuando podria (o deberia) estar haciendo otras cosas...  Un ejemplo de buen uso, es en Souliss utilizar las funciones ya implementadas de FAST_70ms() que haria ejecutar dicho codigo cada 70ms.


Por eso intentaba hacer yo el dimmer sin delay, (he editado el post anterior, me había equivocado y había puesto millis en vez de delay) pero me parece que es una locura. El problema creo yo de hacerlo con el delay es que, si por ejemplo, tengo otro delay en el loop de 2000ms el dimmer cada paso lo dará a los 2050ms. ¿No? Por eso trato de no usar los delay. Pero a mi eso de hacer las pausas con los millis me vuelve loco, por que para que tome como referencia un valor del millis, lo asigne a una variable y no me lo modifique hasta que se cumpla toda la función hay que poner una condición al principio, como por ejemplo esto:

Code: [Select]
if ((contadorManual % 2 != 0)[b]&&(digitalRead(pulsadorManual)[/b])){
   tiempo = millis ();
   LCDman();
  }
else if (millis()-tiempo > temporizadorLCD){
   lcd.noBacklight();
   lcd.clear();


El problema yo lo tengo en que no se que condición poner (o me cuesta la vida verla) para que no me modifique la variable asignada.


En tu codigo pasa algo parecido, piensa que si tu pulsas el boton y el arduino recorre el codigo casi cada milisegundo, estaria detectando e incrementando el pulsador muchisimo mas de lo que crees, a no ser, por ejemplo, una vez incrementado el pulsador haz al codigo esperar hasta que se suelte el boton.


¿Te refieres a esta parte?

Code: [Select]
estadoActualON=digitalRead(pulsadorON);
if(estadoActualON != estadoUltimoON){
   if(estadoActualON == HIGH){
     contadorON = contadorON +1;
   }
}
estadoUltimoON=estadoActualON;


En este caso creo que no, porque para que incremente depende del estado anterior, en el momento en que yo pulso el estado cambia, y al ser ALTO incrementa el contador. Pero si yo lo mantengo pulsado como el estado es igual al anterior no incrementa. que igual me equivoco (y es lo mas probable) XD


En todo caso no seria la mejor forma de hacerlo, lo mejor para hacer detectar si haces 1 o 2 pulsaciones seguidas (y ademas tener en cuenta que puedes mantenerlo pulsado) tienes que replanteartelo.


Esta parte no te entiendo


Para encender con un click y apagar con 2 seria mas sencillo hacerlo con un click que invierta el estado, si aun asi tienes la intencion de hacer el "doble click" lo ideal seria medir el tiempo entre clicks y valorar entonces si es un click o doble click. Y para el tema del pulso es parecido, debes valorar si el click sigue activo mas de x tiempo y entonces empezar a hacer el dimmer. Un problema que te vas a encontrar es que debes valorar el tiempo que vas a invertir a esto.


No se si te entiendo bien. Mi intención no era apagar con doble click lo que pretendo era 1 click enciendo, otro click apaga (que conmute el estado del led con cada click). Aunque esto de medir el tiempo entre clicks me lo apunto para un futuro.

Por otro lado, lo del pulso largo tenia pensado tomarlo como 500ms, aunque en el código que he subido creo que ponía otro valor. Es que como iba probando pues lo cambiaba cada dos por tres XD.

De todas formas voy a mirarme bien tu sketch para ver lo del cambio de estado, a ver si le pillo el rollo por que la verdad parece mucho menos jaleo que como yo lo hago

Muchas gracias por tus consejos, la verdad es que me vienen como agua de mayo. ;)

Saludos

Dabauza

Por cierto juanpintom (y todo el que quiera verlo), aquí dejo el código como lo llevo de momento.

Me falta modificar las cosas que me has comentado y terminar lo del dimmer para añadirlo en el modo manual pero mas o menos en esencia es esto XD

Saludos


juanpintom


Esto si que lo sabia, pero tengo una mini duda XD. El loop Arduino lo recorre infinitamente mientras tenga alimentación, pero... Si yo hago un void aparte, por ejemplo, void escena1, este solamente entrara funcionamiento cuando yo lo llame en el loop. ¿No?

Exacto, lo que llamas void seria precisamente una duda que comentaste, las funciones :)

La idea es que una funcion es una porcion de codigo que puede ser llamada en diferentes momentos de la ejecucion, ademas permiten "enviar" datos y devolver "respuesta", te pongo el ejemplo mas sencillo que conozco en programacion:
Supongamos que tuvieramos una interfaz para introducir los valores a y b.

Code: [Select]
void loop(){
int a = 10;
int b = 15
int c;

c = suma(a,b);   // Llamamos a la funcion suma() enviando los valores a y b y asignando la "respuesta" a la variable c
println(c); //imprimira la respuesta
}

//la funcion se declara poniendo delante void si no devuelve nada o el tipo de variable que devuelve, en este caso un int, y tambien tiene que tener declarados los valores que recibira y el tipo (int en este caso) debe corresponder con el que enviemos al llamar a la funcion, es decir con a y b.

int suma (int valor1, int valor2){     
     int resultado;
     resultado = valor1 + valor2;
     return resultado;    // la linea return devuelve la respuesta y deja sin ejecutar las lineas que esten por debajo (si las hubiera)
}





Si, los estuve comparando y ya vi que la única diferencia era el delay del final. Lo que me pareció extraño es que siempre que pulsaba encendía y cuando volvía a pulsar apagaba. Seria coincidencia.

No, lo hacia bien porque en mi codigo esta la linea:
Code: [Select]
if (!digitalRead(BOTON)) {
Que si te fijas tambien esta en el sketch de JohnnyDeauville, realmente los 2 hacen lo mismo simplemente "expresandolo" de formas diferentes.
En este caso, esa linea lo que hace es impedir que el codigo cambie de estado (subir o bajar), a no ser que el Boton se suelte. Que es parecido a lo que hace tu codigo en este otro Quote:

¿Te refieres a esta parte?

Code: [Select]
estadoActualON=digitalRead(pulsadorON);
if(estadoActualON != estadoUltimoON){
   if(estadoActualON == HIGH){
     contadorON = contadorON +1;
   }
}
estadoUltimoON=estadoActualON;


En este caso creo que no, porque para que incremente depende del estado anterior, en el momento en que yo pulso el estado cambia, y al ser ALTO incrementa el contador. Pero si yo lo mantengo pulsado como el estado es igual al anterior no incrementa. que igual me equivoco (y es lo mas probable) XD

Efectivamente tienes razon, lo hace correctamente .


El problema creo yo de hacerlo con el delay es que, si por ejemplo, tengo otro delay en el loop de 2000ms el dimmer cada paso lo dará a los 2050ms. ¿No?

Correcto, y problema grave xD


El problema yo lo tengo en que no se que condición poner (o me cuesta la vida verla) para que no me modifique la variable asignada.


Es mas o menos la misma duda que la anterior, debes evaluar que solo asigne millis a tiempo la primera vez que se pulse.
En todo caso ese codigo funciona, no?


Esta parte no te entiendo

Tranquilo, a veces yo tampoco me entiendo... xD
Lo que queria decir es que en ese caso el codigo efectivamente era mucho mas sencillo, te lo pongo con el codigo de JohnnyDeauville, que como digo hace lo mismo, pero mas optimizado :)

Code: [Select]
#define PIN_LED 9
#define PIN_BOTON 2

#define MODO_ESPERA 0
#define MODO_ARRIBA 1
#define MODO_ABAJO  2
#define MODO_ON 3
#define MODO_OFF 4

byte byBrillo = 0;
byte byModo = MODO_ESPERA;
unsigned long tiempo;

void setup()
{
   
   pinMode( PIN_LED, OUTPUT );
pinMode( PIN_BOTON, INPUT );

}

void loop()
{

if( !digitalRead( PIN_BOTON ) ) {
 
  byModo = MODO_ESPERA;
  tiempo = millis();

} else {

  switch( byModo ) {
  case MODO_ARRIBA:
    byBrillo = min( byBrillo++, 255 );
    break;
   
  case MODO_ABAJO:
    byBrillo = max( byBrillo - 2, 0 );
    break;

  case MODO_ON:
    byBrillo = 255;
    break;

  case MODO_OFF:
    byBrillo = 0;
    break;
 
  default:
    if (millis() - tiempo > 500)
            byModo = ( ( byBrillo == 0 ) ? MODO_ARRIBA : MODO_ABAJO );
    else
            byModo = ( ( byBrillo == 0 ) ? MODO_ON : MODO_OFF );
  }
     
     analogWrite( PIN_LED, byBrillo ); 
     delay( 50 );

  }


Salu2
Souliss - Distributed Home Automation and Internet of Things<br /><br />http://www.souliss.net/<br /><br />http://forum.arduino.cc/index.php?topic=223723.0

Dabauza

#35
Mar 21, 2014, 10:36 am Last Edit: Mar 21, 2014, 05:45 pm by Dabauza Reason: 1

La idea es que una funcion es una porcion de codigo que puede ser llamada en diferentes momentos de la ejecucion, ademas permiten "enviar" datos y devolver "respuesta", te pongo el ejemplo mas sencillo que conozco en programacion:
Supongamos que tuvieramos una interfaz para introducir los valores a y b.

Code: [Select]
void loop(){
int a = 10;
int b = 15
int c;

c = suma(a,b);   // Llamamos a la funcion suma() enviando los valores a y b y asignando la "respuesta" a la variable c
println(c); //imprimira la respuesta
}

//la funcion se declara poniendo delante void si no devuelve nada o el tipo de variable que devuelve, en este caso un int, y tambien tiene que tener declarados los valores que recibira y el tipo (int en este caso) debe corresponder con el que enviemos al llamar a la funcion, es decir con a y b.

int suma (int valor1, int valor2){     
     int resultado;
     resultado = valor1 + valor2;
     return resultado;    // la linea return devuelve la respuesta y deja sin ejecutar las lineas que esten por debajo (si las hubiera)
}



Vale, creo que ya lo voy pillando. Si pusiera, por ejemplo, void escena1() y en loop con un pulsador llamara a esta escena, esta no devuelve respuesta. esto lo podría usar por ejemplo para un apagado general o cualquier otra cosa que no espere ningún tipo de respuesta.

Pero si pusiera "byte dimmer ()" y dentro de esta función declarara la función del dimmer  y al final del todo pusiera "return estadodimmer" podría usar la respuesta que me devuelve para mostrar en el LCD el nivel de regulación al que esta funcionando el LED.

Es un poco lió la estructura pero solo es cuestión de practicarla unas cuantas veces para cogerle el punto.



No, lo hacia bien porque en mi codigo esta la linea:
Code: [Select]
if (!digitalRead(BOTON)) {
Que si te fijas tambien esta en el sketch de JohnnyDeauville, realmente los 2 hacen lo mismo simplemente "expresandolo" de formas diferentes.
En este caso, esa linea lo que hace es impedir que el codigo cambie de estado (subir o bajar), a no ser que el Boton se suelte.


Vale, me los he revisado una y otra vez y al final creo que he pillado el fincionamiento, solo tengo tres dudas tontas. La primera:

En el trozo este del codigo de JohnnyDeauville,

Quote
Code: [Select]
  case MODO_ARRIBA:
    byBrillo = min( byBrillo++, 255 );
    break;
   
  case MODO_ABAJO:
    byBrillo = max( byBrillo - 2, 0 );
    break;


La regulación ascendente la hará paso a paso, pero la descendente de dos en dos. ¿No?

Luego, esto:

Quote
Code: [Select]
  default:
    byModo = ( ( byBrillo == 0 ) ? MODO_ARRIBA : MODO_ABAJO );


Si no se ejecuta nada anterior del código se ejecuta esto, hasta aquí todo bien, ¿pero que quiere decir? "MODO_ARRIBA : MODO_ABAJO" (los dos puntos entre uno y otro)

Y la ultima. Si yo le asigno un valor a una variable dentro de un if, el valor que esta tome se mantendrá hasta que yo lo cambie en algún momento del loop. ¿No? Como aquí: (Escribo sobre tu codigo)

Code: [Select]
void loop()
{
    if (!digitalRead(BOTON)) {   //Esto se ejecutara todo el rato hasta que yo pulse el BOTON, Entonces esta condición dejara de
          up = false;                      //cumplirse y pasare al else
          down = false;
    }else{
        if (!up && !down && Brillo == 0) up = true;  //Entonces si yo continuo manteniendo pulsado BOTON le asigana a  up el valor
                                                                               //true
        if (up && Brillo < 254) Brillo++;   //Y va incrementando el brillo hasta 254 como máximo, momento en el cual soltare el BOTON
                                                            //Y up volvera a se false en el if
        if (!up && !down && Brillo >= 1) down = true;  //si vuelvo a pulsar BOTON y como el brillo es > que 1  le asigna a down el valor
                                                                                   //true
        if (down && Brillo > 0)                                       //Si down es true y brillo > de 0
            if (Brillo == 1) Brillo--; else Brillo=Brillo-2;     //Si brillo es igual a 1, brillo disminuira; Si no Brillo disminuira de dos en dos
           
        analogWrite(LEDPIN,Brillo); 
        delay(50);

    }
}


Seria así. ¿No?

Quote
En todo caso ese codigo funciona, no?


No, el mio no funciona. Al menos por el momento XD

Quote
Lo que queria decir es que en ese caso el codigo efectivamente era mucho mas sencillo, te lo pongo con el codigo de JohnnyDeauville, que como digo hace lo mismo, pero mas optimizado :)

Code: [Select]
#define PIN_LED 9
#define PIN_BOTON 2

#define MODO_ESPERA 0
#define MODO_ARRIBA 1
#define MODO_ABAJO  2
#define MODO_ON 3
#define MODO_OFF 4

byte byBrillo = 0;
byte byModo = MODO_ESPERA;
unsigned long tiempo;

void setup()
{
   
   pinMode( PIN_LED, OUTPUT );
pinMode( PIN_BOTON, INPUT );

}

void loop()
{

if( !digitalRead( PIN_BOTON ) ) {
 
  byModo = MODO_ESPERA;
  tiempo = millis();

} else {

  switch( byModo ) {
  case MODO_ARRIBA:
    byBrillo = min( byBrillo++, 255 );
    break;
   
  case MODO_ABAJO:
    byBrillo = max( byBrillo - 2, 0 );
    break;

  case MODO_ON:
    byBrillo = 255;
    break;

  case MODO_OFF:
    byBrillo = 0;
    break;
 
  default:
    if (millis() - tiempo > 500)
            byModo = ( ( byBrillo == 0 ) ? MODO_ARRIBA : MODO_ABAJO );
    else
            byModo = ( ( byBrillo == 0 ) ? MODO_ON : MODO_OFF );
  }
     
     analogWrite( PIN_LED, byBrillo ); 
     delay( 50 );

  }


Es mas largo, pero parece mas sencillo. Lo único es (como en el caso anterior) no termino de entender que papel desempeñan los ":" en el default. :~  he buscado en el libro y no lo he visto por ningún lado  =(

Bueno, tras tres horas invertidas en esto, por lo menos lo empiezo a ver mas claro. Voy a probar a ponerlo en practica con el dimmer a ver si consigo hacerlo como yo pretendía.

Muchiiiiiiiiiiiiisiiiiiiiiiiiimas gracias.

juanpintom, tienes una cerveza (cafe o lo que sea) pagada cuando quieras ;)

Saludos

Dabauza

#36
Mar 21, 2014, 12:38 pm Last Edit: Mar 21, 2014, 10:09 pm by Dabauza Reason: 1
Asi es como lo tengo de momento:

Code: [Select]
#define LED 2
#define BOTON 53

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

byte BRILLO = 0;
byte MODO = MODO_ESPERA;

unsigned long tiempo;

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

void loop(){
  if(!digitalRead(BOTON)){
    MODO = MODO_ESPERA;
    tiempo=millis();
  }
  else{
    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 ((millis() - tiempo > 1) && (millis() - tiempo < 500))
          MODO = ((BRILLO == 0) ? ON : OFF);
        else if (millis() - tiempo > 500)
          MODO = ((BRILLO == 255) ? BAJA : SUBE);     
    }
  }
  analogWrite(LED,BRILLO);
  delay(10);
}


Enciende y apaga pero no regula... ¿por que?  =( =( =( =( =( =(

Edito:
Creo que ya se el porque. En el momento justo que pulso el botón cambia de estado y la programación se mete en el switch por eso no le da tiempo a reconocer el tipo de pulsación..

Edito:
Nada, que no hay manera, lo máximo que consigo es control ON/OFF o dimmer, pero las dos funciones en un mismo botón no me sale. Si lo hago solo función dimmer (sin ON/OFF) el retardo de la pulsación si que lo tiene en cuenta antes de empezar a regular.

Edito de nuevo:
juanpintom ahora releyendo me acabo de dar cuenta que lo que yo estoy haciendo es prácticamente lo mismo que me habías puesto tu antes, pffff, menudo jaleo de cabeza que llevo.
Estoy probando tu código también (el ultimo que me has subido) y hace lo mismo que el mio, solo control ON/OFF, pero no hace la función dimmer (no le termino de pillar el punto yo a los millis()).

Saludos

juanpintom


Vale, creo que ya lo voy pillando. Si pusiera, por ejemplo, void escena1() y en loop con un pulsador llamara a esta escena, esta no devuelve respuesta. esto lo podría usar por ejemplo para un apagado general o cualquier otra cosa que no espere ningún tipo de respuesta.

Pero si pusiera "byte dimmer ()" y dentro de esta función declarara la función del dimmer  y al final del todo pusiera "return estadodimmer" podría usar la respuesta que me devuelve para mostrar en el LCD el nivel de regulación al que esta funcionando el LED.

Es un poco lió la estructura pero solo es cuestión de practicarla unas cuantas veces para cogerle el punto.

Correcto, esa es la idea de las funciones, y tienen mucho mas potencial.


La regulación ascendente la hará paso a paso, pero la descendente de dos en dos. ¿No?

Eso es


Code: [Select]
  default:
    byModo = ( ( byBrillo == 0 ) ? MODO_ARRIBA : MODO_ABAJO );

Esta linea es equivalente a:
    if (byBrillo == 0) byModo = MODO_ARRIBA; else byModo = MODO_ABAJO;

Por lo que la respuesta a tu prengunta (":") seria (else)


Si yo le asigno un valor a una variable dentro de un if, el valor que esta tome se mantendrá hasta que yo lo cambie en algún momento del loop.

Eso es, asi unicamente cuando el boton se levante, esas variables se pondran de nuevo a false.


juanpintom, tienes una cerveza (cafe o lo que sea) pagada cuando quieras ;)

Jaja, hecho!, Salu2
Souliss - Distributed Home Automation and Internet of Things<br /><br />http://www.souliss.net/<br /><br />http://forum.arduino.cc/index.php?topic=223723.0

Dabauza

Muchas gracias por tus respuestas juanpintom,

Al final he decidido probar a ver si conseguía sacarlo con dos botones en vez de con uno (uno para ON/OFF y otro para regular) y así si que me funciona.

Code: [Select]
#define LED 2
#define BOTON1 51
#define BOTON2 53

#define ESPERA1     0
#define ESPERA2     0
#define ON          1
#define OFF         2
#define SUBE        1
#define BAJA        2

byte BRILLO = 0;
byte MODO1 = ESPERA1;
byte MODO2 = ESPERA2;

unsigned long tiempo;
int retardoPulsacion = 500;

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

void loop(){
  if(!digitalRead(BOTON1)){
    MODO1 = ESPERA1;
  }
 
  else{
    switch(MODO1){     
    case ON:
      BRILLO = 255;
      break;
             
      case OFF:
      BRILLO = 0;
      break;   
   
      default:
          MODO1 = ((BRILLO == 0) ? ON : OFF); 
    }   
  }
 
  if(!digitalRead(BOTON2)){
    MODO2 = ESPERA2;
  }
  else{
    switch(MODO2){
      case SUBE:
        BRILLO = min (BRILLO++, 255);
        break;
       
      case BAJA:
        BRILLO = max (BRILLO--, 0);
        break;       
       
      default:
          MODO2 = ((BRILLO == 0) ? SUBE : BAJA);     
    }
  }
  analogWrite(LED,BRILLO);
  delay(10);
}


Así que voy a seguir probando a ver por que no me va con un solo pulsador, buscando he encontrado esta función "pulseIn":

http://arduino.cc/es/Reference/PulseIn#.UyyvBPl5NyU

Parece ser que sirve para medir el tiempo que esta pulsado un botón. La estoy probando ahora a ver si con esta si que consigo sacarlo.

Un saludo

juanpintom

#39
Mar 21, 2014, 10:43 pm Last Edit: Mar 21, 2014, 10:46 pm by juanpintom Reason: 1

Asi es como lo tengo de momento:

Code: [Select]
#define LED 2
#define BOTON 53

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

byte BRILLO = 0;
byte MODO = MODO_ESPERA;

unsigned long tiempo;

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

void loop(){
 if(!digitalRead(BOTON)){
   MODO = MODO_ESPERA;
   tiempo=millis();
 }
 else{
   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 ((millis() - tiempo > 1) && (millis() - tiempo < 500))
         MODO = ((BRILLO == 0) ? ON : OFF);
       else if (millis() - tiempo > 500)
         MODO = ((BRILLO == 255) ? BAJA : SUBE);      
   }
 }
 analogWrite(LED,BRILLO);
 delay(10);
}


Enciende y apaga pero no regula... ¿por que?  =( =( =( =( =( =(

Edito:
Creo que ya se el porque. En el momento justo que pulso el botón cambia de estado y la programación se mete en el switch por eso no le da tiempo a reconocer el tipo de pulsación..

Edito:
Nada, que no hay manera, lo máximo que consigo es control ON/OFF o dimmer, pero las dos funciones en un mismo botón no me sale. Si lo hago solo función dimmer (sin ON/OFF) el retardo de la pulsación si que lo tiene en cuenta antes de empezar a regular.

Edito de nuevo:
juanpintom ahora releyendo me acabo de dar cuenta que lo que yo estoy haciendo es prácticamente lo mismo que me habías puesto tu antes, pffff, menudo jaleo de cabeza que llevo.
Estoy probando tu código también (el ultimo que me has subido) y hace lo mismo que el mio, solo control ON/OFF, pero no hace la función dimmer (no le termino de pillar el punto yo a los millis()).

Saludos


Vale, es mi mala costumbre de escribir codigo y no probarlo xD ( lo siento pero no tengo ningun arduino libre xDD )

Lo que pasa en este caso es que efectivamente el switch case entra la primera vez en default: , y entrara en el "modo ON OFF", hasta ahi es normal, el problema viene cuando despues de entrar en modo ON-OFF quieres que al estar pulsado mas de x active el modo ARRIBA-ABAJO, seguramente asi tendras encendidos y apagados erraticos, y es dificil de entender (o dificil de explicar) prueba con este codigo, que no esta muy bien, y puede que tambien tenga fallos xD

Code: [Select]
#define PIN_LED 9
#define PIN_BOTON 2

#define MODO_ESPERA 0
#define MODO_ARRIBA 1
#define MODO_ABAJO  2

byte byBrillo = 0;
byte byModo = MODO_ESPERA;
unsigned long tiempo;

void setup()
{
 
  pinMode( PIN_LED, OUTPUT );
pinMode( PIN_BOTON, INPUT );

}

void loop()
{

if( !digitalRead( PIN_BOTON ) ) {
 
 byModo = MODO_ESPERA;
 if (millis() - tiempo < 500)
if ( byBrillo == 0 ) byBrillo = 255; else byBrillo = 0;
 
 tiempo = millis();

} else {

 switch( byModo ) {
 case MODO_ARRIBA:
   byBrillo = min( byBrillo++, 255 );
   break;
   
 case MODO_ABAJO:
   byBrillo = max( byBrillo - 2, 0 );
   break;

 default:
   if (millis() - tiempo > 500)
           byModo = ( ( byBrillo == 0 ) ? MODO_ARRIBA : MODO_ABAJO );
 }
   
    analogWrite( PIN_LED, byBrillo );  
    delay( 50 );

   }
}


Salu2
Souliss - Distributed Home Automation and Internet of Things<br /><br />http://www.souliss.net/<br /><br />http://forum.arduino.cc/index.php?topic=223723.0

Dabauza

#40
Mar 21, 2014, 11:08 pm Last Edit: Mar 22, 2014, 12:50 am by Dabauza Reason: 1

Prueba con este codigo, que no esta muy bien, y puede que tambien tenga fallos xD


Nada, pasa lo mismo.

Déjalo, no te preocupes, que me sabe mal, te tengo aquí liado  :smiley-roll-sweat: Voy a seguir intentándolo yo e iré poniendo aquí lo que vaya viendo así si quieres puedes ir viéndolo por si te sirve para algo (o le sirve a cualquier otra persona).

Si tengo alguna duda o algo ya te aviso.

Muchas gracias

Saludos

Dabauza

No lo consigo, al final me parece que lo voy a dejar en botones independientes y cuanto tenga mas experiencia en esto ya lo revisare por que si no me parece que de aquí no salgo.

Voy a montarlo con el proyecto principal y a retocar unas cosas.

JohnnyDeauville

Como veo, andas enfrascadísimo y aprendiendo, eso siempre está bien aunque cuesta muchos "palos" y equivocaciones, los que llevamos muchísimos años ya en esto -juer qué mayor que estoy, leñe-, tenemos vistas cosas que de primeras pasan por "bah, si da lo mismo" pero que a la larga ayudan, y mucho, a hacer buen código, y más comprensible hasta por uno mismo cuando lo ve después de tiempo sin haberlo tocado.

Una de mis "manías" que hacen que el código sea más claro es la que ya viste de utilizar las constantes en los #define con mayúsculas y siempre anteponiendo a qué grupo de datos está representando, de este modo, también podemos utilizar un mismo nombre para varias categorías, por ejemplo

Code: [Select]
#define PIN_TEMPERATURA  5

#define LIMITE_TEMPERATURA  25.0

de esta manera nunca te equivocas y permites más claridad en el código con coste mínimo -ten en cuenta que los #define no son más que una traducción del texto por el dato por parte del compilador, por lo que el consumo de memoria lo va a hacer el dato y no su nombre simbólico, que puede así ser todo lo largo que tú quieras, sin escribir El Quijote-

utilizar, siempre que puedas, switch y si no lo ves del todo claro, inicializa una variable que te permita usarlo, el uso de if else if else if... hace el código superengorroso de entender; por supuesto, no hay que volverse loco, si no se puede, no se puede

Para el asunto que te han comentado de ejecutar algo cada cierto tiempo, sin necesidad de más productos ni cosas, lo suyo es utilizar variables testigo, que permitan controlar el tiempo transcurrido tras la activación de algo -el que has pulsado un botón por ejemplo- y evitar que se repita ese proceso hasta que tú quieras, algo del estilo

Code: [Select]


// Cuando pulsamos un botón queremos 0.1 segundos de inactividad del botón hasta el próximo proceso
#define BOTON_ESPERA  100 
#define BOTON_MINIMO  20

long lComienzo;

void setup() {
   lComienzo = 0; 
}

void accionBoton() {
   Serial.print( "Pulsación de botón" );
   Serial.print( lComienzo, DEC );
}

void loop() {

  int iBoton;
 
  iBoton = analogRead( A0 );
 
  if( IBoton > MINIMO_BOTON && lComienzo == 0 ) {
    // Solo si se ha pulsado un botón y había pasado el tiempo suficiente se realiza la acción solicitada
    lComienzo = millis();
    accionBoton();
  }
 
  // Si se había pulsado un botón y pasó el tiempo requerido, se descarga la variable testigo
  if ( lComienzo != 0 && millis() - lComienzo >= BOTON_ESPERA ) lComienzo = 0;
 
}



No sé, si se me ocurre alguna otra charleta de Agüelo Cebolleta, ya te la haré llegar

Dabauza

Muchas gracias JohnnyDeauville por tus consejos.

La verdad es que creo que mi código ha mejorado mucho en la ultima semana :) ahora hasta mas o menos se entiende XD. Al final consegui sacar el dimmer con un solo botón y ademas le he añadido un mando a distancia, anoche también estuve terminandolo y organizandolo un poco.

Tengo que practicar el switch por que la verdad que se me hace mas fácil hacerlo con if else.

Voy a abrir un nuevo tema en la sección de proyectos y lo voy a poner allí (por si te quieres pasar a verlo) así si a alguien le hace falta puede verlo.

Un saludo


Go Up