Questa è una vecchia versione del documento!
Indice
Comunicazione a infrarosso
Hardware
ricevitore IR
Un integrato con un fotodiodo e un circuito di condizionamento che si occupa della demodulazione del segnale a 38kHz inviato dal trasmettitore.
Tre piedini: Vcc, GND e segnale.
Segnale in uscita: alto quando non riceve (space), basso quando riceve un segnale IR a 38kHz (mark/burst).
Decodifica: esistono tanti protocolli che codificano 0 e 1 un maniera differente (ma sempre in base alla durata di space e mark). Il protocollo definisce anche cosa viene trasmesso e con che tempi (in genere 8 bit per indirizzo e comando che vengono inviati due volte e un codice per il repeat).
Trasmettitore
Un LED a infrarosso della lunghezza d'onda giusta (compatibile col ricevitore) da pilotare a 38kHz con un microcontrollore.
Idee per progetti
- video/foto di un telecomando mentre va (si vede col sensore di una camera digitale)
- reverse engineering di un protocollo IR
- copiare i dati di un telecomando (usare la libreria) per fare un telecomando con arduino e IRED
Osservazioni
- perché 38kHz? non confonde il segnale con altro
- non si riesce a vedere il segnale modulato, il ricevitore dà in uscita un segnale già demodulato
Esempio con decodifica segnale IR
Esiste una libreria molto facile da utilizzare fatta da Ken Shirrif. Il programma seguente invece non usa librerie ed è sufficientemente facile da capire. Prerequisiti:
- tipi di dati
- bitwise math (shift, AND)
- array
- registri microcontrollori
/* TODO - MAXPULSE dice che sono ms ma viene confrontato con variabili che sono us/20 RICEVITORE IR demodula il segnale di un trasmettitore IR generando - livello H per space (trasmettitore off) - livello L per mark/burst (impulsi a 38kHz) LEGGERE I SEGNALI CON I REGISTRI I/O l'istruzione digitalRead() è troppo lenta perciò bisogna usare l'accesso diretto ai pin con i registri I/O PIND è il registro che permette di leggere il valore degli ingressi da 0 a 7 (0 livello L, 1 livello H) il terzo bit da destra di PIND è riferito al pin 2 nel test del ciclo while shifta 1 a sinistra di due posizioni (da 00000001 a 00000100) poi fa un AND con gli otto bit di PIND; se il risultato è ancora 00000100 il segnale è alto vedi PortManipulation e BitMath nella Reference PROGRAMMA ORIGINALE da adafruit modificato nello stile (const invece che define) e commentato in italiano */ // pin segnale ricevitore IR const byte IRpin = 2; // valore massimo di highpulse/lowpulse prima del timeout // 65000 intervalli da 20us = 1.3 secondi const unsigned int MAXPULSE = 65000; // risoluzione in us nella lettura degli impulsi // (gli intervalli saranno multipli di questo valore) const byte RESOLUTION = 20; // memorizza la durata di H e L per 100 impulsi unsigned int pulses[100][2]; byte currentpulse = 0; // indice dell'array pulses void setup(void) { Serial.begin(9600); Serial.println("Attesa sequenza IR!"); } void loop(void) { // durata H e L in numero di intervalli di 20us unsigned int highpulse, lowpulse; // azzerati a ogni ciclo highpulse = lowpulse = 0; // se il segnale demodulato è alto (space) while (PIND & (1 << IRpin)) { // incrementa highpulse e aspetta 20 us highpulse++; delayMicroseconds(RESOLUTION); // timeout: stampa la sequenza di impulsi, azzera // l'indice e esce da loop (ricominicia da capo) if ((highpulse >= MAXPULSE) && (currentpulse != 0)) { //printpulses(); printpulses2(); currentpulse=0; return; } } // il segnale diventa L (o timeout) // scrivo la durata dell'impulso H pulses[currentpulse][0] = highpulse; // se il segnale è basso (mark) while (! (PIND & (1 << IRpin))) { // incrementa lowpulse e aspetta 20 us lowpulse++; delayMicroseconds(RESOLUTION); // timeout: stampa la sequenza di impulsi, azzera // l'indice e esce da loop (ricominicia da capo) if ((lowpulse >= MAXPULSE) && (currentpulse != 0)) { //printpulses(); printpulses2(); currentpulse=0; return; } } // il segnale diventa H (o timeout) // scrivo la durata dell'impulso L pulses[currentpulse][1] = lowpulse; // passiamo al prossimo impulso (coppia durate H/L) currentpulse++; } void printpulses(void) { // \n\r newline + return lascia un linea vuota Serial.println("\n\rSequenza impulsi (tempi in microsecondi)"); Serial.println("space (H)\tmark (L)"); Serial.println("IR OFF\t\tIR ON"); for (byte i = 0; i < currentpulse; i++) { Serial.print(pulses[i][0] * RESOLUTION, DEC); Serial.print("\t\t"); Serial.println(pulses[i][1] * RESOLUTION, DEC); } } void printpulses2(void) { // \n\r newline + return lascia un linea vuota Serial.println("\n\rSequenza impulsi (tempi in microsecondi)"); Serial.println("mark (L)\tspace (H)"); Serial.println("IR ON\t\tIR OFF"); Serial.print(pulses[0][1] * RESOLUTION, DEC); for (byte i = 1; i < currentpulse; i++) { Serial.print("\t\t"); Serial.println(pulses[i][0] * RESOLUTION, DEC); Serial.print(pulses[i][1] * RESOLUTION, DEC); } }
Riferimenti
- protocollo NEC (usato anche dalla mia smart TV LG) https://techdocs.altium.com/display/FPGA/NEC+Infrared+Transmission+Protocol
- tutorial e programma senza librerie (adattato sopra) https://learn.adafruit.com/ir-sensor/using-an-ir-sensor
- tutorial con molti riferimenti utili https://learn.sparkfun.com/tutorials/ir-communication#ir-communication-basics
- autore della libreria IR http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html
- generalità sulla trasmissione IR https://www.sbprojects.net/knowledge/ir/index.php
- circuito di un ricevitore vishay https://www.vishay.com/docs/80069/circuit.pdf