// Arduino: decodifica di un telecomando a raggi infrarossi
16 – decodifica di un telecomando a raggi infrarossi
I raggi infrarossi sono delle radiazioni
elettromagnetiche la cui lunghezza d’onda
varia da 0,7 micron a 0,4 millimetri. Si tratta
in pratica di una luce non percepibile
dall’occhio umano ma percepita da particolari
fotoresistenze. Volendo sintetizzare al
massimo i tecnicismi relativi alla trasmissione
infrarossa e’ possibile affermare che il
telecomando altro non e’ che un led che
emette luce infrarossa mentre il ricevitore e’
una fotoresistenza sensibile agli infrarossi. Il
telecomando emette una serie di impulsi (che
si concretizzano in brevissimi flash di luce
infrarossa) che vengono letti ed interpretati
dal ricevitore. Gli impulsi infrarossi trasmessi dal telecomando ricordano, a tratti, il vecchio
alfabeto morse. Il trasmettitore invia al ricevitore bytes da 8 bit componendo gli “0” e gli “1”
modulando opportunamente gli intervalli di tempo tra un flash e l’altro. Se il telecomando
emettesse una luce visibile e se i tempi fossero dilatati potremmo distinguere lo zero dall’uno
semplicemente misurando il tempo trascorso tra un’illuminazione e la successiva. Un tempo lungo
corrisponderebbe ad un 1 mentre un tempo breve corrisponderebbe ad uno zero.
In realta’ il protocollo di codifica e’ un po’ piu’ complicato di quanto detto poiche’ ogni comando e’
composto da una sequenza di 32 bit (4 bytes) preceduta da un segnale di sincronismo (un blocco
luminoso da 9 microsecondi seguito da un blocco non luminoso da 4,5 microsecondi). Ogni bit
rappresentato da flash da 0,56 microsecondi e da un intervallo senza luce che se e’ corto (0,56
microsecondi) indica uno zero mentre se e’ lungo (1,7 microsecondi) indica un 1.
I quattro bytes rappresentano, nell’ordine, un indirizzo, la ripetizione dell’indirizzo, il comando e la
ripetizione del comando (quest’ultimo con la sequenza di bit invertita).
Sia il ricevitore che il trasmettitore devono essere in connessione “visiva” non devono cioe’
frapporsi ostacoli tra l’apparecchio trasmittente ed il modulo ricevente. Il ricevente inoltre
interpreta al meglio il segnale quando il trasmettitore e’ posto esattamente davanti al bulbo (ad una
distanza massima di 8 metri).
Questo esercizio si concretizza nell’evidenziare sul monitor seriale i comandi inviati da un
telecomando e puo’ quindi essere utilizzato anche per “decodificare” i segnali inviati dai vari
telecomandi di casa.
In questa tabella sono riportati i segnali trasmessi dai 21 tasti del telecomando illustrato in figura
(valore HEX = valore esadecimale e valore DEC = valore decimale):
pulsante
valore
HEX
Valore
DEC
pulsante
Valore
HEX
Valore
DEC
pulsante
Valore
HEX
Valore
DEC
Bottone rosso
VOL +
FUNC/STOP
Indietro veloce
Pausa/avvio
Avanti veloce
Punta bassa
0xff00
0xfe01
0xfd02
0xfb04
0xfa05
0xf906
0xf708
0
1
2
4
5
6
8
VOL Punta alta
0
EQ
ST/REPT
1
2
0xf609
0xf50a
0xf30c
0xf20d
0xf10e
0xef10
0xee11
9
10
12
13
14
16
17
3
4
5
6
7
8
9
0xed12
0xeb14
0xea15
0xe916
0xe718
0xe619
0xe51a
18
20
21
22
24
25
26
Il ricevitore utilizzato in questo esercizio, marchiato 1057 D21B, ha la piedinatura illustrata in
figura. E’ ovviamente possibile utilizzare altri tipi di ricevitori, purche’ vengano rispettate le
// Arduino: decodifica di un telecomando a raggi infrarossi
funzionalita’ dei piedini (il positivo all’alimentazione da 5 volt, il negativo a terra ed il sensore alla
porta 2).
Nota: Questo esercizio e questa nota sono parte di una serie che vede protagonisti arduino ed
alcuni dei componenti ad esso collegabili. Per la maggior parte degli esercizi e’ anche disponibile
un filmato su youtube.
 Esercizi facenti parte della raccolta
 Filmati presenti su youtube
 Informazioni su arduino e sui componenti collegabili
 Breve manuale di programmazione
Materiali
1 telecomando ad infrarosssi
1 modulo ricevitore di infrarossi
1 breadbord
3 cavetti
Schema
Programma
/* Per comprendere al meglio questo esercizio e' opportuno comprendere prima i principi
di funzionamento di un telecomando o, meglio, comprendere il protocollo di comunicazione
dei segnali. Tutto cio' e' spiegato, anche se non in maniera esaustiva, nelle note descrittive
su telecomando e ricevitore ad infrarossi che accompagnano questo esercizio.
// Arduino: decodifica di un telecomando a raggi infrarossi
Questo programma e' derivato da un programma, non professionale, esistente sul web
ed il sistema telecomando / ricevitore ad infrarossi / arduino non sempre risponde con prontezza
agli impulsi.
E’ possibile che tale ritardo dipenda dal fatto che il momento di pressione di un tasto
non sempre coincide con il momento in cui il programma verifica l'arrivo di un blocco
di sincronismo
Per ottenere una risposta e' quindi a volte necessario premere piu' volte ed in rapida
successione un tasto, in modo da favorire la sincronizzazione tra telecomando ed apparato
ricevente
Un’ultima osservazione riguarda il telecomando illustrato in figura nelle note descrittive. Si tratta di
un prodotto di infima qualita’ il cui cattivo funzionamento comporta spesso la necessita’ di premere
piu’ volte un tasto. L’impianto risponde meglio se, in sua vece, si utilizza un qualunque
telecomando di casa */
int IR_IN = 2; // inserisce 2 nella variabile IR_IN utilizzata per
// indicare la porta alla quale e' collegato il ricevitore del segnale infrarosso
int Pulse_Width = 0;
int ir_code = 0x00;
char adrL_code = 0x00;
char adrH_code = 0x00;
// zona di memorizzazione del tempo trascorso dal precedente impulso
// zona di memorizzazione dell’indirizzo inviato dal telecomando
// byte in cui viene memorizzato il comando
// byte in cui viene memorizzato il comando invertito (Anti-code)
void timer1_init(void) /* *******routine di inizializzazione delle zone di memorizzazione del tempo.
Le seguenti variabili sono gestite ed autonomamente utilizzate da arduino per gestire il
trascorrere del tempo. In particolare la variabile TCNT1 e’ di fatto un timer contenente un valore
corrispondente al tempo trascorso dal suo ultimo azzeramento */
{
TCCR1A = 0X00;
TCCR1B = 0X05; // modulatore del tempo; con il valore 5, TCNT1 si incrementa di 15625 unita’
// ad ogni secondo
TCCR1C = 0X00;
TCNT1 = 0X00; // timer, con TTCCR1B = 5 si incrementa di 15625 unita' ad ogni secondo,
// fino ad un massimo di circa 65000, poi si azzera e ricomincia
TIMSK1 = 0X00;
}
char logic_value() /* ***********routine di analisi dell’impulso ricevuto. *************
Restituisce il valore 0 (0,56 microsecondi dal precedente impulso, corrispondente al valore 0)
oppure 1 (1,7 microsecondi dal precedente impulso, corrispondente al valore 1) oppure -1 nessun
tasto premuto o segnale non riconosciuto*/
{
TCNT1 = 0X00;
// azzera il timer
while(!(digitalRead(IR_IN))); // se non c’e’ impulso verifica il tempo trascorso
Pulse_Width=TCNT1;
TCNT1=0;
if(Pulse_Width>=7&&Pulse_Width<=10) // 0,56 microsecondi
{
while(digitalRead(IR_IN)); // se c’e’ un impulso
Pulse_Width=TCNT1;
//memorizza il tempo trascorso dal precedente impulso
TCNT1=0;
if(Pulse_Width>=7&&Pulse_Width<=10) // 0.56 microsecondi
return 0;
else if(Pulse_Width>=25&&Pulse_Width<=27) // 1.7 microsecondi
// Arduino: decodifica di un telecomando a raggi infrarossi
return 1;
}
return -1;
}
void pulse_deal() // ******Routine di memorizzazione dei 4 bytes di indirizzo e comando ****
{
int i;
int j;
ir_code=0x00;
// azzera l'area di memorizzazione del comando
adrL_code=0x00; // azzera l'area di memorizzazione dell'indirizzo
adrH_code=0x00; // azzera l'area di memorizzazione dell'indirizzo inverso
// nelle prossime righe analizza i valori trasmessi dal telecomando e compila, bit per bit,
// i 4 bytes in cui viene memorizzato il comando (due bytes di indirizzo e due bytes di comando)
for(i = 0 ; i < 16; i++) // memorizza i 16 bit dei due bytes di comando
{
if(logic_value() == 1) // se la routine di ricezione restituisce il valore 1
ir_code |= (1<<i); // Salva il bit del comando
}
for(i = 0 ; i < 8; i++) // memorizza gli 8 bit del byte di indirizzo
{
if(logic_value() == 1)
adrL_code |= (1<<i); // salva il bit dell'indirizzo
}
for(j = 0 ; j < 8; j++)
// memorizza gli 8 bit del byte del comando inverso
{
if(logic_value() == 1)
adrH_code |= (1<<j); // Salva il bit dell'indirizzo inverso
}
}
void remote_decode(void) // ************* Routine di ricezione e decodifica del segnale *********
{
TCNT1=0X00;
while(digitalRead(IR_IN)) // esegue la routine quando riceve un impulso
{
if(TCNT1>=1563) // se sono trascorsi piu' di 100 millisecondi dal precedente
// impulso significa che il telecomando non e’ in uso e quindi azzera le zone di
// memorizzazione dei codici e torna alla routine chiamante
{
ir_code=0x00ff; // inserisce il valore FF nel comando (0x00ff corrisponde al
// tasto "spento" del telecomando)
adrL_code=0x00; // azzera il byte di indirizzo
adrH_code=0x00; // azzera il byte di indirizzo inverso
return;
}
}
// Se la durata e’ inferiore a 100 microsecondi significa che il telecomando e' in uso
// e quindi si predispone a ricevere una sequenza di impulsi
TCNT1=0X00;
while(!(digitalRead(IR_IN))); // se non c'e' impulso verifica il tempo trascorso dal
// precedente impulso
Pulse_Width=TCNT1;
TCNT1=0;
if(Pulse_Width>=140&&Pulse_Width<=141) // 9 microsecondi. Se sono trascorsi 9 microsecondi
// Arduino: decodifica di un telecomando a raggi infrarossi
// significa che e' arrivato il primo segnale di sincronismo
{
while(digitalRead(IR_IN)); // verifica se dopo il primo blocco di sincronismo sono trascorsi
// 4,5 microsecondi, (secondo segnale di sincronismo)
Pulse_Width=TCNT1;
TCNT1=0;
if(Pulse_Width>=68&&Pulse_Width<=72) // 4.5ms
{
pulse_deal(); // Se e' arrivato anche il secondo segnale di sincronismo lancia la routine
// di ricezione ed interpretazioni della sequenza di impulsi (pulse_deal)
return;
}
else if(Pulse_Width>=34&&Pulse_Width<=36) //2.25ms
{
while(!(digitalRead(IR_IN))); // Low attesa
Pulse_Width=TCNT1;
TCNT1=0;
if(Pulse_Width>=7&&Pulse_Width<=10) //0,56 microsecondi
{
return;
}
}
}
}
void remote_deal(void) // ***********routine di esecuzione delle funzioni richieste dal telecomando
// (e cioe’ visualizzazione, sul monitor di sistema, del comando ricevuto)
{
Serial.print ("codice: ");
Serial.print (ir_code,HEX);
// Visualizzazione esadecimale
Serial.print (" indirizzo: ");
Serial.println(adrL_code,HEX); // Visualizzazione esadecimale
}
void setup()
{
Serial.begin (9600); // predispone la porta seriale ad un velocita’ di 9600 bit al
// secondo
pinMode(IR_IN,INPUT); // definisce come porta di ingresso la porta IR_IN (la porta 2),
// alla quale e' collegato il ricevitore infrarossi,
}
void loop()
{
timer1_init();
//inizializza le zone di gestione del tempo
{
remote_decode(); // lancia la routine di ricezione e decodifica dei segnali
remote_deal();
// lancia la routine di visualizzazione dei comandi ricevuti
}
}
Scarica

16 decodifica telecomando - Arduino: programmi schemi e note