Arduino Delay [Tutorial]

En este tutorial aprenderá a usar correctamente la función delay() para agregar un retardo entre 2 acciones en sus programas Arduino. Luego, descubrirá por qué usar delay() a menudo no es una buena idea cuando desea escalar sus programas, y cómo solucionarlo.

¡Muy bien, comencemos!

Tabla de Contenidos

¿Por qué necesita retrasos en sus programas Arduino?

Bueno, un programa Arduino depende mucho de entradas/salidas externas para funcionar.

Tomando un ejemplo simple: es posible que desee monitorear el estado de un botón pulsador 100 veces por segundo, o hacer que un LED parpadee cada 0,5 segundos.

Ahora, ¿cómo puedes lograr eso? Un programa Arduino funciona así:

  • Primero, la función setup() se ejecuta una vez.
  • Luego, la función loop() se ejecuta una y otra vez, hasta que apaga su Arduino.

Cualquier programa que escriba se ejecutará a toda velocidad. Por lo tanto, si está haciendo que un LED parpadee en su código, lo que sucederá es que el LED parpadeará a una velocidad muy alta (al menos miles de veces por segundo).

¿Está aprendiendo a usar Arduino para construir sus propios proyectos?

Echa un vistazo a Arduino Para principiantes y aprende paso a paso.

Si desea controlar el tiempo, es decir, asegúrese de que el LED parpadee solo cada 0,5 segundos y no a toda velocidad, debe agregar algún retraso en su código.

Implementando Arduino delay en su código

La función Arduino delay ()

Aquí hay un código para hacer que un LED parpadee (aquí elegimos el LED incorporado, sin necesidad de agregar ningún LED externo) cada 0,5 segundos: este es uno de los ejemplos más comunes que verá si comienza con Arduino.

#define LED_PIN 13void setup() { pinMode(LED_PIN, OUTPUT);}void loop() { digitalWrite(LED_PIN, HIGH); delay(500); digitalWrite(LED_PIN, LOW); delay(500);}

Entonces, ¿cómo funciona este código?

Primero usa un » definir «para no tener que codificar el número» 13 » varias veces en su código y hace que su programa sea más legible.

Configura el modo del pin para que SALGA con la función pinMode().

Luego, en la función loop(), usted:

  1. Encienda el LED
  2. Use delay(500) para hacer que el programa duerma durante 500 milisegundos, o 0,5 segundos
  3. Apague el LED
  4. Use delay(500) para hacer que el programa duerma nuevamente durante 0,5 segundos
  5. y vuelva al paso 1, porque la función loop() se sigue ejecutando una y otra vez.

La función delay() espera que dé un número de milisegundos, no segundos, para dormir. Entonces, si piensas en segundos, multiplica el número por 1000 y tendrás el valor que necesitas.

Haga un retraso de Arduino de 1 minuto

Si desea que su Arduino duerma durante 1 minuto o varios minutos, entonces es bastante fácil.

Tome el número de minutos, multiplíquelo por 60 para obtener el número de segundos, y luego multiplíquelo por 1000 para obtener el número de milisegundos.

Ej: delay(3 * 60 * 1000); hará que el programa duerma durante 3 minutos.

La función Arduino delayMicroseconds ()

Si necesita ser más preciso, puede que tenga que usar la función delayMicroseconds(). Con delayMicroseconds() puede proporcionar un número de microsegundos para dormir. La duración mínima para delay() es de 1 milisegundo, por lo que si necesita dormir solo 400 microsegundos, aquí tiene una nueva solución.

Esta función puede ser muy útil cuando se comunica con algunos componentes de hardware. Por ejemplo, Arduino necesita enviar algunos datos al componente y luego leer alguna respuesta. Digamos que el componente necesita 6 microsegundos para procesar la solicitud y entregar datos precisos.

Entonces en su programa puede tener algo como esto:

...void loop() { // send data to component delayMicroseconds(6); // reach out to component again to read data}

Retardo sin bloqueo: por qué debería evitar usar delay()

Así que, ahora que entiende qué es un retardo en Arduino y cómo implementarlo con delay() y delayMicroseconds(), veamos cómo usar la funcionalidad de retardo, pero sin esas funciones.

¿Por qué?

Cuando use delay(), la ejecución de su programa se detendrá y solo se reanudará después de que finalice el retraso.

Esto está bien si solo tiene una acción que hacer-ejemplo: parpadee con un solo LED, pero ¿qué pasa si necesita cuidar varios componentes de hardware o comunicarse con otros dispositivos, como placas Arduino o su propia computadora?

Usando el ejemplo anterior, ¿cómo podría hacer que un LED parpadee cada 0,5 segundos y otro parpadee cada 0,8 segundos?

En ese caso, se quedará atascado bastante rápido. Si aún desea usar delay(), puede encontrar una solución en la que use retrasos más cortos entre varias acciones, pero esto hará que su programa sea más complicado cada vez que agregue una nueva acción.

La solución para eso es simplemente monitorear el tiempo sin usar la función delay(), básicamente para encontrar una manera de reproducir el comportamiento de delay() sin usarlo.

Ejemplo de código-Arduino delay without delay()

Reescribamos nuestro ejemplo de LED parpadeante sin usar delay().

#define LED_PIN 13unsigned int lastTimeLedBlinked = millis();unsigned int delayBetweenBlink = 500;byte ledState = LOW;void setup() { pinMode(LED_PIN, OUTPUT);}void loop() { unsigned int timeNow = millis(); if (timeNow - lastTimeLedBlinked > delayBetweenBlink) { if (ledState == LOW) { ledState = HIGH; } else { ledState = LOW; } digitalWrite(LED_PIN, ledState); lastTimeLedBlinked = timeNow; }}

Analicemos este código línea por línea.

Inicialización

#define LED_PIN 13unsigned int lastTimeLedBlinked = millis();unsigned int delayBetweenBlink = 500;byte ledState = LOW;

Primero, inicializa 3 variables en el ámbito global:

  • lastTimeLedBlinked: esta variable se utilizará para almacenar la última vez que parpadeó el LED. Básicamente, cada vez que hagamos que el LED parpadee, actualizaremos esta variable con el tiempo actual, usando la función millis ().
  • delayBetweenBlink: este es el tiempo que desea esperar entre 2 acciones, aquí la acción es parpadear el LED.
  • Estado de LED: necesitaremos almacenar el estado actual del LED (ALTO o BAJO) para que podamos saber cuál era el estado anterior y tomar medidas en consecuencia.

¿Por qué en el ámbito global? Bueno, lo que planeamos hacer es actualizar esas variables en la función loop() y acceder a ellas de nuevo la próxima vez que entremos en la función loop(). Si creamos las variables dentro de loop(), las variables serán variables locales y, por lo tanto, se destruirán cuando salga de la función loop(). Por lo tanto, la próxima vez que se vuelva a llamar a loop(), se perderán todos los valores y volverá a crear variables sin ningún valor anterior dentro. Aquí, al crear las variables fuera de la función, podemos hacerlas «sobrevivir» y mantener su valor cada vez que ingresamos loop().

Implementando la funcionalidad de retardo de Arduino en la función de bucle

Ahora, veamos qué sucede en la función loop().

void loop() { unsigned int timeNow = millis();

Primero, lee la hora actual con la función millis().

 if (timeNow - lastTimeLedBlinked > delayBetweenBlink) {

Y ahora compara la hora actual que acaba de leer con la hora anterior en que parpadeó el LED. Si ha pasado suficiente tiempo (más que el valor almacenado en delayBetweenBlink), significa que puede ingresar if().

Esta estructura de código, que lee la hora y la compara con la hora anterior en la que realizó una acción, es la forma de reemplazar la función delay(). Básicamente estás calculando una duración aquí. Y como puede ver, significa que su programa contiene más líneas para una aplicación simple, pero le da mucho más control y es mucho más escalable.

Entonces, ¿qué pasará? Bueno, el loop() se seguirá ejecutando a toda velocidad. Cada vez, su programa comprobará si ha pasado suficiente tiempo. Si no, entonces loop() termina aquí, porque no entrará en la estructura if.

Y, cuando ha pasado el tiempo suficiente, ingresamos el if().

Ejecutando la acción

 if (ledState == LOW) { ledState = HIGH; } else { ledState = LOW; } digitalWrite(LED_PIN, ledState);

OK, acabas de ingresar el if(), y aquí harás cualquier acción que necesites hacer.

Aquí hacemos que el LED parpadee. Y debido a que no podemos saber directamente cuál era el estado anterior para el LED (ya que hemos ingresado el loop() muchas veces y hemos perdido todas las variables locales creadas dentro), obtenemos ese estado de una variable global.

Lo que hacemos con esta variable global es simple: si era BAJA, la establecemos en ALTA, y si era ALTA, la establecemos en BAJA. Y luego, por supuesto, actualizamos el estado físico del LED en consecuencia, con digitalWrite().

 lastTimeLedBlinked = timeNow; }}

Finalmente, y esto es súper importante, guardamos el tiempo actual como la última vez que parpadeamos el LED. Si no hacemos eso, el programa parpadeará el LED a toda velocidad porque la condición dentro del if() siempre será verdadera.

Al establecer la hora anterior a la hora actual, «restablecemos el temporizador».

Por lo tanto, en ese ejemplo, el if() solo se ingresará cada 500 milisegundos, o 0,5 segundos.

Y ahora esto es genial porque su programa no se detiene, por lo que puede continuar ejecutando diferentes acciones independientes mientras sigue «esperando» para parpadear el LED.

2 acciones «al mismo tiempo»

Por ejemplo, supongamos que desea parpadear un LED cada 0.5 segundos, y otro cada 0,8 segundos.

#define LED_1_PIN 13#define LED_2_PIN 10unsigned int lastTimeLed1Blinked = millis();unsigned int delayBetweenBlink1 = 500;byte led1State = LOW;unsigned int lastTimeLed2Blinked = millis();unsigned int delayBetweenBlink2 = 800;byte led2State = LOW;void setup() { pinMode(LED_1_PIN, OUTPUT); pinMode(LED_2_PIN, OUTPUT);}void loop() { unsigned int timeNow = millis(); // Action 1 - Blink LED 1 if (timeNow - lastTimeLed1Blinked > delayBetweenBlink1) { if (led1State == LOW) { led1State = HIGH; } else { led1State = LOW; } digitalWrite(LED_1_PIN, led1State); lastTimeLed1Blinked = timeNow; } // Action 2 - Blink LED 2 if (timeNow - lastTimeLed2Blinked > delayBetweenBlink2) { if (led2State == LOW) { led2State = HIGH; } else { led2State = LOW; } digitalWrite(LED_2_PIN, led2State); lastTimeLed2Blinked = timeNow; }}

Como puede ver, repetimos la estructura de código para la segunda acción que agregamos. ¡Y ambas acciones no se molestarán mutuamente!

Recapitule

Si desea realizar un retraso de Arduino sin usar delay():

  1. Cree una variable global para almacenar la última vez que realizó una acción específica.
  2. Cree otra variable global para almacenar la duración que desee entre 2 acciones.
  3. En la función loop(), lea la hora actual con millis().
  4. Justo después de eso, use una estructura if y use la condición (timeNow - lastTimeActionWasExecuted > delayBetweenActions).
  5. Una vez que haya ingresado el if(), realice la acción.
  6. Y aún en if(), almacene la hora actual como la hora anterior.

Puede repetir esos pasos para cada acción para la que necesite un retraso Arduino.

Cuando está bien usar delay() y delayMicroseconds()

Hay ocasiones específicas en las que usar delay() en su código sigue estando bien.

Aquí hay 2 de esos:

  • Necesita inicializar un componente durante la configuración de su programa, y este componente necesita algo de tiempo para inicializarse, por ejemplo, 1,5 segundos. En este caso, usar delay(1500) en su función setup() está perfectamente bien. Básicamente, cualquier delay() en la función setup() de su programa Arduino no será un problema.
  • Como se explica en la parte delayMicroseconds(), debe esperar unos microsegundos (¡no milisegundos!) al comunicarse con un componente externo. Si encuentra que usar delayMicroseconds() con un número pequeño (por ejemplo, 10) no perturba el resto de su programa, aún puede usarlo sin tener que preocuparse demasiado. Pero considéralo una excepción, no la regla común.

Conclusión: Use Arduino delay () con cuidado

Debido a la naturaleza de los programas Arduino, a menudo necesitará agregar retrasos en su código, para que pueda elegir cuándo ejecutar algunas acciones y con qué frecuencia desea ejecutarlas.

Las funciones delay() y delayMicroseconds() son funciones muy simples de usar y se agregaron al lenguaje Arduino para que los principiantes completos pudieran comenzar con algo simple.

Sin embargo, como vio en este tutorial, usar delay() puede hacer que se quede atascado muy rápidamente. Por lo tanto, es mejor entender primero por qué lo necesita, cómo usarlo y luego cómo obtener el mismo comportamiento sin usar la función Arduino delay() directamente.

Una vez que haya entendido la estructura de código para deshacerse de delay(), podrá mejorar mucho sus programas Arduino, y la multitarea se volverá bastante fácil.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.