Arduino, OSC e iPhone

Vuoi regolare la luminosità di un led RGB dal tuo smartfone?

Ti parlo oggi di un protocollo di comunicazione chiamato OSC ( Open Sound Control , nasce infatti come applicazione nel campo musicale per consentire la comunicazione tra computer e sintetizzatori audio, attraverso una rete ethernet.

arduino ethernet per osc

Cosa ti occorre per realizzate questo progetto:

  • Arduino;
  • Ethernet shield;
  • Led RGB e relativa resistenza;
  • uno smartphone ( io ho usato il mio iPhone );
  • l’App TouchOSC o applicazione equivalete per il tuo smartphone;
  • l’applicazione TouchOSC Editor per costruire l’interfaccia lato iPhone;

Per le applicazioni TouchOSC puoi acquistare l’app sull’Apple Store e scaricare l’editor dal sito ufficiale http://hexler.net/software/touchosc quasi in fondo alla pagina c’è la sezione dedicata al download dell’Editor:

TouchOSC Editor download

Ho evidenziato in giallo la sezione del sito in cui trovi il download dell’editor per il sistema operativo che utilizzi.

Inizia a costruire la tua interfaccia grafica, l’editor ti permette di costruirla con i controlli che preferisci, per questo progetto utilizzerai solo gli slider verticali:

Sull’iPhone avrai già installato l’App TouchOSC e puoi quindi accettare la sincronizzazione dal computer via wifi:

Passa ora a collegare la ethernet shield su Arduino e a collegare il led in modo che il catodo comune sia collegato a massa (GND o terminale negativo) passando pre una resistenza da 470Ω, lo schema è simile a seguente:

Per lo sketch da caricare su Arduino devi procurarti la liberia OSCClass dal sito http://www.recotana.com, questa libreria ti serve per poter scrivere lo sketch senza preoccuparti di getsire la chimata con il protocollo OSC. La OSC Class ti mette a disposizioni diversi metodi per interrogare il tuo dispositivo o per ricevere da esso i comandi e renderteli disponibili.

Per capire come saranno interpretati i valori inseriti nell’interfaccia che hai realizzato è necessario che ricordi cosa hai impostato, nel campo OSC:

  • come path hai scritto /butt/pwmr (g o b);
  • come range hai assegnato valori da 0 a 255;

sono le due informazioni fondamentali, il path indica la struttura che arriverà ad arduino ogni volta che una comunicazione OSC viene stabilita tra il telefono e arduino, il range di valori indica come oscillerà il valore inviato da ogni slider.

Per consentirti di utilizzare le informazioni che arrivano via OSC la OSCClass ti mette a disposizione molti metodi tra cui:

getAddress(level): con level indichi a quale punto del path vuoi riferirti, es.: /butt/pwmr il livello 0 è butt il livello 1 pwmr; ti restituisce il valore letto nel livello indicato;

getAddressNum(): non ha parametri e ti restituisce il numero di livelli di cui è composto il path comunicato via OSC;

getArgNum(): non ha parametri e ti restituisce il numero di Argomenti ( valori ) che il messaggio contiene;

getTypeTag(arglevel): specificando un numero corrispondente all’argomento di cui vuoi il valore ti informa se il valore è di tipo “i” intero o “f” float, è particolarmente utile se non sai che tipo di valore ti sarà ritornato e vuoi interpretarlo prima di usarlo con arduino;

getArgInt(arg): recupera il valore intero di un argomento passatogli, è necessario che tu sia certo che il valore è di tipo intero altrimenti ti restituisce un intero che potrebbe non corrispondere al valore atteso;

getArgFloat(arg): è identico al metodo getArgInt(arg) ma si riferisce a valori di tipo float che puoi poi convertire con arduino.

Ed ecco lo sketck:

#include "Ethernet.h"
#include "OSCClass.h"
#include "SPI.h"

int pinLedR=3;
int pinLedG=5;
int pinLedB=6;

  OSCMessage recMes;

  OSCClass osc(&recMes);

  byte serverMac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
  byte serverIp[]  = { 192, 168, 2, 99 };
  int  serverPort  = 10000;

  char *topAddress="butt";
  char *subAddress[3]={ "pwmr" , "pwmg" , "pwmb" };

void setup() {
     Serial.begin(19200);
     Ethernet.begin(serverMac ,serverIp);

     osc.begin(serverPort);

     pinMode(pinLedR, OUTPUT);
     pinMode(pinLedG, OUTPUT);
     pinMode(pinLedB, OUTPUT);

     digitalWrite(pinLedR, LOW);  //LED OFF
     digitalWrite(pinLedG, LOW);  //LED OFF
     digitalWrite(pinLedB, LOW);  //LED OFF

     osc.flush();
}

void loop() {
   if ( osc.available() ) {
      if( !strcmp( recMes.getAddress(0) , topAddress ) ){
         if( !strcmp(recMes.getAddress(1),subAddress[0]) ) {
            red();
         }
         else if( !strcmp(recMes.getAddress(1),subAddress[1]) ) {
            green();
         }
         else if( !strcmp(recMes.getAddress(1),subAddress[2]) ) {
            yellow();
         }
      }
  }
}

void red(){
   analogWrite(pinLedR, getIntValue(&recMes));
}

void green(){
   analogWrite(pinLedG, getIntValue(&recMes));
}

void yellow(){
   analogWrite(pinLedB, getIntValue(&recMes));
}

// *********  utility  ***********************************

int getIntValue(OSCMessage *mes){
    switch( mes->getTypeTag(0) ){
        case 'i': { return mes->getArgInt(0); }
        break;

        case 'f':  { return int(mes->getArgFloat(0)); }
        break;
      }
}

Ci sono alcune linee che si riferiscono solo alla comunicazione Ethernet, sono linee che avrai già incontrato in altri tutorial di questo sito: Tutorial Arduino Ethernet e SD Card.

Ecco le linee principali:

linee 01-03: includi le classi necessarie alla comunicazione Ethernet e OSC;

linea 09: costruisci un oggetto di tipo OSCMessage denominato recMes in cui saranno inseriti tutti i messaggi di comunicazione tra l’iPhone ed Arduino;

linea 11: inizializza la classe OSC;

linee 13-14: imposta Mac Address ed IP della tua lan in modo che arduino risponda su quell’IP;

linea 15: imposta una porta di comunicazione che serve alla classe OSC per ricevere i messaggi;

linee 17-18: definisci i tag del path che ti aspetti di ricevere nella comunicazione tra telefono ed Arduino, alla linea 17 impoti il path di livello 0 o topAddress; alla linea 18 imposta il path di livello 1 o subAdress come array di 3 valori uno per ogni slider;

Nella funzione di setup() le uniche righe nuove rispetto ai tutorial già letti sono la:

linea 24 in cui imposti la porta di comunicazione lato Arduino (serverPort);

linea 34: pulisce il buffer della classe OSC da precedenti messaggi;

La funzione loop() utilizza i metodi visti in alto per interpretare i path e i valori inviati via OSC e trasformarli in comandi per arduino ed il led RGB, in particolare:

linea 38: similmente a come avviene per le comunicazioni seriali l’if fa in modo che solo quando arriva un nuovo messaggio sia interpretato da Arduino;

linea 39: utilizza il comando strcmp() per confrontare il valore letto dal metodo recMes.getAddress(0) con quello impostato nella variabile topAddress alla linea 17, in caso di valore corrispondente continua l’elaborazione del messaggio OSC;

linee 40,43,46: sono identiche dal punto di vista sintattico a meno del valore di contronto, la linea 40 confronta il risultato del metodo recMes.getAddress(1) con il valore di subAddress[0], la 43 con subAddress[1] e la 46 con subAddress[2]; quando uno dei valori corrisponde a quello di confronto esegue la rispettiva funzione che ha azione sul led;

linee 53-55: definsci la funzione red() che agisce sul led di colore rosso, viene invocata dalla linea 41 quando il valore del livello 1 del path corrisponde a pwmr e invia al pin su cui è collegato il led rosso (pinLedR) il valore ricevuto dal telefono, per interpretare il valore ho costruito una funzione getIntValue(messaggio) che accetta in input il messaggio contenete tutta la comunicazione tra telefono ed arduino e ti restituisce il valore intero inviato;

linea 67: definisci la funzione getIntValue( messaggio ) come funzione di tipo integer in quanto il valore di ritorno sarà sempre un intero compreso tra 0 e 255;

linea 68: valuti con il comando switch ed il metodo  getTypeTag(0) se il valore contenuto nel messaggio è di tipo “i” o “f”;

linea 69: se è di tipo “i” è già un intero e lo restituisci recuperandolo con il metodo getIntArg(arg);

linea 72: se il valore è di tipo “f” ossia float dovrai convertirlo o in questo caso eseguire il cast ad intero in modo che possa essere passato alla funzione chiamante come intero, per recuperare questo tipo di valore utilizza il metodo getFloatArg(arg) in modo da ricavare correttamente il valore ed esegui un int() sul valore prima di restituirlo con il comando return.

Lo sketch è finito e puoi vedere il risultato in questo video:

Buona Pasquetta.

Prima di inserire un commento, per favore, leggi il regolamento

Permanent link to this article: https://www.mauroalfieri.it/elettronica/arduino-osc-iphone.html

98 pings

Skip to comment form

  1. […] protocollo OSC e quello che si può fare con arduino lo hai già letto nell’articolo Arduino, OSC e iPhone su questo blog, oggi ti mostro come realizzare un piccolo impianto domotico a 6 luci comandato da […]

Lascia un commento

Your email address will not be published.

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.