Strumenti Utente

Strumenti Sito


infrarosso

Differenze

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

Link a questa pagina di confronto

infrarosso [2020/07/03 17:58] (versione attuale)
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 17:58 (modifica esterna)