16 decodifica telecomando - Arduino: programmi schemi e note

Transcript

16 decodifica telecomando - Arduino: programmi schemi e note
// 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 dal
telecomando in figura e puo’ in teoria essere utilizzato anche per decodificare i segnali inviati dai
vari telecomandi di casa (in realta’ per decodificare il segnale di un telecomando di casa conviene
utilizzare il programma, meno didattico e piu’ professionale, presente nel prossimo esercizio
17bis).
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
// Arduino: decodifica di un telecomando a raggi infrarossi
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
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 (PDF scaricato nell’area di download)
 Breve manuale di programmazione (PDF scaricato nell’area di download)
Per eventuali chiarimenti o suggerimenti sul contenuto di questa scheda scrivere a
[email protected]
Materiali
1 telecomando ad infrarosssi
1 modulo ricevitore di infrarossi
1 breadbord
3 cavetti
Schema
// Arduino: decodifica di un telecomando a raggi infrarossi
Programma
/* Attenzione: facendo il copia/incolla dal PDF all’IDE si perde la formattazione del testo. Per
rendere piu’ facilmente leggibile il programma e’ opportuno formattarlo subito dopo il
trasferimento nell’IDE, premendo CTRL+T. 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.
Questo programma e' derivato da un programma, complesso e non professionale, reperito sul web e la
catena 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 altro, forse piu’ semplice ed efficace programma per la decodifica di un telecomando, e’ presente
anche nella scheda descrittiva dell’esercizio 17bis – telecomando tv
Un’ultima osservazione riguarda il telecomando illustrato 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
zona
byte
byte
di
di
in
in
memorizzazione del tempo trascorso dal precedente impulso
memorizzazione dell’indirizzo inviato dal telecomando
cui viene memorizzato il comando
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
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,
// Arduino: decodifica di un telecomando a raggi infrarossi
// 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
// 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 interpretazione 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()
// Arduino: decodifica di un telecomando a raggi infrarossi
{
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();
{
remote_decode();
remote_deal();
}
}
// inizializza le zone di gestione del tempo
// lancia la routine di ricezione e decodifica dei segnali
// lancia la routine di visualizzazione dei comandi ricevuti