Temporizador de encendido de leds

Hola, me de mi ultimo post me dijeron que use la funcion millis para que cuente el tiempo de encendido, ya mire por paginas y no lo consigo hacer, yo se que es parecido al ejemplo del Blinkwithoutdelay, pero no consigo implementar para que cuente el tiempo que queda encendido, os dejo mi codigo para que lo veais.

Perdonad si es lioso soy principiante,

#define PINBUT 2
#define PINLED1 3
#define PINLED2 6

int leds[2] = {1, 2};

bool estado_led = false;

unsigned long tiempo_on = 8000;
unsigned long tiempo_ant = 0;

int valor;
int valor_ant = 0;
int salida = 0;

void setup() {
  // put your setup code here, to run once:
  pinMode(PINBUT, INPUT);
  pinMode(PINLED1, OUTPUT);
  pinMode(PINLED2, OUTPUT);
  digitalWrite(PINLED1, LOW);
  digitalWrite(PINLED2, LOW);
}
void loop() {
  // put your main code here, to run repeatedly:
  valor = digitalRead(PINBUT);

  if((valor == 1)&&(valor_ant == 0)){
    salida = 1 - salida;
  }

  valor_ant = valor;


  if(salida == 0){
    digitalWrite(PINLED1, estado_led);
  }else{
    digitalWrite(PINLED1, estado_led);
    if(PINLED1 == HIGH){
      unsigned long tiempo_aho = millis();
        if((unsigned long)(tiempo_aho - tiempo_ant >= tiempo_on)){
          estado_led = !estado_led;
          digitalWrite(PINLED1, estado_led);
        }
    }
  }
}

Lo que quieres hacer es que cuando se pulse un botón se encienda un led un tiempo X y después se apague, todo esto sin usar delay no?

jafox007:
Lo que quieres hacer es que cuando se pulse un botón se encienda un led un tiempo X y después se apague, todo esto sin usar delay no?

Sip solo eso

Eso cuando pulses guardas los milis en una "variable" y despues vas comparando hasta que "milis >= variable + X" y apagas.

jafox007:
Eso cuando pulses guardas los milis en una "variable" y despues vas comparando hasta que "milis >= variable + X" y apagas.

Ok y si quiero hacer eso con 2 leds, pero que el conteo sea idependiente de cada led, por ejemplo, le doy al pulsador y empieza a contar el primero, y despues le doy otra vez y desde cero cuenta el segundo, y si el primero acabo de contar se apague.

Ve a Documentación y lee en Indice de Tutoriales el item correspondiente a millis() y luego nos dices si aún tienes dudas.

No es exáctamente lo que quieres hacer, pero algo se le parece, mira el post alarma temporizada en un mismo led al presionar un botón y verás que en las respuestas explico un poco cómo desarrollar el programa. Tal vez te sirva de ayuda.

IgnoranteAbsoluto:
No es exáctamente lo que quieres hacer, pero algo se le parece, mira el post alarma temporizada en un mismo led al presionar un botón y verás que en las respuestas explico un poco cómo desarrollar el programa. Tal vez te sirva de ayuda.

Gracias por tu respuestas, ya me estoy estudiando el codigo para entenderlo, pero ¿a que te refieres con que gasta RAM?

#define boton 2
#define led 6
#define leds 3

int estado = 0;
int estadoAN = 0;
int salida = 0;


unsigned long conteo;
int tempOn = 6000;


void setup() {
  // put your setup code here, to run once:
  pinMode(boton, INPUT_PULLUP);
  pinMode(led, OUTPUT);
  pinMode(leds, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  estado = digitalRead(boton);

  if((estado == 1)&&(estadoAN == 0)){
    salida = 1 - salida;
  }

  estadoAN = estado;

  if(salida == 0){
    digitalWrite(led, HIGH);
    digitalWrite(leds, HIGH);
    x = millis();
    Serial.println(x);
    if ((conteo == tempOn)){
      digitalWrite(led, LOW);
      digitalWrite(leds, LOW); 
    }
  }
  else{
    digitalWrite(led, LOW);
    digitalWrite(leds, LOW);
  }
  
}

IgnoranteAbsoluto, mucha gracias, por ese post pude hacer mi propio codigo pero pasa algo, que cuando
millis llega a 6000 que es el tiempo limite que le puse, no se apaga el led, te dejo el codigo para que me lo veas, y si puedes probarlo mejor, gracias y si puedes probarlo o otro que pueda, mejor.

Lo primero de todo disculpa porque el código lo voy a escribir con el teléfono móvil, así que revísalo por si se me escapa algún caracter.

Mi segunda disculpa es que yo programo a mi manera. Me agobia el uso de mil variables o el uso de 10 líneas para algo que se hace en 1. Comprendo que mi código aunque más breve pueda ser difícil de leer a quienes empiezan.

Confío en que te sirva para ver un ejemplo :slight_smile:
Seguro ves algo nuevo.

/*
Indice 0. Pin boton
Indice 1. Pin led
Indice 2. Estado boton
Indice 3. Modo interruptor 
Indice 4. Contador tiempo luz
Indice 5. Contador debounce

Recuerda,  botones con resistencia 10k :) 
*/

unsigned int
btnA[6] ={2,6,0,0,0,0}, 
btnB[6] ={3,7,0,0,0,0} ;

void setup() {
   Serial.begin(9600);
   DDRD =B11110010; //Pin 2 y 3 como INPUT
}

void loop() {
   luz(btnA) ; //usando punteros
   luz(btnB) ;
} 

void luz( int  *arr ) {
   bool val = digitalRead(arr[0]); 
   if(arr[2] != val && millis() >= arr[5] + 150) { //debounce
      arr[2] = val; //valor como pulsador
      if(! arr[2] ) {
         arr[3]  = ! arr[3] ; //valor como interruptor
         if( arr[3] ) {
            arr[4] = millis() ;
         }else{
            Serial. println("El led del pin "+String(arr[1]) +" ha estado encendido " + String(millis() - arr[4]) +" milisegundos");
         } 
      } 
      arr[5] = millis() ; //reiniciar tiempo debounce
   } 
   digitalWrite(arr[1], arr[3]) ; //apagar encender led
}

Saludos.

Shadoaru, no entiendo qué pretendes hacer con la variable conteo, nunca le asignas un valor ni se lo cambias.

Por otro lado, si vas a usar variables para controlar milisegundos, mejor decláralas siempre de tipo unsigned long, para no tener problemas de desbordamientos y con números negativos. Así que declara la variable tempOn como unsigned long en lugar de int.

ArduMyth, muchas gracias por poner tu código y así se pueda ver un claro ejemplo de cómo no se ha de programar. Si ya un código medianamente "legible" es difícil de entender, depurar, mantener y adaptar; el código que tú has puesto está orientado a ofuscar y a no ser nada práctico ya que, por otro lado, derrochas memoria de mala al tratar todas las variables como tipo int. Cuando, si te fijas, en más de un caso con un byte tendrías (e incluso menos, si utilizas los campos de bits).

Pero bien pudiera ser que yo esté equivocado y la mejor manera de programar y enseñar a programar sea "tu estilo". Lo que entonces me pregunto para qué están las estructuras y las clases en un lenguaje de programación orientado a objetos como este, si con un simple array donde se mete todo junto y por igual ya tenemos más que suficiente. Así como la portabilidad que nos permite el entorno de Arduino en donde tenemos la función pinMode que nos abstrae del hardware que estamos usando y así no tener que preocuparnos más que del número asignado al pin según sea un Arduino UNO, un MEGA, un ESP8266 o un ESP32... Total, como nos conocemos al dedillo todos los registros de todos los micros que podemos manejar. Eso sin hablar de lo "fácil" que lo haces con "tu sistema" cuando decides no usar el pin 3, sino el 5 porque el cable me llega mejor a ese pin.

Pero bueno, que no descarto que yo esté equivocado. Y si es así, estoy dispuesto a retirar, entre otras, algunas de mis respuestas. Como la que hice al post Para qué sirve un enum? ya que está visto que lo de tener un código con mucha verborrea no es algo que parezca aconsejable, sino que cuanto más breve mejor.

Aunque, siguiendo tu criterio, no entiendo porqué pones comentarios. ¿No es escribir de más? El preprocesador del compilador es de lo primero que elimina del código antes de compilar.

1 Like

IgnoranteAbsoluto:
ArduMyth, muchas gracias por poner tu código y así se pueda ver un claro ejemplo de cómo no se ha de programar. Si ya un código medianamente "legible" es difícil de entender, depurar, mantener y adaptar; el código que tú has puesto está orientado a ofuscar y a no ser nada práctico ya que, por otro lado, derrochas memoria

Saludos. Curiosamente yo opino que tu código es el que está mal, incompleto, largo, ofuscado, ineficiente y ni sabes hacer lo más básico con millis()... Peeeero en ningún momento te dije que así no se debe programar, no cómo tú.

Si no sabes usar millis() ¿qué potestad tienes criticando a quien sí sólo porque tus conocimientos sean escasos?

Con otro tipo de comentario te habría explicado y me habría "adecuado" más a tu forma de programar.

Sin jaleos te deseo que consigas resolverlo. Por cierto, tema harto repetido en el foro cada semana con mil ejemplos. Vamos que si buscases un poquito...

IgnoranteAbsoluto:
Aunque, siguiendo tu criterio, no entiendo porqué pones comentarios. ¿No es escribir de más? El preprocesador del compilador es de lo primero que elimina del código antes de compilar.

Poner comentarios no es para quien hace el código es para quienes no lo han hecho y puedan guiarse. Ponerlos o no no es obligado, al igual que el resto de reglas que existen en la programación de buenas prácticas. Algo elemental y que es de lo primerito que se estudia. Suerte con tu código. Ánimo.

IgnoranteAbsoluto:
derrochas memoria de mala al tratar todas las variables como tipo int. Cuando, si te fijas, en más de un caso con un byte tendrías (e incluso menos, si utilizas los campos de bits).

Dí que sí. Guarda el valor de millis() en una variable de tipo byte y a ver que depura el IDE...

Saludos ArduMyth. Lo primero de todo es pedirte disculpas porque creo que he sido algo pedante y grosero contigo. No debería de tratar así a alguien nuevo en el foro que trata de ayudar desinteresadamente. Así que ruego sepas disculparme.

Aunque parezca sarcasmo, lo que dije:

IgnoranteAbsoluto:
… muchas gracias por poner tu código y así se pueda ver un claro ejemplo de cómo no se ha de programar.

… lo dije en serio y con toda buena intención (tal vez no con buenos modales). Creo que no se debería de poner ejemplos y explicaciones ofuscadas para aquellos que son nuevos, están aprendiendo y carecen de muchos conocimientos y experiencia en la programación. Además de ser un muy mal hábito el “programar para uno”, sin pensar en “los demás” ya que, en el caso de necesitar ayuda, tu código puede resultar “áspero” y poco legible para otros. Así que, en serio, creo que has puesto un claro ejemplo de cómo no programar.

ArduMyth:
Curiosamente yo opino que tu código es el que está mal, incompleto, largo, ofuscado, ineficiente y ni sabes hacer lo más básico con millis()... Peeeero en ningún momento te dije que así no se debe programar, no cómo tú.

Si no sabes usar millis() ¿qué potestad tienes criticando a quien sí sólo porque tus conocimientos sean escasos?

Con otro tipo de comentario te habría explicado y me habría "adecuado" más a tu forma de programar.

Creo que te has confundido, quien hace la consulta y necesita ayuda no soy yo, sino Shadoaru. Soy yo, y no él, quien ha criticado tu código. No critico la escasez de comentarios, sino el mal uso de nombres de las variables y, sobre todo, el usar un array como único contenedor de datos que son muy diferentes y heterogéneos entre sí. Ya que deberían de ser de tipos diferentes, sería preferible usar una simple estructura con la que poder especificar tipos y nombres diferentes a cada uno de los elementos que conjuntamente controlan lo que deseamos hacer. Precisamente en mi respuesta a Shadoaru le remito a un post donde explico paso a paso cómo hacerlo, así como el recorrido “lógico” que lleva al resultado final.

En cuanto a lo que dije yo, no Shadoaru, de...

IgnoranteAbsoluto:
Aunque, siguiendo tu criterio, no entiendo porqué pones comentarios. ¿No es escribir de más? El preprocesador del compilador es de lo primero que elimina del código antes de compilar.

… confieso que quería ser sarcástico. Mis disculpas.

Respecto a:

ArduMyth:
Dí que sí. Guarda el valor de millis() en una variable de tipo byte y a ver que depura el IDE...

Había dicho claramente:

IgnoranteAbsoluto:
...derrochas memoria de mala al tratar todas las variables como tipo int. Cuando, si te fijas, en más de un caso con un byte tendrías (e incluso menos, si utilizas los campos de bits).

en más de un caso”, no para todos los casos. De hecho, para controlar los “famosos” millis(), es aconsejable utilizar variables de tipo unsigned long, en lugar del tipo unsigned int, ya que con este último apenas se puede “manejar” poco más de seis segundos. Es por eso que, en mi respuesta a Shadoaru, le aconsejo el uso de unsigned long en lugar de int.

Así que, si fuera necesario controlar tiempos de más de seis segundos y medio, ¿tú lo que harías es declarar el array de tipo unsigned long? ¿Consumiendo así el doble de memoria en lugar de cuatro bytes más? (Pasaría de un array de 6 unsigned int, un total de 12 bytes, a un array de 6 unsingned long, un total de 24 bytes por array).

Mi “propuesta rápida” de “correción de estilo” a tu código, sin saber si funciona o no, y sólo sustituyendo el array por una simple estructura, sería esta:

struct Boton {
    byte pinBoton;
    byte pinLed;
    bool estadoBoton : 1;
    bool modoInterruptor : 1;
    unsigned long contadorTiempoLuz;
    unsigned long contadorDebounce;
} botonA = {2, 6, 0, 0, 0, 0},
  botonB = {3, 7, 0, 0, 0, 0};

void setup() {
   Serial.begin(9600);
   DDRD =B11110010; //Pin 2 y 3 como INPUT
}

void loop() {
   luz(botonA) ; // Usamos el paso por referencia
   luz(botonA) ;
}

void luz(Boton &b) { // Usamos el paso por referencia
   bool val = digitalRead(b.pinBoton);
   if(b.estadoBoton != val && (millis() - b.contadorDebounce >= 150)) { //debounce
      b.estadoBoton = val; //valor como pulsador
      if(! b.estadoBoton ) {
         b.modoInterruptor  = ! b.modoInterruptor ; //valor como interruptor
         if( b.modoInterruptor ) {
            b.contadorTiempoLuz = millis() ;
         }else{
            Serial. println("El led del pin "+String(b.pinLed) +" ha estado encendido " + String(millis() - b.contadorTiempoLuz) +" milisegundos");
         }
      }
      b.contadorDebounce = millis() ; //reiniciar tiempo debounce
   }
   digitalWrite(b.pinLed, b.modoInterruptor) ; //apagar encender led
}

Bueno, como no te gusta “escribir de más”, en la función luz en lugar de llamar el parámetro boton lo he llamado simplemente b. Después de todo, cada campo de la estructura nos deja claro de qué se trata. Así que nos podemos tomar esa licencia.

La estructura finalmente tiene un tamaño de 11 bytes (aprovechando los campos de bits para los dos bool). Los tiempos se controlan con unsigned long, así que podrán ser mayores a seis segundos y medio.

¡Ah! Otra cosa. Como he dicho, no sé si tu propuesta funciona o no, sólo he cambiado “el estilo” y corregido una única cosa. Mira que como tú bien dices es un tema harto repetido en el foro cada semana con mil ejemplos... y aún así siempre hay a quien se le escapa el uso correcto de los millis() a la hora de verificar si ha transcurrido el tiempo deseado, como es tu caso. No has de hacerlo así:

millis() >= arr[5] + 150

La forma correcta de hacerlo es así:

millis() - arr[5] >= 150

Busca en los foros o en Google, hay muchas explicaciones del porqué y del problema que se da cuando se desborda el contador de los millis(). Pero supongo que eso tú ya lo sabías y lo tenías más que controlado (nótese el sarcasmo).

Una vez más, ruego disculpes mi pedantería y si he sido grosero contigo. Te animo a que sigas ayudando en el foro. No todo el mundo lo sabe todo, y doy por hecho de que tú sabes mucho, así que espero que lo compartas poco a poco con todos.

Leyendo consultas y respuestas de este foro he descubierto que estaba equivocado en alguna que otra cosa. A la vez que he descubierto y aprendido cosas nuevas.

Los fallos nos pueden servir para aprender, los aciertos sólo nos sirven para confirmarnos lo que creemos saber.

No estoy muy seguro de las normas de este foro pero esto empieza a ser offtopic. Yo planteé una manera. Si no te gusta me alegro y si querías, como dices, ser irónico y pedante de entrada las posteriores disculpas son vacías. Si quieres criticarme al menos hazlo vía privado y no distorciones un ejemplo a un offtopic criticando hasta que ponga comentarios. Ya te has retratado. Be happy.

Lo que has dicho al final de milis()... Tan sólo coge una calculadora o aprende ecuaciones de primer grado.

Podría exponer otras formas partiendo con tu manera de hacer las cosas e igual más cortas, pero creo haber tropezado con un usuario un poco sobrado vía internet.

No confundas el número de post en un foro con otras cuestiones.

Saludos y fin. Evita esas respuestas conmigo cuando escriba algo. Si no te gusta no sé, ponte con otro usuario que aguante tus formas. Sólo quise exponer un ejemplo, todo lo demás desvía la duda del autor.

Y lo del desbordamiento de millis... Que sí... 50 días con el arduino encendido y más de lo mismo. Repito... No deduzcas a razón del número de post en un foro...

Más te leo y más infantil pareces. Te disculpas, explicas q eres irónico, te vuelves a burlar, animas a que colabore, y vuelves a faltar el respeto... No sé tu edad pero me das vergüenza ajena y yo no soy irónico ni pienso dejar el foro por gente así.

ArduMyth:
Más te leo y más infantil pareces. Te disculpas, explicas q eres irónico, te vuelves a burlar, animas a que colabore, y vuelves a faltar el respeto... No sé tu edad pero me das vergüenza ajena y yo no soy irónico ni pienso dejar el foro por gente así.

Tienes razón. :confused:

Creen otro hilo y debatimos NUEVAMENTE (es uno de los temas mas debatibles) el tema millis() según el enfoque de IgnoranteAbsoluto pero estoy de acuerdo con ArduMyth que ya ha sido algo mas de la cuenta, aunque yo también me excedo y no debería.
Limitemos el hilo a lo que el tema requiere.