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().
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.
Gracias a ti Armando por tan fraternal saludo. Un abrazo.
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
Hola Luis, tendrías que hacerlo similar al ejemplo 4, cuando leas el pulsador actualizas tiempo anterior y comienzas a contar.
Saludos,
saludos master ,me podria poner un pequeño ejemplo no entiendo muy bien necesito que el boton arranque el tiempo de encendido y apagado
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
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.
Muchas gracias por tu tiempo y tu trabajo, me fue de gran ayuda
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.
Eres bueno!!!
Muchas gracias!!!!