En este momento estás viendo Como usar la función millis y delay en Arduino

Como usar la función millis y delay en Arduino

Arduino cuenta con un conjunto básico de funciones para el manejo de tiempo, y estas son: millis, micros, delay y  delayMicroseconds.  Aprender a usarlas correctamente es muy importante, pues no todos los programas funcionan bien usando solo la función delay, de hecho algunos programas no es posible realizarlos sin usar la función millis para crear temporizadores que hagan un uso eficiente del tiempo.

Comencemos por describir estas funciones para controlar el tiempo.

La función millis

Devuelve el número de milisegundos (ms) desde que la placa Arduino empezó a ejecutar el sketch (partiendo desde cero). Este conteo se reiniciara aproximadamente después de 50 días (cuando su valor supere el máximo permitido por su tipo de variable, que es “unsigned long”). No tiene parámetros.

Y la función micros

Devuelve el número de microsegundos (μs) desde que la placa Arduino empezó a ejecutar el sketch. Este número (de tipo unsigned long) se reseteará a cero aproximadamente después de 70 minutos. Esta instrucción tiene una resolución de 4 μs (es decir, que el valor retornado es siempre un múltiplo de cuatro). Recordar que 1.000 μs es un milisegundo y por tanto, .1000.000 μs es un segundo. No tiene parámetros.

Ejemplo 1 – Conteo de tiempo en microsegundos

unsigned long time; //Declara un variable del mismo tipo que la que devuelve micros()
void setup(){
    Serial.begin(9600); //Inicializa la comunicación serial
}
void loop(){
    time = micros(); //Consulta los microsegundos desde que se inició el sketch
    Serial.println(time); //Imprime el valor en el monitor serial
    delay(1000); //Espera 1 segundo
}

La espera es con delay()

Pausa el sketch durante la cantidad de milisegundos especificados como parámetro (de tipo unsigned long). No tiene valor de retorno.

Y la espera con delayMicroseconds()

Pausa el sketch durante la cantidad de microsegundos especificados como parámetro (de tipo unsigned long) . Actualmente el máximo valor que se puede utilizar con precisión es de 16383. Para esperas mayores que esta, se recomienda usar la instrucción delay(). El mínimo valor que se puede utilizar con precisión es de 3 μs. No tiene valor de retorno.

Ejemplo 2 – Como funciona millis()

unsigned long inicio, fin, transcurrido;  // Declaramos 3 variables
void setup(){
   Serial.begin(9600);  //Inicializa la comunicación serial
}
void loop(){
   inicio=millis();  //Consulta los milisegundos desde que se inició el sketch
   delay(1000);  //espera un segundo
   fin=millis();  //Consulta los milisegundos desde que se inició el sketch
   transcurrido=fin-inicio;  //Calcula el tiempo desde la última lectura
   Serial.println(transcurrido);  //Imprime el valor en el monitor serial
   delay(500);  //espera 0.5 segundos
}

Las funciones delay() y delayMicroseconds() como lo mencionamos anteriormente, ponen en pausa el sketch, lo cual puede resultar un problema cuando tenemos otras tareas que atender, y este problema se ve acentuado cuando los tiempos de espera son largos. Para resolver esto es recomendable usar la función millis() para controlar esos tiempos. En el siguiente ejemplo veremos como hacer parpadear un led usando millis(). Y podemos usar una programación similar para atender eventos periódicos.

Si necesitas repasar como utilizar la función if o seleccionar el tipo correcto de variable puedes mirar los siguientes post:

Ejemplo 3 – Hacer parpadear un led con millis()

int estadoLed;  //guarda el estado del led (encendido o apagado)
int periodo = 100;  // tiempo que esta el LED en alto y bajo
unsigned long tiempoAnterior = 0;  //guarda tiempo de referencia para comparar
void setup() {
    pinMode(13,OUTPUT);  //configura la salida
}
void loop() {
  if(millis()-tiempoAnterior>=periodo){  //si ha transcurrido el periodo programado
    estadoLed=!estadoLed;  //cambia el estado del led cada 100ms
    digitalWrite(13,estadoLed);  //actualiza el estado del led
    tiempoAnterior=millis();  //guarda el tiempo actual como referencia
    }
}

En el siguiente ejemplo tenemos el caso de un periodo de tiempo que necesitamos medir pero que no se repite, para probarlo conectamos un pulsador al pin 7 y a tierra y, usaremos el LED del pin 13 para ver su funcionamiento. Cada vez que presionemos el pulsador, el LED del pin 13 se apagara por 3 segundos (al iniciar el programa el LED esta apagado, se encenderá tres segundos después de la primera vez que lo pulse).

Ejemplo 4 – Contar un periodo de tiempo con millis()

int periodo = 3000;  // tiempo para que el led se encienda
byte temp = 0; //estado del temporizador, 1= activo 0= inactivo
unsigned long tiempoAnterior = 0;  //guarda tiempo de referencia para comparar
void setup() {
    pinMode(13,OUTPUT);  //configura la salida
    //tengo un pulsador conectado al pin 7 usando la resistencia pull-up
    //cuando lo presiono leo cero
    pinMode(7,INPUT_PULLUP);  //configura la entrada con resistencia pull-up
}
void loop() {
  if (digitalRead(7)==0) {  //si el pulsador fue presionado
      tiempoAnterior=millis();  //guarda el tiempo actual como referencia
      temp = 1;  //indica que esta activo el temporizador
      digitalWrite(13,LOW);  //apaga el LED
      }
  if((millis()-tiempoAnterior>=periodo)&&temp==1){  //si ha transcurrido el periodo programado
      digitalWrite(13,HIGH);  //enciendo el LED
      temp = 0;  //y desactivo el temporizador
      }
}

En este ejemplo tenemos el caso de un periodo de tiempo que necesitamos medir pero que no se repite, para probarlo conectamos un pulsador al pin 7 y a tierra y, usaremos el LED del pin 13 para ver su funcionamiento. Cada vez que presionemos el pulsador, el LED del pin 13 se encenderá por 5 segundos (al iniciar el programa el LED esta apagado, se encenderá cinco segundos después de la primera vez que lo pulse). Adicionalmente tenemos un botón de pausa, mientras lo tengamos presionado el temporizado no esta activo, cuando soltamos el pulsador el conteo se reanuda donde había quedado.

Ejemplo 5 – Contar un periodo de tiempo con millis() y un botón de pausa

int periodo = 5000;  // tiempo para que el led se encienda
byte temp = 0; //estado del temporizador, 1= activo 0= inactivo
unsigned long tiempoAnterior = 0;  //guarda tiempo de referencia para comparar
unsigned long tiempoTranscurrido = 0;  //guarda el tiempo que resta por contar cuando presionamos la pausa
int pulsadorPausa = 1;
int pulsadorPausaAnterior = 1;
void setup() {
    pinMode(13,OUTPUT);  //configura la salida
    //tengo pulsadores conectados a los pines 2 y 7 usando la resistencia pull-up
    //cuando los presiono leo cero
    pinMode(7,INPUT_PULLUP);  //Pulsador para iniciar el conteo
    pinMode(2,INPUT_PULLUP);  //Pulsador de pausa
}
void loop() {
  pulsadorPausa = digitalRead(2);
  
  if (digitalRead(7)==0) {  //si el pulsador de inicio fue presionado
      tiempoAnterior=millis();  //guarda el tiempo actual como referencia
      temp = 1;  //indica que esta activo el temporizador
      digitalWrite(13,HIGH);  //enciende el LED
      }
   if ((pulsadorPausa != pulsadorPausaAnterior)&&temp==1) {
    // detecto que el pulsador fue presionado o liberado cuando el temporizador esta activo
    if (pulsadorPausa == LOW) { //detecto que el pulsador fue presionado
      tiempoTranscurrido = millis()-tiempoAnterior; //es el tiempo que resta por contar
      temp=0; //desactivo el temporizador mientras dure la pausa
      }
     }
   if ((pulsadorPausa != pulsadorPausaAnterior)) {
    // detecto que el pulsador fue presionado o liberado cuando el temporizador esta activo
    if (pulsadorPausa == HIGH) { //detecto que el pulsador fue liberado
      tiempoAnterior =  millis() - tiempoTranscurrido; //es el tiempo que transcurrio antes de la pausa
      temp=1;  //activo el temporizador al terminar la pausa
      }
     }    
  if((millis()-tiempoAnterior>=periodo)&&temp==1){  //si ha transcurrido el periodo programado
      digitalWrite(13,LOW);  //apago el LED
      temp = 0;  //y desactivo el temporizador
      }
      pulsadorPausaAnterior = pulsadorPausa;  //actualiza el estado del pulsador de pausa
}

En el siguiente ejemplo veremos como hacer parpadear un led usando millis(), pero en este caso el tiempo de encendido y apagado del led son diferentes.  Por lo que necesitamos usar dos contadores de tiempo y activarlos secuencialmente. Si necesitases mas de un led, solo tienes que duplicar el programa y las variables.

Ejemplo 6 – Hacer parpadear un led con millis() con tiempos de apagado y encendido diferentes

boolean estadoLed = true;  //guarda el estado del led (encendido o apagado)
int intervaloEncendido = 300;  // tiempo que esta encendido el led
int IntervaloApagado = 800;  // tiempo que esta apagado el led
unsigned long tiempoAnteriorEncendido = 0;  //guarda tiempo de referencia para comparar
unsigned long tiempoAnteriorApagado = 0;  //guarda tiempo de referencia para comparar

void setup() {
    pinMode(13,OUTPUT);  //configura el pin como salida
    digitalWrite(13,estadoLed);  //enciende el led
}

void loop() {
  if((millis()-tiempoAnteriorEncendido>=intervaloEncendido)&&estadoLed==true){  //si ha transcurrido el periodo programado
    estadoLed=false;  //actualizo la variable para apagar el led
    digitalWrite(13,estadoLed);  //apago el led
    tiempoAnteriorApagado=millis();  //guarda el tiempo actual para comenzar a contar el tiempo apagado
  }
  if((millis()-tiempoAnteriorApagado>=IntervaloApagado)&&estadoLed==false){  //si ha transcurrido el periodo programado
    estadoLed=true;  //actualizo la variable para encender el led
    digitalWrite(13,estadoLed);  //enciendo el led
    tiempoAnteriorEncendido=millis();  //guarda el tiempo actual para comenzar a contar el tiempo encendido
  }
}

A continuación te presento el vídeo de explicación del programa, este vídeo forma parte de mi curso online «Como usar millis en Arduino en menos de 90 minutos» actualmente disponible en Udemy, donde muestro muchos más ejemplos del uso de esta función.

Ejercicios

Para realizar algunos ejercicios es necesario que montemos el siguiente circuito:

Ejercicio 1: Medir tiempo

Medir cuanto tiempo le toma al microcontrolador ejecutar diferentes tipos de instrucciones. Y mostrar el resultado en el monitor serial.

Ejercicio 2: Dos leds intermitentes

Hacer que un led parpadee, que se encienda por 600ms y este apagado por 600ms, y un segundo led también parpadeara pero estará encendido por 300ms, usando la función delay().

Ejercicio 3: Led de tiempo programable

Hacer que un led encienda y apague a una velocidad variable, (entre 0.2s y 2s) usando un potenciómetro para ajustar esta velocidad.

Ejercicio 4: Dos leds intermitentes con millis

Hacer que un led parpadee, que se encienda por 600ms y este apagado por 600ms, y un segundo led también parpadeara pero estará encendido por 300ms y apagado por 300ms, usando la función millis().

Esta entrada tiene 10 comentarios

  1. Armando Pacher

    Deseo agradecerte por los videos sobre las funciones de control de tiempo que acabo de ver y felicitarte por la claridad de tus exposiciones, lo mismo por los programas fuente que facilitaste.. Es la primera vez que comprendo la función millis() y su utilización, después de haber deambulado sin éxito en varios tutoriales. Un fraternal abrazo desde Argentina.

    1. Fidias Rodriguez

      Gracias a ti Armando por tan fraternal saludo. Un abrazo.

    2. Luis

      Buena pagina muy agradecido por lo que enseña aqui tengo una pregunta sobre el ejemplo 6 de encender un led con millis tiempo de apagado y encendido diferente como podria agregarle a ese codigo para que ahora funcione con un boton

      1. Fidias Rodriguez

        Hola Luis, tendrías que hacerlo similar al ejemplo 4, cuando leas el pulsador actualizas tiempo anterior y comienzas a contar.
        Saludos,

        1. Luis

          saludos master ,me podria poner un pequeño ejemplo no entiendo muy bien necesito que el boton arranque el tiempo de encendido y apagado

  2. Jesus

    Espectacular, los ejemplos.
    Pero necesitaría que mi led no se encendiera si el pulso es inferior a 1seg, creo que están fácil que por eso no encuentro ejemplos, pero par mi es un imposible. Garcias

  3. Jim Ortega

    Buenas tardes quiero usar la función Millis, y leer la entrada serial(19), de un Tags, en un circuito RFID, el problema es que a veces lee la identificación del TAGs (resultado ok), y a veces la lectura me da otro resultado (resultado diferente), si uso la función delay(20) siempre me funciona, necesito usar millis porque ademas quiero enviar información a un aro leds por un pin de salida (pin 18), de antemano muchas gracias por tu respuesta.

  4. Miguel

    Muchas gracias por tu tiempo y tu trabajo, me fue de gran ayuda

  5. Juan

    Buenas tardes soy nuevo en esto, pero me he dado cuenta de que el codigo del ejemplo 6 hace lo opuesto en un esp8266, en un nano me corre bien como dice pero en en un Esp8266 en vez de encender se apaga y en vez de apagar se enciende.

  6. larva

    Eres bueno!!!
    Muchas gracias!!!!

Deja una respuesta