Gestire segnali I.R. con Java e Arduino

0

di Emanuele Paiano

Molti sistemi di domotica, fanno uso di apposite interfacce hardware/software, che consentono la connessione di vari dispositivi ad un sistema di elaborazione centrale, come ad esempio un sistema embedded o un apposito server che ne permette la supervisione da remoto. In alcuni casi, si sente la necessità di interfacciare con tali sistemi, anche dispositivi non smart, dotati della sola interfaccia ad infrarossi, la quale permette la ricezione dei comandi inviati da un telecomando.

 

In questo articolo, verrà esposto un progetto basato su Arduino e su una libreria Java, per consentire la gestione di segnali infrarossi, oltre che l’eventuale elaborazione all’interno di uno o più thread Java. In questo modo, si potrebbe pensare all’integrazione di tale applicazione all’interno di una comoda interfaccia basata su Swing/ AWT, JavaEE oppure su un’applicazione Android.

Struttura del progetto

Il progetto è composto da due parti, come illustrato in Figura 2:
• un modulo hardware formato da un sensore e un trasmettitore IR, gestiti da un microcontrollore (come Arduino), che si
occupa di inviare o ricevere i segnali IR in base ai comandi ricevuti sulla porta seriale;
• un modulo software che si occupa di far comunicare il microcontrollore con l’applicazione, grazie ad un protocollo
(applicativo) realizzato ad hoc, il quale si appoggia su un collegamento seriale di tipo Usb, Wifi o Bluetooth;
La componente software è composta dalla futura applicazione Java, e dalla libreria che si interfaccia con la componente hardware, come mostrato in Figura 2: quest’ultima è composta dal microcontrollore, ricevitore e trasmettitore ad infrarossi.

Figura 2: Struttura del progetto

Modulo hardware (Irduino)

Per tale modulo, verrà utilizzato Arduino, noto microcontrollore low-cost impiegato da molti maker per la prototipazione rapida di progetti homebrew. L’idea generale consiste nel combinare gli schemi elettrici di due progetti (reperibili su Adafruit e mostrati in seguito) per la ricezione e la trasmissione dei segnali IR, tramite la libreria IRLib2 di Chris Young, mentre lo sketch di Arduino sarà realizzato con un protocollo ad hoc per la comunicazione con la componente software. Come vedremo dopo, la libreria Java mette a disposizione delle interfacce per essere estesa e supportare altri tipi di sketch Arduino o librerie IR, grazie ai vantaggi offerti dalla programmazione a oggetti.
Circuito di ricezione
La realizzazione di questo circuito è piuttosto semplice: nell’articolo originale, spiega come collegare il ricevitore TSOP38238, possiamo utilizzare collegamenti analoghi per altri tipi di ricevitori IR. Solitamente, tali ricevitori dispongono di 3 pin:
• VCC, ossia il pin di alimentazione che va collegato all’alimentazione o all’uscita 5V di Arduino;
• GND, ossia la massa che va collegata ad un’uscita GND di Arduino;
• OUT, ossia il pin su cui viaggiano i dati in input al microntrollore, tale pin va collegato al pin 2 di Arduino.
Il collegamento generale è illustrato in Figura 3 ed è possibile trovare maggiori dettagli nell’articolo originale di Adafruit (https://goo.gl/HRyiZa).

 

Figura 3: Il fotorecettore IR ed i rispettivi collegamenti

Circuito di invio
Tale circuito è leggermente più complesso del precedente: in un primo momento si potrebbe pensare di collegare il diodo
IR direttamente al pin del microcontrollore ed inviare il segnale. Poichè i pin di I/O di Arduino non sono in grado di erogare una corrente sufficiente per poterli collegare direttamente al diodo, è opportuno utilizzare la linea di alimentazione a 5V di Arduino. Nel prelevare tale tensione, si fa uso di un transistor 2N2222, la cui base va collegata ad un Pin 3 di Arduino tramite una resistenza da 470 ohm, ottenendo come risultato un interruttore che apre e chiude il circuito verso il diodo IR. Il collegamento avviene nel modo seguente:
• la base del transistor va al pin 3 di Arduino, piazzando una resistenza nel mezzo;
• il collettore del transistor va al catodo del diodo (ovvero al piedino più corto);
• l’anodo del Diodo va collegato con il pin 5V di Arduino; l’emettitore del transistor va al pin GND di Arduino.
Tale collegamento è illustrato in Figura 4: se abbiamo collegato tutto a modo, è possibile verificare il funzionamento di entrambi i circuiti, facendo delle prove tramite gli sketch di esempio presenti nella libreria IRLib2. Maggiori dettagli si possono trovare nell’articolo originale di Adafruit (https://goo.gl/zcFBpj).

Figura 4: Il LED IR collegato mediante un transistor 2N2222

Nota: Collegando il circuito all’alimentazione a 5V (Vcc), sarebbe anche opportuno limitare la corrente di picco del LED durante i periodi di conduzione del transistor. A questo scopo si può collegare una resistenza da 4,7 ohm 1/2W in serie a LED1

Protocollo e Sketch
Realizzato e testato il circuito, si necessita di un protocollo applicativo, ovvero un’insieme di regole che stabiliscono i comandi che l’applicazione Java dovrà inviare al microcontrollore, oltre alle risposte contenenti l’esito delle operazioni. Per motivi di spazio, ci si limita alla sola descrizione del protocollo, mentre lo sketch lo si può scaricare già pronto da github all’indirizzo https://goo.gl/3UxRmQ. Per le istruzioni da inviare al microcontrollore, si è pensato di introdurre un set di istruzioni con lo stesso numero di campi separati da virgole, ovvero opcode, param1, param2, param3 dove opcode rappresenta il codice dell’operazione, mentre tutti gli altri sono i parametri che specificano gli argomenti. Nello sketch sono presenti gli oggetti irSender e irReceiver che rappresentano rispettivamente il trasmettitore ed il ricevitore infrarossi. Dalla porta seriale vengono lette le istruzioni che vengono interpretate in modo tale da richiamare le rispettive funzioni. Alcune di queste istruzioni sono elencate in Tabella 1 e si possono inviare aprendo il monitor seriale dell’IDE di Arduino, impostando la ricezione a 9600bps. Tuttavia tale dispositivo è poco efficiente senza l’implementazione di un’apposita interfaccia software che semplifichi l’utilizzo.

Modulo software (Jirduino)

A questo punto è possibile descrivere la libreria Java che mette a disposizione classi e metodi per interagire con il microcontrollore, sfruttando il collegamento seriale. La libreria in questione si chiama jIRDuino, è ancora in via di sviluppo ma già utilizzabile: attualmente è composta da diversi package e classi, tra cui quelle per la conversione dei segnali trasmessi da alcuni telecomandi IR, oltre che le classi di base per l’invio e la ricezione dei segnali. Per questioni di spazio, in questa sede verranno descritte solo le classi di base, con il solo collegamento seriale tramite usb (jIRDuino, con l’aggiunta di alcune classi, supporta anche collegamenti wireless con Arduino). Chi non mastica Java, può saltare questa parte e sfruttare alcune funzionalità tramite irduino-tools: si tratta di un tool da riga di comando che implementa alcune funzioni di jIRDuino.
Segnali IR in Java
Sono rappresentati dalle classi racchiuse nel package org.jirduino.core, contenente:
• la classe Signal che istanzia gli oggetti che rappresentano un generico segnale IR;
• la classe Protocols che contiene delle costanti rappresentanti i vari protocolli (supportati da IRLib2).
Il costruttore della classe Signal, prevede tre parametri in ingresso:
• un parametro id, ovvero un intero rappresentante il tipo di protocollo utilizzato, che può essere un campo della classe Protocols (come ad esempio Protocols.NECx);
• un parametro value che rappresenta il comando esadecimale da inviare in formato stringa, ovvero E0E040BF per indicare il comando 0xE0E040BF;
• un parametro bits che rappresenta il numero di bit utilizzati dal protocollo specificato.
Per esempio, per istanziare un oggetto rappresentante il comando 0xE0E040BF con protocollo NECx, si usa:
Signal poweroff=new Signal(Protocols.NECx, “E0E040BF”, 32); instanziando così l’oggetto poweroff che può essere passato alla classe responsabile per l’invio del segnale. Tale comando simula la pressione del tasto power su alcune
TV Samsung. Nell’immagine di Figura 5 sono illustrate le interazioni tra le varie componenti hardware e software.

Figura 5: interazioni tra le varie componenti hardware e software.

Invio e ricezione dei segnali

Nel package org.jirduino.drivers si trovano le entità coinvolte nella comunicazione con il microcontrollore: l’interfaccia IRDevice che rappresenta il dispositivo IR su cui sono definiti i metodi principali come send- Data() e receiveData(); la classe IRLib2Device che rappresenta l’implementazione concreta di IRDevice, la quale comunica con lo sketch descritto prima, il quale è basato sulle librerie IRLib2; la classe IRDriver- Sample rappresenta la struttura base una futura implementazione di un driver alternativo (come ad esempio, uno non basato su IRLib2 o uno che interagisca con altri
sketch, protocolli o altri microcontrollori diversi da Arduino); Il costruttore dell’oggetto IRLib2Device (che è anche un oggetto IRDevice), richiede un parametro di tipo LinkDevice: consiste in un’interfaccia (appartenente alla libreria SerialDuino – https://goo.gl/sq5NJZ) che è estesa dalla classe ComLinkDevice. Questa realizza un collegamento COM o USB tra l’oggetto di tipo IRDevice e Arduino. Se ad esempio, si usa un sistema Linux con Arduino connesso sulla porta /dev/ttyUSB0, è possibile istanziare l’oggetto IRDevice con
String port=”/dev/ttyUSB0″;
/* Velocità porta */
int speed=ComLinkDevice.BAUDRATE_
9600;
/* creazione porta */
ComLinkDevice port=
new ComLinkDevice(
port, speed);
/* istanza */
IRDevice irDevice=
new IRLib2Device(
port);
/* apri la connessione
ad Arduino */
irDevice.init();
ed inizializzarlo con il metodo init(). Un modo alternativo per ottenere la porta, riguarda l’uso del metodo statico ComLinkDevice. getPorts() che restituisce la lista delle porte disponibili sul sistema, mentre con ComLinkDevice.getPortByName(String name) è possibile ottenere il percorso completo (tra quelle restituite da getPorts()) dando una stringa in input, come ttyUSB0 al posto di /dev/ttyUSB0.
Per l’invio del segnale, basta utilizzare il metodo sendData() e passare l’oggetto poweroff istanziato precedentemente:
Signal poweroff=new Signal(Protocols.
NECx, “E0E040BF”, 32);
irDevice.sendData(poweroff);
Una rappresentazione grafica della procedura di invio è illustrata nella Figura 6.

Figura 6: invio di un segnale IR

Per la ricezione dei segnali, possiamo utilizzare il metodo receiveData() dopo aver abilitato il ricevitore con setReceiverEnabled():
/* Attiva ricezione */irDevice.setReceiverEnabled(true);
/* Attendi un segnale IR */
Signal in=irDevice.receiveData();
/* Stampalo sulla console */
System.out.println(“Il segnale ricevuto
è “+in);
il valore del comando ed il protocollo del segnale possono essere recuperati con i metodi getValue() e getProtocol() della classe Signal. Se il protocollo non è supportato da jIRDuino, verrà restituito il segnale nullo (con tutti i valori impostati a zero). È possibile fare una prova utilizzando il telecomando della propria tv. Impostando la modalità sniffer, ed utilizzando il metodo waitResponse() in un ciclo, possiamo vedere tutti i comandi inviati dal telecomando al televisore:
irDevice.setPassiveSnifferMode(
true);
/* Attiva ricezione */
irDevice.setReceiverEnabled(true);
/* stampa su console i segnali
ricevuti */
while(true)
System.out.println(
ir.waitResponse());
premendo i tasti sul telecomando, si dovrebbero notare valori del tipo
Decoded Sony(2): Value:1E6

Adrs:0 (12 bits)
Decoded Sony(2): Value:5E6 Adrs:0
(12 bits)
Decoded Sony(2): Value:5E6 Adrs:0
(12 bits)
o leggermenti differenti, in base al protocollo utilizzato dal trasmettitore. Se viene restituito un segnale zero, allora il protocollo utilizzato dal telecomando non è supportato da IRLib2 (quindi nemmeno da IRDuino). In Figura 7 viene illustrata la procedura di ricezione di un segnale IR.

Figura 7: ricezione di un segnale IR

Traduzione di segnali
Un’altra interessante caratteristica di tale libreria, è la possibilità di ricevere un segnale in ingresso e tradurlo in un altro (anche di protocollo differente). Ciò è permesso dalle classi definite nel package org. jirduino.translators.SignalRule, rappresenta una regola di traduzione del segnale. Permette di associare un segnale di ingresso a uno di uscita, ovvero effettuare una traduzione. Inoltre contiene il campo delay che specifica il numero di secondi in cui attendere prima dell’invio del segnale tradotto. SignalRuleTable permette di istanziare una “tabella” contenente una lista di SignalRule, ovvero una tabella delle traduzioni; SignalConverter, è l’implementazione del thread che, dopo aver ricevuto un segnale in input, utilizzerà la SignalRuleTable per la traduzione. Tale classe implementa l’interfaccia Runnable di Java, ed il rispettivo oggetto istanziato, sarà passato al costruttore della classe Thread. Un esempio d’uso di tali classi è illustrato nel seguente codice:
IRDevice ir=new IRLib2Device(port);
ir.init();
SignalConverter converter=new SignalConverter(
new SignalRule-
Table(),ir);
Signal source=new Signal(Protocols.
NECx, “E0E040BF”, 32);
Signal target=new Signal(Protocols.
NEC, “E13650AF”, 32);
converter.addRule(source, target);
converter.setDebugModeOn(true);
Thread T1=new Thread(converter);
T1.start();
in questo caso, il segnale 0xE0E040BF trasmesso con protocollo NECx viene tradotto in un segnale 0xE13650AF che viene
ritrasmesso con protocollo NEC, ma è possibile aggiungere altre regole di conversione, grazie al metodo addRule(). Con
questo sistema è possibile usare Arduino come un bridge di protocolli, ovvero come un “convertitore IR”, oltre che mappare e convertire tutti i tasti di un telecomando non ufficialmente supportato dal dispositivo IR (per esempio è possibile utilizzare il telecomando dell’impianto Hi fi sulla vecchia TV). Sono comprese delle classi che permettono di automatizzare il tutto
(come JSONController e JSONConverter del package org.jirduino.config), definendo due file di configurazione in formato JSON, contenenti i rispettivi tasti del telecomando reale e di quello che si vuole emulare. Un esempio di questo tipo è possibile vederlo nella classe ConverterController.java del package org.jirduino.demo.

Shell e prompt: irduino-tools

Qualora non si abbia dimestichezza con Java, è possibile testare alcune le funzionalità descritte direttamente da shell, grazie ad un’implementazione di jIRDuino chiamata irduino-tools. Si tratta di un file jar eseguibile che, accettando i vari parametri
in input, permette di inviare, riceve e convertire i segnali IR. La directory “data/” contiene i vari file di configurazione in formato JSON di alcuni telecomandi, mappati e testati dall’autore del progetto. Lanciando irduino-tools senza argomenti,
si ottiene la guida con alcune opzioni:
————————-
IRDuino Tools 0.9.5
————————-

Use: java -jar irduino-tools.jar
<command> <port> [parametres]
Available commands:
> show-protocols show supported
protocols
> send send IR command
> sniff receive and print
IR signals
> generate-json generate
json config for IR controller
> probe-json probe exists
json config, by key pressing
> convert-signal convert
single signal between different
protocols
Run java -jar irduino-tools.jar
<command> for advanced help
mentre specificando un singolo comando, si ottiene la guida relativa al comando:
# java -jar irduino-tools.jar
sniff
Use: java -jar irduino-tools.jar
send <port> <id> <value> <bits>
where:
– id, integer id for infrared protocol
(i.e. 1 for NEC). See Protocol.
java.
– value, integer in hex format

for command value (i.e. E13650AF).
– port, arduino-connected serial
port (i.e. /dev/ttyUSB0)
Supponiamo di avere un sistema linux con Arduino collegato sulla porta /dev/ttyUSB0. Per inviare il comando 0xE 0E040BF con protocollo NECx, basta lanciare irduino-tools seguito dall’opzione send, dal numero di protocollo (usiamo 7 per NECx), dal comando da inviare e dal numero di bit previsti dal protocollo:
# java -jar irduino-tools.jar send
/dev/ttyUSB0 7 E0E040BF 32
per ottenere la lista dei protocolli supportati, si usa l’opzione show-protocols:
# java -jar irduino-tools.jar
show-protocols
Supported IR Protocols:
id 0 for Unknown Protocol
id 1 for NEC
id 2 for Sony
id 3 for RC5
id 4 for RC6
id 5 for PANASONIC_OLD
id 6 for JVC
id 7 for NECx
id 8 for SAMSUNG36
id 9 for GICABLE
id 10 for DIRECT_TV
id 11 for RCMM
id 12 for CYKM
Se si vuole ricevere dei segnali e stamparli a schemo, si ricorre al parametro sniff anzicchè send:
# java -jar irduino-tools.jar sniff
/dev/ttyUSB0
premendo un tasto sul telecomando, dovrebbero apparire i segnali IR ricevuti da Arduino:
Decoded Sony(2): Value:1E6 Adrs:0
(12 bits)
Decoded Sony(2): Value:5E6 Adrs:0
(12 bits)
Decoded Sony(2): Value:5E6 Adrs:0
(12 bits)
Per la conversione dei tasti, si ricorre
all’opzione convert-signal:
$ java -jar irduino-tools.jar convert-
signal
Use: java -jar irduino-tools.jar
convert-signal <port> <source>
<target>
options list:
<source> := <source protocols>
<source command hex> <source bits>
<target> := <target protocols>
<target command hex> <target bits>
<source protocols>: IR command
source’s protocol (e.g. 1 for NEC)
<source hex>: IR command source’s
protocol (e.g. E13650AF)
<source bits>: IR bits source’s
protocol (e.g. 32)
<target protocols>: IR command target’s
protocol (e.g. 2 for Sony)
<target hex>: IR command target’s
protocol (e.g. A90)
<target bits>: IR bits target’s protocol
(e.g. 12)
per fare un esempio, è possibile tradurre
il segnale A86 con protocollo Sony, in un
segnale 0xE13650AF con protocollo NEC:
$ java -jar irduino-tools.jar convert-
signal /dev/ttyUSB0 2 A86 12 1
E13650AF 32
premendo i tasti sul telecomando, dovrebbe
apparire la conversione:
SUCCESS => Received: (2, A86, 12)
SUCCESS => (2, A86, 12) resolved to
(1, E13650AF, 32)
SUCCESS => Sent: (1, E13650AF, 32)
e il dispositivo IR interessato dovrebbe rispondere
alla ricezione del comando.

Conclusioni
Tale libreria ci consente di gestire i segnali IR direttamente all’interno di un’applicazione Java, rendendo possibile l’integrazione con framework come Spring, dando la possibilità di gestire i vecchi dispositivi IR con comandi RESTful, funzionalità utile per chi si occupa dello sviluppo di interfacce IoT o domotiche. Inoltre grazie alle sue interfacce Java, è
possibile estenderla aggiungendo il supporto per nuovi sketch, o addirittura è possibile farla interagire con microcontrollori
diversi da Arduino.

Total 0 Votes
0

Tell us how can we improve this post?

+ = Verify Human or Spambot ?

About The Author

Laureato in Informatica e appassionato di tecnologia dall'età di 14 anni, tra i miei campi di interesse ci sono i sistemi operativi Unix (in particolare Linux), alcuni framework per lo sviluppo in Java, Python e Php. I ruoli ricoperti in passato riguardano l'amministrazione di reti e server Linux oltre all'assistenza tecnica e la consulenza informatica. Tra gli studi da autodidatta sono compresi l'elettronica e la robotica amatoriale, con sperimentazione nella realizzazione di prototipi basati su Arduino, Raspberry Pi e board IoT. Per informazioni: https://emanuelepaiano.github.io

Nessun commento on "Gestire segnali I.R. con Java e Arduino"

Leave a Comment

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