Usando hilos en Arduino

Uno de los problemas al empezar a programar con Arduino es acostumbrarse a la estructura del programa, principalmente del método loop() que se ejecuta continuamente; muchos de los ejemplos en Internet hacen uso del método delay() o alguna de sus variantes para poder tener control sobre la ejecución, pero esta técnica bloquea la ejecución de toda instrucción y nada más puede ocurrir, si quieren hacer múltiples tareas en paralelo esto no es una buena opción.

En mi artículo anterior mostré un ejemplo muy fácil de como leer desde un keypad basándome en esta librería; si leen la referencia verán que también estaba disponible una función llamada waitForKey() que podría haber simplificado mucho el código ya que eliminaría la necesidad de los ciclos while() , yo decidí no usar esta función a propósito para que pudiera jugar bien con otras acciones que estuvieran ejecutándose en paralelo, esto normalmente se conoce como hilos o threads; la plataforma Arduino no soporta thread reales pero este funcionamiento puede ser emulado con algunas técnicas, una de las más sencillas es la que provee a librería Thread.

Este es un pequeño ejemplo introductorio; supongamos que necesitamos un led intermitente a un intervalo de 1 segundo, normalmente escribiríamos un fragmento de código como el siguiente:

 void loop() {
    blink();
    delay(1000);
}
 
void blink() {
   digitalWrite(PIN, !digitalRead(5));
}

Mientras no tengamos que realizar otra tarea, nuestro ejemplo funcionará sin problemas pero al agregar más cosas, rápidamente veremos que nuestro led ya no se comporta como esperamos, por ejemplo, si queremos leer al mismo tiempo de nuestro keypad; acá es donde la case Thread entra en acción, primero es necesario crear y configurar nuestro Thread:

 #include <Thread.h>
 
Thread thrBlink = Thread();
 
void setup() {
  pinMode(5, OUTPUT);
 digitalWrite(5, HIGH);
  
    thrBlink.enabled = true;
    thrBlink.setInterval(1000);
 thrBlink.onRun(blink);
}
 
void blink() {
 digitalWrite(5, !digitalRead(5));
}

Una vez configurado sólo debemos colocar llamadas dentro de nuestro método loop para que verificar si el código debe correr o no, la llamada se ejecutará pero no bloqueará el resto del programa, el código requiere que primero verifiquemos si la tarea debe correr y de ser así, luego la ejecutemos, para el ejemplo del keypad en el artículo anterior esto sería una vez dentro de cada ciclo while, lo pueden poner en cualquier lugar siempre y cuando esté dentro del ciclo como se muestra a continuación:

 void loop() {
 quantity = 0;
   Serial.println("Seleccione una opcion (A-D):");
 flag = true;
    while (flag) {
     if(thrBlink.shouldRun())
       {
           thrBlink.run();
     }
       key = keypad.getKey();
      if (key) {
         switch (key)
           {
           case 'A':
          case 'B':
//...

Estos ejemplos básicos están sirviendo como una base para mostrar cosas más interesantes en el futuro, como envío de mensajes a la nube o integración continua con despliegue a múltiples sensores desde la plataforma Visual Studio Team Services que les tendré listo muy pronto.

Hasta la próxima!
--Rp