Strumenti Utente

Strumenti Sito


infrarosso
no way to compare when less than two revisions

Differenze

Queste sono le differenze tra la revisione selezionata e la versione attuale della pagina.


Ultima revisione
infrarosso [2018/09/15 18:24] – creata admin
Linea 1: Linea 1:
 +====== Comunicazione a infrarosso ======
 +
 +Esperimenti di comunicazione a infrarosso con Arduino usando  un ricevitore IR integrato e un IRED:
 +  * decodifica dei segnali di un telecomando
 +  * telecomando per scatto remoto di una macchina fotografica digitale
 +  * telecomando di una TV
 +
 +===== 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
 +
 +===== Decodifica segnale IR con Arduino =====
 +
 +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
 +
 +
 +<code C>
 +/* 
 + 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);
 +  }
 +}
 +
 +</code>
 +
 +===== Telecomando IR con Arduino =====
 +
 +Programma adattato da adafruit per pilotare lo scatto remoto della mia Nikon D50 (funziona). Il codice IR è stato ottenuto con un telecomando Nikon e qualcosa tipo il programma sopra. Non usa i registri quindi è sicuramente migliorabile lato prestazioni.
 +
 +<code C>
 +
 +// Intervallometro IR per la Nikon D50 (da adafruit)
 +
 +// IRED sul pin 13 con resistore da 1k
 +byte IRED = 13;
 +// intervallo in secondi tra gli scatti
 +byte intervallo = 5;
 +
 +void setup() {                
 +  pinMode(IRED, OUTPUT);      
 +  Serial.begin(9600);
 +}
 +
 +void loop() {
 +  Serial.println("Invio sequenza IR");
 +  // invia comando scatto
 +  SendNikonCode();
 +  // intervallo
 +  delay(intervallo * 1000);
 +}
 +
 +// genera un segnale a 38kHz per tot microsecondi
 +void pulseIR(long usecs) {
 +
 +  // disattiva gli interrupt
 +  noInterrupts();
 +
 +  while (usecs > 0) {
 +    // 38 kHz corrisponde circa a 26 us (3+10+3+10)
 +    // digitalWrite impiega 3 us (usare i registri?
 +    digitalWrite(IRED, HIGH);
 +    delayMicroseconds(10);
 +    digitalWrite(IRED, LOW);
 +    delayMicroseconds(10);
 +    usecs -= 26;
 +  }
 +
 +  // riattiva gli interrupt
 +  interrupts();
 +}
 +
 +// sequenza IR per scatto remoto Nikon D50
 +void SendNikonCode() {
 +  // comando scatto
 +  pulseIR(2000);  // 2080 codice adafruit non va!
 +  delay(27);
 +  pulseIR(440);
 +  delayMicroseconds(1500);
 +  pulseIR(460);
 +  delayMicroseconds(3440);
 +  pulseIR(480);
 +
 +  // pausa
 +  delay(65);
 +
 +  // ripetizione comando scatto
 +  pulseIR(2000);
 +  delay(27);
 +  pulseIR(440);
 +  delayMicroseconds(1500);
 +  pulseIR(460);
 +  delayMicroseconds(3440);
 +  pulseIR(480);
 +}
 +
 +
 +</code>
 +
 +===== Telecomando ON/OFF TV LG =====
 +
 +La sequenza corretta è stata ottenuta confrontando il protocollo utilizzato dalla TV LG (il protocollo NEC) con la sequenza ottenuta col programma che decodifica i segnali IR (vedi sopra). E' possibile accendere e spegnere la TV con Arduino, un IRED (di lunghezza d'onda compatibile) e resistore. Testato su smart TV LG 43LF590V.
 +
 +<code C>
 +
 +// TODO riscriverlo con array (o byte per la sequenza)
 +
 +// on/off smart tv LG
 +// invia il comando e lo ripete dopo 2 minuti
 +// reset per rilanciarlo
 +
 +// IRED sul pin 13 con resistore da 1k
 +byte IRED = 13;
 +
 +void setup() {                
 +  pinMode(IRED, OUTPUT);      
 +  Serial.begin(9600);
 +}
 +
 +void loop() {
 +  Serial.println("Invio sequenza IR tra un secondo");
 +  delay(1000);
 +  // invia comando on/off
 +  SendCode();
 +  // intervallo
 +  delay(120000);
 +}
 +
 +// genera un segnale a 38kHz per tot microsecondi
 +void pulseIR(long usecs) {
 +  // disattiva gli interrupt
 +  noInterrupts();
 +  while (usecs > 0) {
 +    // 38 kHz corrisponde circa a 26 us (3+10+3+10)
 +    // digitalWrite impiega 3 us (usare i registri?
 +    digitalWrite(IRED, HIGH);
 +    delayMicroseconds(10);
 +    digitalWrite(IRED, LOW);
 +    delayMicroseconds(10);
 +    usecs -= 26;
 +  }
 +  // riattiva gli interrupt
 +  interrupts();
 +}
 +
 +// sequenza IR per pulsante on/off LG
 +// il protocollo e il NEC
 +// 562 + 562 codifica il valore logico 0
 +// 562 + 1687 codifica il valore logico 1
 +// ottenuto con arduino e un ricevitore IR è questo
 +//mark (L) space (H)
 +//IR ON IR OFF
 +//8880 4420      9ms + 4ms per inizio trasmissione
 +//560 540       8 bit per l'indirizzo 
 +//560 540       
 +//560 1660      indirizzo 00100000
 +//540 540
 +//560 540
 +//540 540
 +//560 540
 +//560 540
 +//560 1660      ancora l'indirizzo ma complementato
 +//540 1660
 +//540 540       complementato 11011111
 +//560 1680
 +//520 1680
 +//520 1680
 +//520 1680
 +//520 1680
 +//520 540       8 bit del comando
 +//560 540
 +//560 540       comando 00010000
 +//560 1680
 +//520 540
 +//560 540
 +//560 540
 +//560 540
 +//560 1660      ancora il comando ma complementato
 +//540 1660
 +//540 1660      11101111
 +//540 540
 +//540 1680
 +//540 1660
 +//540 1660
 +//540 1660
 +//540                     fine trasmissione
 +
 +void SendCode() {
 +  // inizio trasmissione
 +  pulseIR(9000);
 +  delayMicroseconds(4000);
 +  // indirizzo 00100000
 +  pulseIR(560);
 +  delayMicroseconds(560);  
 +  pulseIR(560);
 +  delayMicroseconds(560);  
 +  pulseIR(560);
 +  delayMicroseconds(1687);  
 +  pulseIR(560);
 +  delayMicroseconds(560);  
 +  pulseIR(560);
 +  delayMicroseconds(560);
 +  pulseIR(560);
 +  delayMicroseconds(560);  
 +  pulseIR(560);
 +  delayMicroseconds(560);  
 +  pulseIR(560);
 +  delayMicroseconds(560); 
 +  // indirizzo complementato 11011111
 +  pulseIR(560);
 +  delayMicroseconds(1687); 
 +  pulseIR(560);
 +  delayMicroseconds(1687);
 +  pulseIR(560);
 +  delayMicroseconds(560); 
 +  pulseIR(560);
 +  delayMicroseconds(1687); 
 +  pulseIR(560);
 +  delayMicroseconds(1687); 
 +  pulseIR(560);
 +  delayMicroseconds(1687);
 +  pulseIR(560);
 +  delayMicroseconds(1687);   
 +  pulseIR(560);
 +  delayMicroseconds(1687);   
 +  // comando 00010000
 +  pulseIR(560);
 +  delayMicroseconds(560);  
 +  pulseIR(560);
 +  delayMicroseconds(560);  
 +  pulseIR(560);
 +  delayMicroseconds(560);  
 +  pulseIR(560);
 +  delayMicroseconds(1687);  
 +  pulseIR(560);
 +  delayMicroseconds(560);
 +  pulseIR(560);
 +  delayMicroseconds(560);  
 +  pulseIR(560);
 +  delayMicroseconds(560);  
 +  pulseIR(560);
 +  delayMicroseconds(560);
 +  // comando complementato 11101111 
 +  pulseIR(560);
 +  delayMicroseconds(1687); 
 +  pulseIR(560);
 +  delayMicroseconds(1687);
 +  pulseIR(560);
 +  delayMicroseconds(1687); 
 +  pulseIR(560);
 +  delayMicroseconds(560); 
 +  pulseIR(560);
 +  delayMicroseconds(1687); 
 +  pulseIR(560);
 +  delayMicroseconds(1687);
 +  pulseIR(560);
 +  delayMicroseconds(1687);   
 +  pulseIR(560);
 +  delayMicroseconds(1687);    
 +  // fine trasmissione
 +  pulseIR(560);
 +  delayMicroseconds(4000); 
 +}
 +
 +</code>
 +
 +
 +
 +===== 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
 +  * datasheet https://www.vishay.com/docs/82667/tsdp341.pdf
 +  * circuito di un ricevitore vishay https://www.vishay.com/docs/80069/circuit.pdf
  
infrarosso.txt · Ultima modifica: 2020/07/03 15:58 da 127.0.0.1