En la clase 9 del curso de Arduino UNO, vimos como generar comunicaciones con nuestra placa Arduino a través del puerto COM con una conexión serial. La conexión Serial es una función que realiza el intercambio de bytes entre la placa y el programa externo conectado a un puerto concreto (como la conexión a través de puerto USB).

Pues en este capítulo aprenderas a crear una conexión con otra libreria llamada Firmata que está disponible en tu IDE de Arduino.

¿Qué es Firmata?.

Firmata es un protocolo genérico para la comunicación con microcontroladores desde software instalado en un ordenador. Este protocolo se puede implementar en cualquier arquitectura de microcontroladores, así como en cualquier paquete de software.

El objetivo de firmata es permitir controlar completamente Arduino desde software instalado en un ordenador, sin escribir una sola línea de código de Arduino.

Por ejemplo, cuando se dice que Windows 10 puede usarse con Arduino, realmente lo que significa es que puedes controlar un Arduino desde Windows 10, mediante la comunicación con el protocolo firmata entre Windows 10 y Arduino. Windows 10 implementa este protocolo de forma nativa.

Para comprobar que el firmata de nuestro Arduino funcione correctamente vamos a realizar una prueba.

Circuito comprueba firmata

El circuito siguiente es una serie de diodos Leds puestos en serie entre ellos y mediante la programación de activar y desactivar puerto (HIGH, LOW), encenderemos y apagaremos una serie de conjuntos de Led según pase el tiempo.

void setup()
{
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
}

void loop()
{
  digitalWrite(2, HIGH);
  delay(1000); // Wait for 1000 millisecond(s)
  digitalWrite(3, HIGH);
  digitalWrite(2, LOW);
  delay(1000); // Wait for 1000 millisecond(s)
  digitalWrite(3, LOW); 
  digitalWrite(5, HIGH);
  delay(1000); // Wait for 1000 millisecond(s)
  digitalWrite(5, LOW);
  digitalWrite(4, HIGH);
  delay(1000); // Wait for 1000 millisecond(s)
  digitalWrite(4, LOW); 
  digitalWrite(7, HIGH);
  delay(1000); // Wait for 1000 millisecond(s)
  digitalWrite(7, LOW);
  digitalWrite(6, HIGH);
  delay(1000); // Wait for 1000 millisecond(s)
  digitalWrite(6, LOW);
}

Funcionamiento básico

El anterior programa te muestra como se organizan los puertos en cuanto a entrada y salida y simula la conexión con el programa que establece los encendidos y apagados.

El estándar del protocolo firmata se puede encontrar AQUI, donde disponemos de las espcificaciones del protocolo standard, así como las implementaciones para comunicar con dispositivos i2c, onewire, soporte para encoders, servos, motores paso a paso, etc.

Firmata está basado en el formato de mensaje de midi en el que los comandos se mandan en 8 bits y los datos en 7 bits. En Midi System Exclusive (Sysex http://www.2writers.com/eddie/tutsysex.htm), los mensajes pueden tener cualquier longitud y se usa de forma más extensiva en el protocolo firmata.

Comandos de firmata.

Los comandos (primer byte del protocolo), se descomponen en el primer nibble (el más significativo), es el propio comando y el segundo nibble del byte (el menos significativo) que en algunos casos aparece como 0 y da el número de puerto o de pin. Los comandos son:

● 0x90 – datos del pin digital (un puerto son hasta 8 pines digitales que se almacenan en en los "port registers" que permiten una manipulación a bajo nivel más rápida. Cada puerto es controlado por 3 registros.
● 0xE0 – datos del pin analógico
● 0xF4 – Configurar el modo del pin.
● 0xF5 – configurar el valor del pin digital.
● 0xC0 – configurar reporte del pin digital (una vez habilitado, el valor del pin debe ser reportado a la aplicación cliente).
● 0xD0 – configurar reporte del pin analógico (una vez habilitado, el valor del pin debe ser reportado a la aplicación cliente).
● 0xF9 – versión del protocolo

tabla de comandos

Además existen otros comandos llamados sysex. La idea de estos comandos es disponer de un espacio para un segundo comando usando el primer byte después del SysEx start byte (0xF0). La diferencia es que los datos pueden tener cualquier tamaño al contrario que los mensajes MIDI standard que tienen 2 bytes):

●0x71 – string.
● 0x79 – nombre/versión del firmware.
● 0xF7 – fin de Sysex.

Librería Firmata de Arduino.

La librería Firmata de Arduino implementa el protocolo Firmata visto anteriormente para comunicar el Arduino con el software ejecutado en un ordenador. Los métodos que implementa son los siguientes:

● begin(long) – Comienza la librería, es posible poner otra velocidad diferente a la velocidad por defecto que es 57600 baudios. También es posible iniciar el protocolo firmata desde otro Stream que no sea el que viene por defecto que es Serial.
● printVersion() – envía la versión del protocolo al ordenador.
● blinkVersion() – parpadea la versión de protocolo en el "build in LED", generalmente el pin 13.
● printFirmwareVersion() . envía la versión de firmware y su versión al ordenador.
● setFirmwareVersion(byte major, byte minor) – Configura la versión del firmware.
● setFirmwareNameAndVersion(const char *name, byte major, byte minor) – Configura nombre y versión del firmware.
● sendAnalog(byte pin, int value) – Manda el valor del pin analógico.
● sendDigitalPort(byte portNumber, int portData) – Manda el valor de un puerto digital de 8 bits.
● sendString(const char* string) – Manda un string a un ordenador.
● sendString(byte command, byte bytec, byte *bytev) – Manda un string al ordenador usando un tipo de comando.
● sendSysex(byte command, byte bytec, byte* bytev) – Manda un comando un con array de bytes.
● write(byte c) – Manda un byte al stream de datos.
● available() – Comprueba si hay algún mensaje entrante en el buffer.
● processInput() – Procesar los mensajes entrantes que hay en el buffer, mandado los datos a cualquiera de las funciones de callback registradas.
● attach(byte command, callbackFunction myFunction) – Registrar una función a un tipo de mensaje entrante.
● detach(byte command) – desregistrar la función del tipo de mensaje.
● sendValueAsTwo7bitBytes(int value) – Escribe el valor como 2 bytes.
● startSysex(void) – Comenzar mensaje sysex.
● endSysex(void) – Finalizar mensaje sysex.

Para asociar una función de callback a un tipo de mensaje de Firmata, la función debe cumplir el estándar de “callback function”. Hay varios tipos de funciones de respuesta en Firmata:

● genérica: void callbackFunction(byte pin, int value);
● reset del sistema: void systemResetCallbackFunction(void);
● string: void stringCallbackFunction(char *myString);
● sysex: void sysexCallbackFunction(byte command, byte byteCount, byte *arrayPointer);

Hay varios tipos de mensajes que se pueden asociar a las funciones de callback:

●ANALOG_MESSAGE //the analog value for a single pin // Comando (0xE0)
● DIGITAL_MESSAGE //8-bits of digital pin data (one port) // Comando (0x90)
● REPORT_ANALOG //enable/disable the reporting of an analog pin // Comando (0xC0)
● REPORT_DIGITAL //enable/disable the reporting of a digital port // Comando (0xD0)
● SET_PIN_MODE //change the pin mode between INPUT/OUTPUT/PWM/etc. // Comando (0xF4)
● STRING_DATA //C-style strings, uses stringCallbackFunction for the function type // Comando (0x71)
● SYSEX_START //generic, arbitrary length messages (via MIDI SysEx protocol), uses sysexCallbackFunction for the function type // Comando (0xF0)
● SYSTEM_RESET //message to reset firmware to its default state, uses systemResetCallbackFunction for the function type.

EL Firmata de Arduino UNO implementa un firmata llamado StandardFirmata.ino y es muy usado por aplicaciones para ordenador y móvil. Implementa control de servos (librería servo.h), dispositivos I2C (librería wire.h).

firmata de Arduino UNO

En línea 96, implementa la función wireWrite y wireRead para que funcione con todo tipo de versiones de IDE Arduino al compilar. En línea 747 setup: inicializa la versión de firmware y asocia las funciones de callback a los mensajes de entrada. La implementación de cada función se hace en las líneas anteriores. Luego resetea a la configuración por defecto de los pines. En línea 777 loop: en cada loop primero comprueba el cambio de estado de las entradas digitales. Luego busca mensajes entrantes firmata y los procesa si es necesario. Por último lee las entradas analógicas según el intervalo de muestreo configurado y manda datos a los dispositivos I2C con modo de lectura continua activado.