Firmata: il protocollo standard per comunicare con i microcontrollori

Firmata

Firmata è un protocollo generico per consentire la comunicazione tra un microcontrollore e un computer host. Scopriamo in questo articolo in cosa consiste questo protocollo, quali sono i suoi vantaggi, e come possa essere utilizzato a livello pratico.

L'interfacciamento tra un dispositivo a microcontrollore (si pensi a un qualunque sistema di tipo embedded) e un sistema host (ad esempio un normalissimo PC) è una funzionalità fondamentale e di enorme utilità al fine di eseguire il debugging, l'autodiagnosi, la configurazione, o il semplice controllo, di un qualsiasi dispositivo hardware basato su microcontrollore. Il proliferare di diversi tipi di interfacce hardware (seriale, Ethernet, USB) anche sulle comuni MCU di fascia medio-bassa, ha riproposto un problema fino a poco tempo fa trascurato: la mancanza di uno standard in grado di regolamentare questo tipo di comunicazione.

Si pensi a una comune scheda equipaggiata con un microcontrollore (perchè no, anche una comune scheda Arduino come quella mostrata nell'immagine seguente), e supponiamo che si voglia controllare da remoto lo stato degli ingressi e delle uscite, sia di tipo analogico sia digitale. La prima soluzione che ci viene in mente è quella di sfruttare il collegamento seriale (disponibile in modo nativo sulle schede Arduino tramite il convertitore USB-seriale) e di realizzare su PC un programmino ad-hoc utilizzando il linguaggio e il sistema di sviluppo a noi più graditi (Visual Basic, oppure Visual Studio C/C++, C#, Delphi, ecc.).

A questo punto sembra tutto chiaro: abbiamo definito le specifiche di massima del nostro progetto e come intendiamo procedere. E il protocollo? Che tipo di messaggi utilizzeremo per realizzare a livello implementativo questa comunicazione? Che tipo di struttura avranno questi messaggi? Quali saranno i loro parametri, i loro codici di controllo, ecc.? Ecco quindi che nasce un problema, un'esigenza comune a cui occorre dare una risposta. Firmata è stato introdotto proprio per rispondere a questi quesiti, definendo uno strato standard per la comunicazione microcontrollore-host.

Il principale vantaggio offerto da questo tipo di soluzione è presto detto. Da un lato è possibile utilizzare lo stesso software di controllo su host sostituendo secondo le esigenze solo l'hardware del microcontrollore. Potremo quindi ad esempio realizzare un'applicazione di controllo "Firmata-compliant" e continuare a utilizzarla con l'hardware prodotto dalla società X, oppure Y, oppure Z (a condizione, ovviamente, che tutte queste supportino lo standard Firmata). Dall'altro lato, chi produce sistemi hardware di tipo embedded ha tutto l'interesse a fornire un supporto nel proprio firmware/hardware anche per Firmata: in questo modo mette automaticamente a disposizione degli utilizzatori un sistema remoto di controllo fondamentale nelle fasi di sviluppo, messa a punto, e manutenzione di un'applicazione.

L'obiettivo principale di Firmata è quello di far sì che il microcontrollore diventi un'estensione dell'ambiente di sviluppo su host computer, nel modo più semplice e naturale possibile. Firmata è stato espressamente progettato per essere open e flessibile, in modo tale da poter essere supportato da qualsiasi ambiente di sviluppo, e semplice da implementare sia lato microcontrollore sia lato HOST computer, in modo da assicurare un'ampia scelta di implementazioni. L'implementazione di riferimento di Firmata è attualmente la libreria per Arduino/Wiring inclusa nel pacchetto software Arduino a partire dalla versione 0012.

Come è nato

Lo standard Firmata è nato nel 2006, quando Hans-Cristoph Steiner decise di creare un'applicazione demo per Arduino. Questa consisteva di più schede Arduino collegate tra loro, oltre a differenti tipi di sensori. L'approccio iniziale seguito da Hans era quello classico del "try and test": le board Arduino venivano cioè configurate volta per volta scaricando l'opportuno software, e si procedeva ad eseguire direttamente la verifica sul campo. Ben presto, tuttavia, Hans si stancò di questo metodo, che lo obbligava a riprogrammare le schede ad ogni cambio di configurazione. Perchè allora non utilizzare un approccio diverso, più flessibile e generale? L'idea era quella di collegare i microcontrollori ad un computer host (un normale PC) tramite un'interfaccia seriale; i microcontrollori avrebbero acquisito i dati dai sensori e preparato i dati da inviare ai motori, relè, e alle altre uscite. Per poter mettere in pratica quest'idea era però necessario disporre di un protocollo seriale sul quale basare la comunicazione tra computer host e microcontrollore. Nacque così la prima versione dello standard, oggi disponibile su tutta la famiglia di microcontrollori Arduino, come pure sulla scheda Wiring. I criteri seguiti da Hans per definire il nuovo protocollo furono i seguenti:

  • semplicità e flessibilità;
  • utilizzo efficiente della banda disponibile;
  • semplicità di implementazione.

Steiner, nel definire il protocollo firmata, non partì da zero, ma piuttosto cercò di agganciarsi a qualcosa di già esistente che fosse in grado di soddisfare i requisiti menzionati precedentemente. La scelta ricadde sullo standard MIDI, al quale Firmata si ispira fortemente. MIDI è infatti un protocollo efficiente, relativamente semplice da realizzare, e del quale esistono già pronte numerose implementazioni (quindi codice riutilizzabile già esistente). Per le piattaforme Arduino e Wiring, Firmata è stato implementato come una libreria; ciò significa che essa può essere utilizzata per realizzare delle applicazioni in cui il microcontrollore è controllato remotamente tramite un computer host e protocollo Firmata.

Il protocollo

Il protocollo Firmata, giunto oggi alla versione 2.3, è attualmente in grado di supportare fino a 16 pin analogici e fino a 128 pin digitali (16 * 8 porte a 8-bit). Sono tuttavia già state avanzate delle proposte per estendere il protocollo, e dobbiamo quindi attenderci nuove versioni dello stesso. Vediamo ora in dettaglio le sue caratteristiche salienti (per gli approfondimenti è sufficiente consultare il sito firmata.org.

Tipi di messaggi

Il protocollo utilizza il formato dei messaggi del protocollo MIDI, largamente impiegato nel settore delle applicazioni musicali. La caratteristica di questo formato di messaggi è quella di essere particolarmente compatto, quindi elevata efficienza nell'utilizzo della banda e elevata efficienza nell'utilizzo della CPU. I comandi disponibili consentono di:

  • controllare la modalità dei singoli pin (digital out, digital in, analog in, PWM control, servo control);
  • leggere gli ingressi digitali;
  • impostare le uscite digitali;
  • leggere gli ingressi analogici;
  • controllo tramite PWM;
  • controllo servo motori.

Da notare come la maggior parte dei messaggi abbia una lunghezza di soli 3 byte.

/* This protocol uses the MIDI message format, but does not use the whole
 * protocol.  Most of the command mappings here will not be directly usable in
 * terms of MIDI controllers and synths.  It should co-exist with MIDI without
 * trouble and can be parsed by standard MIDI interpreters.  Just some of the
 * message data is used differently.
 *
 * MIDI format: http://www.harmony-central.com/MIDI/Doc/table1.html
 * 
 *                              MIDI       
 * type                command  channel    first byte            second byte 
 *----------------------------------------------------------------------------
 * analog I/O message    0xE0   pin #      LSB(bits 0-6)         MSB(bits 7-13)
 * digital I/O message   0x90   port       LSB(bits 0-6)         MSB(bits 7-13)
 * report analog pin     0xC0   pin #      disable/enable(0/1)   - n/a -
 * report digital port   0xD0   port       disable/enable(0/1)   - n/a -
 *
 * sysex start           0xF0   
 * set pin mode(I/O)     0xF4              pin # (0-127)         pin state(0=in)
 * sysex end             0xF7   
 * protocol version      0xF9              major version         minor version
 * system reset          0xFF
 *
 */
/* SysEx-based commands (0x00-0x7F) are used for an extended command set.
 *
 * type                command  first byte       second byte      ...
 *-----------------------------------------------------------------------------
 * string                0x71   char *string ...
 * firmware name/version 0x79   major version   minor version     char *name...
 */

Supponiamo ad esempio che si voglia impostare il pin 13 di una board (può essere un Arduino ma, più in generale, una qualsiasi board basata su microcontrollore) come pin di uscita. Osservando la tabella, vediamo che il comando corrispondente ha codice 0xF4 (set pin mode I/O), al quale seguono due byte: il primo contenente il numero di pin (0-127) e il secondo il tipo di porta (0=input, 1=output). Quindi, se ad esempio vogliamo impostare il pin 0 (primo pin) come pin di uscita, dovremo generare un comando di questo tipo:

0xF4 0x00 0x01

Osservando la tabella precedente in cui sono elencati i codici comando, notiamo che alcuni comandi hanno anche associato un "MIDI channel" ("pin #" oppure "port"). Ciò significa che per questi comandi, in modo analogo a quanto avviene nel protocollo di riferimento MIDI, la parte alta del codice comando (nibble più significativo) identifica il codice del comando stesso, mentre la parte bassa (nibble meno significativo) serve per contenere il valore del parametro (numero pin o numero porta, a seconda del comando). Quindi, se volessimo ad esempio impostare l'uscita analogica del pin 1 al valore 300, dovremmo scrivere un comando di questo tipo:

0xE1 0x2C 0x02

Si noti inoltre che il port number viene calcolato dividendo il numero di pin per 8.

I comandi appartenenti alla categoria SysEx sono stati introdotti per estendere il set di comandi. Ciò viene attuato utilizzando il primo byte dopo il byte di start SysEx (0xF0) per identificare il comando esteso. L'utilità di SysEx permette di superare il limite di 3 byte per ogni comando, come indicato nelle note seguenti:

/* Generic Sysex Message
 * 0     START_SYSEX (0xF0)
 * 1     sysex command (0x00-0x7F)
 * x     between 0 and MAX_DATA_BYTES 7-bit bytes of arbitrary data
 * last  END_SYSEX (0xF7)
 */

I comandi della categoria SysEx sono diversi, come indicato nella tabella seguente:

#define RESERVED_COMMAND        0x00 // 2nd SysEx data byte is a chip-specific command (AVR, PIC, TI).
#define ANALOG_MAPPING_QUERY    0x69 // ask for mapping of analog to pin numbers
#define ANALOG_MAPPING_RESPONSE 0x6A // reply with mapping info
#define CAPABILITY_QUERY        0x6B // ask for supported modes and resolution of all pins
#define CAPABILITY_RESPONSE     0x6C // reply with supported modes and resolution
#define PIN_STATE_QUERY         0x6D // ask for a pin's current mode and value
#define PIN_STATE_RESPONSE      0x6E // reply with a pin's current mode and value
#define EXTENDED_ANALOG         0x6F // analog write (PWM, Servo, etc) to any pin
#define SERVO_CONFIG            0x70 // set max angle, minPulse, maxPulse, freq
#define STRING_DATA             0x71 // a string message with 14-bits per char
#define SHIFT_DATA              0x75 // shiftOut config/data message (34 bits)
#define I2C_REQUEST             0x76 // I2C request messages from a host to an I/O board
#define I2C_REPLY               0x77 // I2C reply messages from an I/O board to a host
#define I2C_CONFIG              0x78 // Configure special I2C settings, eg. power pins and delay times
#define REPORT_FIRMWARE         0x79 // report name and version of the firmware
#define SAMPLING_INTERVAL       0x7A // sampling interval
#define SYSEX_NON_REALTIME      0x7E // MIDI Reserved for non-realtime messages
#define SYSEX_REALTIME          0x7F // MIDI Reserved for realtime messages

I comandi estesi sono molto utili, e tra essi ricordiamo ad esempio il comando EXTENDED_ANALOG, che permette di indirizzare dei pin analogici superiori al 15-esimo, oppure il comando PIN_STATRE_QUERY, che permette di rilevare lo stato (ingresso o uscita) con cui è configurato un determinato pin. Una descrizione dettagliata e completa del protocollo è disponibile a questo indirizzo.

Il programma Firmata Test

Il programma "firmata_test" (disponibile per il download a questo indirizzo) è un'applicazione, disponibile in ambiente Linux, Mac OS-X e Windows, la quale permette di controllare da un computer host (un normalissimo PC) un sistema embedded in grado di gestire il protocollo Firmata. La versione in oggetto è già pronta per essere interfacciata con Arduino. Per fare ciò, occorre anzitutto configurare la board Arduino. Il primo passo è quello di selezionare nell'ambiente IDE di Arduino l'esempio "StandardFirmata" (File->Esempi->Firmata->StandardFirmata), e caricarlo sulla board. Arduino è a questo punto pronto per interfacciarsi con un computer host utilizzando lo standard Firmata (a livello hardware, verrà utilizzata la stessa porta COM utilizzata dall'IDE per rilevare Arduino). Per verificare che l'esempio StandardFirmata sia stato correttamente caricato sulla board, possiamo abilitare nell'IDE il monitor seriale, e dare un reset alla board (ricordarsi di impostare sul monitor seriale la velocità a 57600 bit/s, la stessa utilizzata da Firmata per Arduino): se tutto è andato per il verso giusto, dovremmo vedere comparire una stringa come indicato nell'immagine seguente:

Quest'altra immagine mostra invece come si presenta il programma Firmata Test una volta avviato.

Con una board come Arduino Uno (già provvista di un led collegato al pin di I/O #13), è sufficiente cambiare lo stato del pin stesso (configurato come output) da 0 a 1 e viceversa: si vedrà come effetto il led accendersi o spegnersi, rispettivamente. Si può poi collegare un altro led a un'uscita analogica di Arduino, e verificare che l'intensità del led cambia modificando il valore analogico su Firmata Test.

Il programma Firmata Test è molto utile anche per testare, debuggare, e validare eventuali schede Arduino-compatibili da noi preparate per specifici progetti. Se vogliamo infatti verificare la bontà dei cablaggi, possiamo lanciare l'applicazione in oggetto e testare i vari pin di I/O, sia digitali che analogici. Da notare inoltre che, allo stesso indirizzo internet, è disponibile il codice sorgente dell'applicazione Firmata Test (con istruzioni per compilarlo, se interessati, in ambiente GCC con WxWidgets), molto utile per studiare e comprendere meglio anche gli aspetti più "reconditi" dell'implementazione del protocollo.

In ambiente Arduino, oltre all'esempio StandardFirmata, è disponibile anche la libreria Firmata (utilizzata ovviamente nel programma di esempio stesso), la quale implementa il protocollo Firmata e consente di scrivere applicazioni personalizzate basate su questo protocollo. Istruzioni sull'utilizzo della libreria sono disponibili a questo indirizzo.

Esempi di utilizzo

Visto che il canale di comunicazione tra il sistema embedded a microcontrollore e il sistema host è una comune linea seriale, possiamo pensare di realizzare l'applicazione software su host utilizzando qualunque linguaggio o ambiente di sviluppo che supporti tale interfaccia. La fantasia a questo punto non ha limiti. Possiamo utilizzare ad esempio Visual Basic (magari modificando un'applicazione che già abbiamo per la seriale), oppure VisualStudio C++ o C#, oppure Delphi, oppure altri linguaggi ancora (Processing, ovviamente, oltre a Python, Perl, e anche il Javascript!). Un primo esempio significativo è quello descritto a questo indirizzo, nel quale viene utilizzato Visul Basic DotNet per implementare l'applicazione su host computer. Non solo, l'autore ha anche realizzato degli utili controlli grafici che possono essere inclusi nelle nostre applicazioni. Un esempio di controllo è il seguente:

Allo stesso link sono presenti istruzioni dettagliate per l'utilizzo dell'applicazione e per il download delle dll necessarie.

Un secondo esempio è quello che si trova a questo link. In questo caso viene utilizzato addirittura Javascript per controllare una board Arduino tramite il protocollo Firmata. Il post in oggetto è descritto molto bene, anche se si rivolge a un pubblico che può non avere conoscenze di Arduino e di hardware in generale; se volete, potete quindi "saltare" le parti relative dell'articolo (un pò di ripasso non fa comunque mai male!). Diamo un'occhiata anche a questo video dove troviamo Arduino, Firmata, e Node.js utilizzati assieme: viene mostrato come sia possibile pilotare un led RGB tramite un'applicazione eseguita all'interno del browser.

Conclusioni

Abbiamo visto in questo articolo un buon esempio di protocollo standard per la comunicazione tra un microcontrollore e un PC host. Numerose sono le applicazioni utili: dalla diagnostica dell'hardware (ciò vale a maggior ragione per le board autoassemblate), al debugging remoto (basta un collegamento seriale, anche remotizzabile, non è necessario avere la board collegata direttamente al PC HOST), alla realizzazione di reti di board a microcontrollore. Come abbiamo detto in precedenza, Firmata è oggi disponibile su tutte le board della serie Arduino, ma non solo. Ad esempio, sul Raspberry PI è stata creata la libreria pyFirmata (in linguaggio Python) che implementa lo stesso tipo di protocollo. Ciò significa che possiamo far parlare una scheda Arduino con un Raspberry PI tramite Firmata? Certamente sì! Un esempio lo possiamo trovare a questo link

 

Quello che hai appena letto è un Articolo Premium reso disponibile affinché potessi valutare la qualità dei nostri contenuti!

 

Gli Articoli Tecnici Premium sono infatti riservati agli abbonati e vengono raccolti mensilmente nella nostra rivista digitale EOS-Book in PDF, ePub e mobi.
volantino eos-book1
Vorresti accedere a tutti gli altri Articoli Premium e fare il download degli EOS-Book? Allora valuta la possibilità di sottoscrivere un abbonamento a partire da € 2,95!
Scopri di più

2 Comments

  1. delfino_curioso delfino_curioso 6 novembre 2013
  2. slovati slovati 6 novembre 2013

Leave a Reply