Controllo remoto di Arduino da dispositivi mobile

In rete è disponibile un ricco campionario di materiale relativo alla comunicazione tra Arduino e dispositivi mobile; spesso però non tutte le informazioni sono corrette e dettagliate, e muoversi all’interno dei vari forum alla ricerca di soluzioni può risultare una pratica sfiancante. La soluzione proposta in questo articolo è una rivisitazione nota ai più che si basa sull’utilizzo del formato OSC.

Introduzione

Il progetto proposto rappresenta un valido strumento per approcciare al mondo della domotica. Attraverso un’applicazione che gira su un dispositivo mobile ci si propone di controllare dispositivi connessi ad Arduino da qualsiasi parte del mondo. L’iterazione con gli oggetti virtuali dell’interfaccia (pulsanti, fader, etc.) causa l’invio di messaggi OSC che verranno utilizzati per caratterizzare il comportamento degli oggetti stessi, così ad esempio agendo su un Fader sarà possibile dimmerare il relativo canale RGB, piuttosto che modificare la frequenza dell’oscillazione utilizzata per il dimmeraggio automatico agendo sull’apposito controllo rotativo. Requisiti richiesti sono che sia Arduino che il dispositivo mobile siano connessi ad internet.

Elenco del materiale utilizzato

  • Arduino UNO
  • Ethernet Shield W5100
  • Arduino IDE Release 1.0.6
  • TouchOSC Editor e TouchOSC App
  • Sony Xperia E2115
  • Router ADSL + cavo Ethernet
  • Libreria OSCuino
  • Driver + alimentatore 12V
  • Strip LED RGB 12V

Schema di principio

Come si può osservare dalla figura seguente (figura 1) ad ogni oggetto dell’interfaccia dell’applicazione si può associare un “codice” OSC (vedremo più avanti cosa questo significhi), ed un range di valori numerici. Il comportamento associato agli oggetti va descritto opportunamente all’interno del codice da caricare su Arduino. Nello schema è possibile individuare: una funzione che si occupa della ricezione dei dati che pervengono dagli oggetti, e specifiche funzioni associate ad essi.

Schema di principio

Figura 1 : schema di principio

Cos’è l’Open Sound Control?

Per comprendere il funzionamento di questo progetto semplice, ma che nasconde al suo interno grandi potenzialità, è utile rispondere a questa domanda cercando di capire di cosa si tratta e come funziona senza però appesantire troppo la trattazione.

Più brevemente detto OSC, l’Open Sound Control, è un “content format” o formato. Questo significa che OSC può essere visto e confrontato con formati come XML, WDDX o JSON. Esso infatti non definisce le caratteristiche tipiche di un protocollo, quali processi semantici come pattern di comando-risposta, ma solo un formato di messaggi. Perdoni il lettore l’eventuale abuso di linguaggio che potrebbe venire utilizzato all’interno di questo documento qualora ci si riferisca con il termine protocollo OSC va tenuto presente che si tratta di un protocollo solo in senso lato.

• Sviluppato nel 1997 all’interno dei laboratori del dipartimento di Musica dell’Università della California, Berkeley da Adrian Freed and Matt Wright, questo formato ha visto una larga diffusione negli ultimi anni in diversi campi come la robotica, sistemi di musica professionale (X32 Digital Mixing Console, DiGiCo SD9, SSL Sigma, etc), video light console (GrandMA2, Whole Hog 4, Martin serie M, ChamSys MagicQ, etc.), software come Resolume Arena, Ableton Live, Cubase, Logic PRO, QLAB, etc.

OSC consente di far colloquiare vari dispositivi multimediali, sia fisici che virtuali, all'interno di un network.

Spesso contrapposto al protocollo MIDI, OSC non rappresenta un suo semplice antagonista. Una prima evidente e fondamentale differenza tra i due è rappresentata dalla natura della licenza che è di tipo proprietario per quanto riguarda il protocollo MIDI mentre è aperta per OSC. I due protocolli nascono con presupposti diversi. Il protocollo MIDI risulta sicuramente la scelta più indicata in termini di efficienza qualora si debbano interfacciare due o più apparecchiature. Nel mercato consumer le apparecchiature protendono verso l’utilizzo del protocollo MIDI e per questo motivo è ancora largamente diffuso. La semplicità di utilizzo del formato OSC all’interno delle reti lo ha invece reso indispensabile in apparecchiature professionali, che devono interagire efficientemente con altri dispositivi connessi al network.

Facendo riferimento alla documentazione fornita dalla CNMAT vediamo di capire come funziona OSC e come sfruttarlo per i nostri progetti.

Non essendo OSC un protocollo non si occupa dell’invio dei dati, che sono trasmessi in pacchetti. È la rete stessa che si occupa del trasporto e della consegna del pacchetto.

Scambio di pacchetti OSC

Figura 2 : scambio di pacchetti OSC tra client e server

 

Ogni richiesta di operazione in uscita OSC da parte di una applicazione produce un pacchetto OSC, similmente a quanto accade con il protocollo UDP, che produce un datagramma IP da inviare (figura 2).

Esistono diverse librerie che consentono di gestire facilmente il  formato OSC in Arduino. La libreria utilizzata in questo progetto è la OSCuino sviluppata e mantenuta dai creatori dello stesso protocollo ai laboratori del CNMAT (Center for New Music and Audio Technologies at the University of California at Berkeley).

Il  codice d'esempio riportato all'interno di questo documento fa riferimento a questa libreria.

Trattandosi di un formato che consente unicamente lo scambio di dati tra i vari client e il server per caratterizzare il comportamento di servizi personalizzati, si comprende facilmente il motivo per cui non esistano porte assegnate dallo IANA (Internet Assigned Numbers Authority). Come si può vedere dalla figura 3 il formato OSC si colloca al livello 6 (presentazione) del modello OSI.

Relazione tra pila OSI e OSC

Figura 3 : posizionamento del formato OSC nel modello OSI

Un pacchetto OSC è costituito dal suo contenuto, un blocco contiguo di dati, e dalla dimensione su 8 bit del contenuto stesso. Il contenuto del pacchetto deve essere o un messaggio OSC o un OSC Bundle (questo viene specificato nel primo byte del pacchetto).

Un messaggio OSC (figura 4) è composto da un Address Pattern seguito da un Type Tag e da 0 o più argomenti (numeri e stringhe).

Es. di struttura di un messaggio

Figura 4 : esempio di messaggio OSC

L’address pattern è l’equivalente dell’indirizzo IP, e segue la convenzione UNIX per la costruzione del percorso, quindi, deve sempre iniziare con “/”. Il Type Tag invece definisce il tipo di dato. Nell’esempio “f“ rappresenta un dato numerico a 32 bit in virgola mobile (float). Un OSC Type Tag String è una stringa che inizia con il carattere “,” seguito da una sequenza di caratteri pari in numero al numero di argomenti del messaggio in questione e ne rappresentano una codifica del tipo di argomento (nella tabella 1 sono mostrati alcuni esempi).

Tipo di argomento  OSC Type Tag String
Un tipo float sarà  identificato da ",f"
Due interi seguiti da una stringa, seguita da tre float corrispondono a ",iisfff"
Se non ci sono argomenti avremo semplicemente ","
Un argomento intero  seguito a due argomenti di tipo blob corrispondono a  ",ibb"
Tabella 1 : Esempio di corrispondenza tra argomenti e OSC Type Tag String

Ogni carattere dopo la virgola è chiamato Type Tag e rappresenta il tipo del corrispondente argomento. In figura 5 viene riportata la corrispondenza dei tipi comuni.

corrispondenza di tipi: tag e argomenti

Figura 5 : corrispondenza tra Type Tag e argomenti OSC

OSC Bundle è invece composto da una stringa: “#bundle” (8 byte), seguita da un Time Tag (8 byte), seguito a sua volta da 0 o più OSC Bundle Element. Un OSC Bundle Element è un intero (uint32 = 4 bytes) che indica la dimensione dei contenuti in byte, in multiplo di 4 byte (32 bit), seguito dai contenuti che possono essere sia un messaggio OSC che un OSC Bundle (i pacchetti possono contenere pacchetti).

I pacchetti ricevuti dal server sono passati a dei metodi. I metodi corrispondono a vari punti di controllo messi a disposizione. “Invocare” un metodo equivale a chiamare una “procedura”, ossia passare argomenti al metodo causandone una risposta.

I metodi OSC sono organizzati in una struttura ad albero chiamata “OSC Address Space”. I rami che si diramano sono detti “contenitori” e l'estremità del ramo farà capo ad un metodo. Ogni contenitore ha un nome simbolico, una stringa di caratteri ASCII che non deve contenere nessuno dei seguenti caratteri speciali (vedremo più avanti cosa significano):

’‘ # * , / ? [ ] { }

Considerando ad esempio l'indirizzo OSC "/a/b/cde" secondo quanto esposto sopra avremo che:

  • la root dell'albero presenta un contenitore: "a"
  • il contenitore "a" contiene a sua volta un contenitore: "b"
  • il contenitore "b" contiene il metodo o funzione: "cde"

Prendiamo adesso in considerazione il messaggio OSC con il seguente address pattern: "/oscillator/4/frequency" e supponiamo che presenti  come unico argomento un float di valore 440.0. La rappresentazione del messaggio su 32 bit avrà la seguente forma:

 2f (/)  6f (o)  73 (s)  63 (c)
 69 (i)  6c (l)  6c (l)  61 (a)
 74 (t)  6f (o)  72 (r)  2f (/)
 34 (4)  2f (/)  66 (f)  72 (r)
 65 (e)  71 (q)  75 (u)  65 (e)
 6e (n)  63 (c)  79 (y)  0 ()
 2c (,)  66 (f)  0 ()    0 ()
 43 (C)  dc (Ü)  0 ()    0 ()

Si noti che è stato riportando tra parentesi tonde la codifica ASCII del codice esadecimale che lo precede.

Se invece volessimo rappresentare il messaggio che ha come adress pattern "/foo" e come argomenti:

  1. 1000 (int32)
  2.  -1 (int32)
  3. "hello" (string)
  4. 1.234 (float32)
  5. 5.678 (float32)

Ciò che otterremmo in questo caso sono i seguenti 40 byte:

 2f (/)  66 (f)  6f (o)  6f (o)
 0 ()    0 ()    0 ()    0 ()
 2c (,)  69 (i)  69 (i)  73 (s)
 66 (f)  66 (f)  0 ()    0 ()
 0 ()    0 ()    3 ()    e8 (è)
 ff (ÿ)  ff (ÿ)  ff (ÿ)  ff (ÿ)
 68 (h)  65 (e)  6c (l)  6c (l)
 6f (o)  0 ()    0 ()    0 ()
 3f (?)  9d ()   f3 (ó)  b6 (¶)
 40 (@)  b5 (µ)  b2 (”)  2d (-)

Alla ricezione di ogni messaggio, il server invoca i metodi appropriati al suo OSC Address Space (quando questo corrisponde con l’OSC Address Pattern del messaggio). Questo processo è chiamato matching. La libreria OSCuino offre quattro metodi per gestire il pattern e l’address matching: match(), fullMatch(), root() e dispatch().
[...]

ATTENZIONE: quello che hai appena letto è solo un estratto, l'Articolo Tecnico completo è composto da ben 4500 parole ed è riservato agli ABBONATI. Con l'Abbonamento avrai anche accesso a tutti gli altri Articoli Tecnici e potrai fare il download in formato PDF eBook e Mobi per un anno. ABBONATI ORA, è semplice e sicuro.

Scarica subito una copia gratis

Una risposta

  1. Giordana Francesca Brescia Giordana Francesca Brescia 5 Dicembre 2019

Scrivi un commento

Seguici anche sul tuo Social Network preferito!

Send this to a friend