Un protocollo di comunicazione Pure Data Arduino

Reading Time: 5 minutes



In questo tutorial presentiamo come realizzare un semplice protocollo di comunicazione Pure Data Arduino.

Il codice presentato di seguito è stato sviluppato appositamente per realizzare l’invio dello stato dei sensori capacitivi e dei potenziometri del nostro prototipo Cap-pad.

CapPad Arduino sensori capacitivi

Cap-Pad (abreviazione di Capacitive Pad) è il prototipo di una superficie di controllo basata su Arduino e sull’uso di sensori capacitivi realizzati con fogli di alluminio. Questo sistema d’interazione, progettato utilizzando la scheda Arduino Uno, è dotato di sei potenziometri rotativi e di undici sensori capacitivi. Cap-Pad può essere utilizzato come controller seriale per Pure Data, Max/MSP, Processing e qualsiasi altro programma e ambiente capace di ricevere i messaggi inviati da Arduino attraverso una connessione seriale.

Codice Arduino

Questo programma attiva una connessione seriale con un baud rate pari 115200 bps e invia in successione due byte per ogni potenziometro e per ciascun sensore capacitivo. Un semplice protocollo di comunicazione seriale è stato sviluppato per realizzare la trasmissione dei dati. Il protocollo prevede l’invio del primo byte per la trasmissione di un dato numerico mentre il secondo byte invia un’etichetta che identifica univocamente a quale potenziometro o sensore capacitivo si riferisce il dato appena inviato.

Per una semplice introduzione a come realizzare una trasmissione di dati da Arduino a Pure Data è possibile fare riferimento a questa guida: Inviare numeri interi a 8bit da arduino a pure data.

Il primo byte può essere un numero compreso nell’intervallo da 0 a 199 nel caso in cui sia utilizzato per definire lo stato attuale di uno dei sei potenziometri. Nel caso di un sensore capacitivo utilizzato come pulsante, invece, il primo byte assume i valori 0 oppure 1. Le etichette inviate attraverso il secondo byte vanno da 200 a 205 per indicare rispettivamente i potenziometri connessi agli ingressi analogici di Arduino da A0 ad A5. Successivamente,  si usano i numeri da 206 a 216 per definire i sensori capacitivi connessi alle porte digitali di Arduino dalla 3 alla 13.
//Arduino code for Cap-Pad
#include <capacitivesensor.h>;
CapacitiveSensor cs23 = CapacitiveSensor(2,3);
CapacitiveSensor cs24 = CapacitiveSensor(2,4);
CapacitiveSensor cs25 = CapacitiveSensor(2,5);
CapacitiveSensor cs26 = CapacitiveSensor(2,6);
CapacitiveSensor cs27 = CapacitiveSensor(2,7);
CapacitiveSensor cs28 = CapacitiveSensor(2,8);
CapacitiveSensor cs29 = CapacitiveSensor(2,9);
CapacitiveSensor cs210 = CapacitiveSensor(2,10);
CapacitiveSensor cs211 = CapacitiveSensor(2,11);
CapacitiveSensor cs212 = CapacitiveSensor(2,12);
CapacitiveSensor cs213 = CapacitiveSensor(2,13);
boolean isTriggered1=false;
boolean isTriggered2=false;
boolean isTriggered3=false;
boolean isTriggered4=false;
boolean isTriggered5=false;
boolean isTriggered6=false;
boolean isTriggered7=false;
boolean isTriggered8=false;
boolean isTriggered9=false;
boolean isTriggered10=false;
boolean isTriggered11=false;
int Soglia=180;
int Samples=15;
int i = 0;
int lastValue0=0;
int lastValue1=0;
int lastValue2=0;
int lastValue3=0;
int lastValue4=0;
int lastValue5=0;
void setup(){
Serial.begin(115200);
}
void loop(){
int PotValue0=analogRead(A0);
if(abs(PotValue0-lastValue0)>1)
{
// print out the value you read:
int MapPotValue0 = map(PotValue0, 0, 1023, 0, 199);
Serial.write(MapPotValue0);
Serial.write(200);
lastValue0=PotValue0;
}
int PotValue1=analogRead(A1);
if(abs(PotValue1-lastValue1)>1)
{
// print out the value you read:
int MapPotValue1 = map(PotValue1, 0, 1023, 0, 199);
Serial.write(MapPotValue1);
Serial.write(201);
lastValue1=PotValue1;
}
int PotValue2=analogRead(A2);
if(abs(PotValue2-lastValue2)>1)
{
// print out the value you read:
int MapPotValue2 = map(PotValue2, 0, 1023, 0, 199);
Serial.write(MapPotValue2);
Serial.write(202);
lastValue2=PotValue2;
}
int PotValue3=analogRead(A3);
if(abs(PotValue3-lastValue3)>1)
{
// print out the value you read:
int MapPotValue3 = map(PotValue3, 0, 1023, 0, 199);
Serial.write(MapPotValue3);
Serial.write(203);
lastValue3=PotValue3;
}
int PotValue4=analogRead(A4);
if(abs(PotValue4-lastValue4)>1)
{
// print out the value you read:
int MapPotValue4 = map(PotValue4, 0, 1023, 0, 199);
Serial.write(MapPotValue4);
Serial.write(204);
lastValue4=PotValue4;
}
int PotValue5=analogRead(A5);
if(abs(PotValue5-lastValue5)>1)
{
// print out the value you read:
int MapPotValue5 = map(PotValue5, 0, 1023, 0, 199);
Serial.write(MapPotValue5);
Serial.write(205);
lastValue5=PotValue5;
}
long total1=cs23.capacitiveSensor(Samples);
if(total1>Soglia)
{
if(!isTriggered1)
{
Serial.write(1);
Serial.write(206);
isTriggered1=true;
}
} else
{
if(isTriggered1)
{
isTriggered1=false;
Serial.write(0);
Serial.write(206);
}
}
long total2=cs24.capacitiveSensor(Samples);
if(total2>Soglia)
{
if(!isTriggered2)
{
Serial.write(1);
Serial.write(207);
isTriggered2=true;
}
} else
{
if(isTriggered2)
{
isTriggered2=false;
Serial.write(0);
Serial.write(207);
}
}
long total3=cs25.capacitiveSensor(Samples);
if(total3>Soglia)
{
if(!isTriggered3)
{
Serial.write(1);
Serial.write(208);
isTriggered3=true;
}
} else
{
if(isTriggered3)
{
isTriggered3=false;
Serial.write(0);
Serial.write(208);
}
}
long total4=cs26.capacitiveSensor(Samples);
if(total4>Soglia)
{
if(!isTriggered4)
{
Serial.write(1);
Serial.write(209);
isTriggered4=true;
}
} else
{
if(isTriggered4)
{
isTriggered4=false;
Serial.write(0);
Serial.write(209);
}
}
long total5=cs27.capacitiveSensor(Samples);
if(total5>Soglia)
{
if(!isTriggered5)
{
Serial.write(1);
Serial.write(210);
isTriggered5=true;
}
} else
{
if(isTriggered5)
{
isTriggered5=false;
Serial.write(0);
Serial.write(210);
}
}
long total6=cs28.capacitiveSensor(Samples);
if(total6>Soglia)
{
if(!isTriggered6)
{
Serial.write(1);
Serial.write(211);
isTriggered6=true;
}
} else
{
if(isTriggered6)
{
isTriggered6=false;
Serial.write(0);
Serial.write(211);
}
}
long total7=cs29.capacitiveSensor(Samples);
if(total7>Soglia)
{
if(!isTriggered7)
{
Serial.write(1);
Serial.write(212);
isTriggered7=true;
}
} else
{
if(isTriggered7)
{
isTriggered7=false;
Serial.write(0);
Serial.write(212);
}
}
long total8=cs210.capacitiveSensor(Samples);
if(total8>Soglia)
{
if(!isTriggered8)
{
Serial.write(1);
Serial.write(213);
isTriggered8=true;
}
} else
{
if(isTriggered8)
{
isTriggered8=false;
Serial.write(0);
Serial.write(213);
}
}
long total9=cs211.capacitiveSensor(Samples);
if(total9>Soglia)
{
if(!isTriggered9)
{
Serial.write(1);
Serial.write(214);
isTriggered9=true;
}
} else
{
if(isTriggered9)
{
isTriggered9=false;
Serial.write(0);
Serial.write(214);
}
}
long total10=cs212.capacitiveSensor(Samples);
if(total10>Soglia)
{
if(!isTriggered10)
{
Serial.write(1);
Serial.write(215);
isTriggered10=true;
}
} else
{
if(isTriggered10)
{
isTriggered10=false;
Serial.write(0);
Serial.write(215);
}
}
long total11=cs213.capacitiveSensor(Samples);
if(total11>Soglia)
{
if(!isTriggered11)
{
Serial.write(1);
Serial.write(216);
isTriggered11=true;
}
} else
{
if(isTriggered11)
{
isTriggered11=false;
Serial.write(0);
Serial.write(216);
}
}
}

Pure Data

Una apposita patch chiamata CapPadReceive è stata sviluppata per ricevere i dati inviati attraverso la connessione seriale tra Arduino e Pure Data. L’oggetto ha un ingresso che consente, mediante un interruttore (toggle nel gergo di Pure Data), di attivare o disattivare la connessione seriale. Inoltre, dispone di sei uscite, una per ogni potenziometro di Cap-Pad. Le uscite forniscono ciascuna un valore numerico corrispondente alla posizione del rispettivo potenziometro.

CapPadReceive Pure Data Arduino

CapPadReceive

L’immagine di seguito mostra in dettaglio l’architettura interna della patch. La connessione seriale viene gestita attraverso l’oggetto comport . I due argomenti definiscono rispettivamente il primo il numero di porta a cui connettersi e il secondo la velocità di connessione (115200 bps nel caso di Cap-Pad).

RouteData Pure Data Arduino

Il messaggio devices può essere molto utile per individuare il numero che identifica il dispositivo che s’intende utilizzare per la connessione. Infatti, se si invia questo messaggio, comport stamperà sulla console di Pd la lista di tutti i dispositivi seriali disponibili con accanto il corrispondente numero identificativo. Questo numero può, quindi, essere inserito come primo argomento dell’oggetto comport oppure come primo argomento di un messaggio open utile per avviare una nuova connessione seriale. Il messaggio open $1 (nell’immagine a sinistra subito sopra comport) è stato, infatti, appositamente inserito nella patch per fare in modo che se nella creazione dell’oggetto CapPadReceive viene fornito un numero come primo argomento questo venga utilizzato per definire l’identificativo del dispositivo a cui connettersi (se non viene inserito alcun argomento la connessione si avvia utilizzando sempre il device 0).

La subpatch RouteData

L’oggetto comport fornisce attraverso l’uscita sinistra i dati ricevuti dal dispositivo seriale. Da qui, questi dati vengono inviati alla subpatch RouteData. All’interno di RouteData, con il primo oggetto select si provvede a realizzare una selezione dei dati provenienti dal dispositivo seriale per distinguere i dati dalle etichette. Si realizza, inoltre, un cambiamento dei valori delle etichette (per le nuove etichette si utilizza un campo di numeri interi nell’intervallo da 0 a 16).

Successivamente, l’oggetto pack trasforma i due byte inviati in modalità seriale in una lista. L’oggetto route, infine, suddivide la lista e realizza il corretto indirizzamento del dato in base alla sua etichette. Le prime sei uscite dell’oggetto route inviano i dati relativi ai potenziometri. Per questo motivo sono collegate agli oggetti outlet della subpatch e di CapPadReceive. Le restanti uscite forniscono i dati relativi agli undici sensori capacitivi e sono collegate a degli oggetti toggle che inviano il loro stato attraverso messaggi denominati: Trigger1,Trigger2,…,Trigger11.

Se ti piace questo progetto e vuoi provare a realizzarlo per problemi, curiosità e suggerimenti scrivici qui di seguito:

Codice di sicurezza:
security code
Inserire un codice di sicurezza.:

Invia

One thought to “Un protocollo di comunicazione Pure Data Arduino”

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *