Arduino multitarea y la gestión del tiempo

Prueba de Arduino para trabajar en multitarea con milis

No soy un experto en Arduino, a pesar de tener la placa desde hace tiempo no he investigado casi. Las veces que lo he usado ha sido como herramienta copiando y pegando código ya creado pero sin mucho interés por aprender realmente como funciona sino simplemente con la intención de hacer que funcione y me resulte útil. Estas Navidades tuneé un poco el Belén con unos leds y un sensor de ultrasonidos HC-SR04. Y me detuve a observar que había que hacer.

Tan sólo quería hacer cosas diferentes con dos leds a partir de una misma señal. Ups. Rápidamente tropecé con la que me parece que será una de las primeras limitaciones que te encuentras cuando empiezas a trastear con Arduino. Y no es necesario complicarlo mucho. Hablo tan sólo de unos leds te das cuenta de que no puedes hacer correctamente lo que quieres.

Vamos a dejarlo claro desde el principio en Arduino la multitarea no existe, no se pueden procesar dos tareas en paralelo. Pero existen técnicas para hacer llamadas tan rápido que parece que trabajan a la vez.

Cuento el caso con más detalle. En Navidad monté un Belén y quería  que se encendieran ciertas luces del Nacimiento cuando se acercaran mis hijas. Nada complicado. Sólo quería que dos ramas de luces led funcionaran de forma diferente ante los valores de un sensor de proximidad.

Quería que cuando alguien se acercara a menos de 10 cm

  • Una de las ramas de luces que iría a las estrellas se quedara encendida 10 segundos
  • Que la otra que iría dentro de las casas se quedara encendida 10 segundos pero desde que se separan del belén.

¿Sencillo no? pues esto puede causarte grandes problemas. Porque Arduino no es capaz trabajar la multitarea, él ejecuta una orden después de otra.

 

circuito montaje leds parpadeando y ultrasonidos en multitarea

He hecho un montaje con el sensor de ultrasonidos HC-SR04 y 2 leds, cada uno equivaldría una rama del Belén. La primera parte no tiene mucha gracia, ya que es configurar el setup y el funcionamiento del sensor de ultrasonidos en el LOOP, pero esto lo puedes encontrar en miles de sitios. Igual otro día si indago más hago un especial, de momento aquí tienes (siento no poner créditos, pero no recuerdo de donde lo cogí)

Código HC-SR04 en Arduino


Con esto se irá revisando y almacenando la distancia que mide el sensor de ultrasonido

Solución funcionamiento LEDS

Lo primero que se nos viene a la mente es empezar a meter delays. No sé por qué pero todos los principiantes pensamos en delay() y eso limita muchísimo las opciones porque mientras usas delay() la placa no sigue trabajando y por tanto ya no puedes hacer nada más en ese tiempo de suspensión. La solución es el uso de millis()

Aquí encontré una solución, sencillota a base de if y de contadores. Como decía un profesor mío, cualquier cosa se puede programar con muchos if seguidos. Pero claro no es muy elegante la verdad.


Lo que pretende este código es eso que Arduino vaya ejecutando constantemente esos tres if de forma que pasará tan rápido por ellos que parece que esté haciendo varias cosas al mismo tiempo. Pero como ya sabemos sigue ejecutando sentencias de una en una.

Una vez medida la distancia y almacenada en la variable distancia, se evaluarían los if:

  • El primero comprueba si la distancia es menor de los 10 centímetro deseados. Si es así encendemos los dos LEDS y empezamos a contar el tiempo con milis()
  • y pasaríamos al segundo if  para la distancia mayor de 10 cm. Si cumple, calculamos el tiempo que ha pasado y desactivamos el led 1 que sólo dependía de la distancia.
  • Pasaríamos al tercer if donde comprobamos si ha pasado más de 10 segundos desde que se activó el contador, y en caso de ser así apaga el pin 2
  • Y así sigue el bucle. Una y otra vez.

Al final y aunque la solución funcionaba tenía claro que este problema seguro que lo había tenido mucha gente y que tenía que haber una solución más ortodoxa. Me puse a buscar y encontré una buena (que seguro que no la única) de la mano de los chicos de Adafruit y la programación orientada a objetos. Consiste en la creación de objetos con clases definidas para hacer rápidas llamadas y no tener que repetir el código cientos de veces en nuestro programa.

Que al final es “lo mismo” que mi solución con de if + contadores pero mucho más elegante y que proporciona un código mucho más legible y mucho más eficiente.

La gestión de la multitarea lleva irremediablemente a la gestión del tiempo en Arduino. En un principio esto no entraba en el artículo pero creo que es muy interesante.

Arduino y las funciones de tiempo

Como ya he comentado creo que existe una gran dependencia con delay() ,posiblemente porque la gente que empieza ve esta función en todos los ejemplos que se suelen poner desde el blink a cualquier semáforo o cualquier manipulación de encendido y apagado de LEDS.

Delay tiene un problema bien grande y es que cuando hacemos una llamada a delay() por una cantidad de tiempo todo se para. La placa no lee ningún sensor, ni sigue ejecutando sentencias, ni hace nada de nada, tan sólo esperar a que pase el tiempo que le hemos dicho y claro si queremos usar la placa para más de una cosa al mismo tiempo esto no es viable.

Tendremos que echarle un vistazo a millis() incluso a delayMicroseconds() Y también tenemos micros() que nos devuelve el número de microsegundos desde que se ha empezado a ejecutar el programa

Blink sin delay

Un ejemplo chulo para ver como funciona es ejecutar el mítico Blink pero sin el delay. La principal diferencia consiste en olvidarnos de la función delay()  usar milis() para poder contar el tiempo transcurrido entre operaciones.

Recibe ofertas y recursos sobre DIY en nuestro canal de Telegram

¿Quieres colaborar con el proyecto?
¿Te hemos ayudado o te gusta lo que escribimos?Haz una donación para poder soportar los gastos del blog, dedicarle más tiempo y comprar el material necesario para nuevos artículos
Dirección Bitcoin
1C5j3QJgZbSfZno1mbnKBUnXBGjvWLi79x
1C5j3QJgZbSfZno1mbnKBUnXBGjvWLi79x
Paypal
Te puede interesar

Categorías

Arduino

Nacho Morato

Ingeniero Industrial. Apasionado del DIY o como hacer de toda la vida.

2 comentarios

  1.   Leandro Albero dijo

    Conocer la existencia de los “interrupts” en arduino puede ayudarte a implementar programas con cierto grado de multitarea.

    1.    Nacho Morato dijo

      Hola Leandro, muchas gracias. No conozco el tema de los interrupts. Voy a investigar a ver :)

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *