Ricevitore Infrarosso (PNA4602M)

Andiamo a completare l’articolo precedente, parlando di come utilizzare il ricevitore infrarosso con Arduino.

I ricevitori di segnali infrarossi sono piccoli microchip con una fotocella settati per ascoltare nelle lunghezze d’onda dell’infrarosso.

Sono spesso utilizzati per il controllo remoto dei dispositivi – quali ad esempio TV, lettori DVD – e li troviamo posti nella parte frontale.

La differenza tra i ricevitori per segnali IR e le normali fotocelle sono i seguenti:

  • I ricevitori IR sono costruiti per ricevere solo la luce IR, mentre non sono sensibili alla luce visibile. Le normali fotocelle sono ottime nel rilevare la luce visibile, specialmente nei colori giallo/verde, ma sono pessime per l’infrarosso.
  • I ricevitori IR cercano in modo specifico segnali IR a 38kHz. Un normale led infrarosso acceso (o anche un corpo caldo, che appunto emette nell’infrarosso), non sarà rilevato. Le fotocelle non fanno distinzione tra le frequenze, ma solo limitate solo superiormente dal loro tempo di risposta, che in genere è 1kHz.
  • I ricevitori IR hanno un’uscita digitale, che va a 1 se rilevano un segnale IR a 38kHz, mentre a 0 quando non rilevano segnale. Le fotocelle si comportano come resistori, la cui resistenza cambia in base all’intensità luminosa a cui sono esposte.

È bene sottolineare, anche se è scontato, che nella comunicazione per mezzo di segnali IR, tra il ricevitore IR e il led IR non devono esserci ostacoli.

Andiamo a vedere il sensore PNA4602M del modulo presente nel kit Elegoo.

Struttura Modulo

Specifiche Tecniche

Come possiamo osservare in figura, il nostro sensore non è pensato ovviamente per tutte le frequenze dell’infrarosso, ma in modo specifico per una lunghezza d’onda di 940nm. Inoltre presenta il massimo della sensibilità a frequenza 38kHz.

Frequenza segnale IR35kHz; 41kHz
ottimo a 35kHz
Lunghezza d’onda850nm; 1100nm
ottimo tra 900nm e 1000nm

Schema Collegamento

Schema Collegamento

Codice

Per utilizzare il ricevitore infrarosso con Arduino, andiamo ad utilizzare la stessa libreria del precedente articolo: Arduino-IRremote, che trovate qui. Per semplicità vi riporto lo zip della libreria qui sotto.

Trovate qui di seguito due diversi codici. Il primo per leggere i comandi inviati con il codice dall’articolo precedente, l’altro per analizzare generici segnali IR.

#include <IRremote.h>

/*
 * Defininiamo i segnali di comando,
 * che dovremo definire uguale nel modulo trasmittente
 */
#define CMD1 1 //Possiamo anche scriverlo in esadecimale come 0x001 se ci piace di più
#define CMD2 2 //Possiamo anche scriverlo in esadecimale come 0x010 se ci piace di più

#define RCV_PIN 11
IRrecv receiver(RCV_PIN); 

void setup() {
  Serial.begin(9600); //Inizializziamo la seriale
  receiver.enableIRIn(); //Abilitiamo la ricezione
}

/*
 * Andiamo a leggere i comandi
 */
void loop() {
  decode_results results; //Qui vengono salvati i comandi letti
  if (receiver.decode(&results)) { //Proviamo a vedere se abbiamo ricevuto dati
    //Confrontiamo i comandi con i nostri
    if (results.value == CMD1){
      Serial.println("Ricevuto il comando 1!");
    }else if (results.value == CMD2){
      Serial.println("Ricevuto il comando 2!");
    }
    receiver.resume(); //Ricordiamoci di continuare a leggere dal sensore
  }
}
#include <IRremote.h>

#define RCV_PIN 11 //Pin di ricezione, può essere uno qualsiasi dei pin digitali

IRrecv receiver(RCV_PIN); 

void setup() {
  Serial.begin(9600); //Inizializziamo la seriale
  receiver.enableIRIn(); //Abilitiamo la lettura
}


void loop() {
  decode_results results;
  if (receiver.decode(&results)) {  //Verifico se ho ricevuto comandi
    dumpInfo(&results);             //Stampo le informazioni sul comando
    dumpRaw(&results);              //Stampo i dati completi del comando
    dumpCode(&results);             //Stampo il codice corrispondente
    Serial.println("");
    receiver.resume();              //Continuo a leggere i comandi
  }
}

/*
 * Funzioni ausiliarie
 */
void  ircode (decode_results *results) {
  // Panasonic has an Address
  if (results->decode_type == PANASONIC) {
    Serial.print(results->address, HEX);
    Serial.print(":");
  }

  // Print Code
  Serial.print(results->value, HEX);
}
void  encoding (decode_results *results) {
  switch (results->decode_type) {
    default:
    case UNKNOWN:      Serial.print("UNKNOWN");       break ;
    case NEC:          Serial.print("NEC");           break ;
    case SONY:         Serial.print("SONY");          break ;
    case RC5:          Serial.print("RC5");           break ;
    case RC6:          Serial.print("RC6");           break ;
    case DISH:         Serial.print("DISH");          break ;
    case SHARP:        Serial.print("SHARP");         break ;
    case JVC:          Serial.print("JVC");           break ;
    case SANYO:        Serial.print("SANYO");         break ;
    case MITSUBISHI:   Serial.print("MITSUBISHI");    break ;
    case SAMSUNG:      Serial.print("SAMSUNG");       break ;
    case LG:           Serial.print("LG");            break ;
    case WHYNTER:      Serial.print("WHYNTER");       break ;
    case AIWA_RC_T501: Serial.print("AIWA_RC_T501");  break ;
    case PANASONIC:    Serial.print("PANASONIC");     break ;
    case DENON:        Serial.print("DENON");         break ;
  }
}
void  dumpInfo (decode_results *results) {
  // Check if the buffer overflowed
  if (results->overflow) {
    Serial.println("IR code too long. Edit IRremoteInt.h and increase RAWBUF");
    return;
  }

  // Show Encoding standard
  Serial.print("Encoding  : ");
  encoding(results);
  Serial.println("");

  // Show Code & length
  Serial.print("Code      : ");
  ircode(results);
  Serial.print(" (");
  Serial.print(results->bits, DEC);
  Serial.println(" bits)");
}
void  dumpRaw (decode_results *results) {
  // Print Raw data
  Serial.print("Timing[");
  Serial.print(results->rawlen-1, DEC);
  Serial.println("]: ");

  for (int i = 1;  i < results->rawlen;  i++) {
    unsigned long  x = results->rawbuf[i] * USECPERTICK;
    if (!(i & 1)) {  // even
      Serial.print("-");
      if (x < 1000)  Serial.print(" ") ;
      if (x < 100)   Serial.print(" ") ;
      Serial.print(x, DEC);
    } else {  // odd
      Serial.print("     ");
      Serial.print("+");
      if (x < 1000)  Serial.print(" ") ;
      if (x < 100)   Serial.print(" ") ;
      Serial.print(x, DEC);
      if (i < results->rawlen-1) Serial.print(", "); //',' not needed for last one
    }
    if (!(i % 8))  Serial.println("");
  }
  Serial.println("");                    // Newline
}
void  dumpCode (decode_results *results) {
  // Start declaration
  Serial.print("unsigned int  ");          // variable type
  Serial.print("rawData[");                // array name
  Serial.print(results->rawlen - 1, DEC);  // array size
  Serial.print("] = {");                   // Start declaration

  // Dump data
  for (int i = 1;  i < results->rawlen;  i++) {
    Serial.print(results->rawbuf[i] * USECPERTICK, DEC);
    if ( i < results->rawlen-1 ) Serial.print(","); // ',' not needed on last one
    if (!(i & 1))  Serial.print(" ");
  }

  // End declaration
  Serial.print("};");  // 

  // Comment
  Serial.print("  // ");
  encoding(results);
  Serial.print(" ");
  ircode(results);

  // Newline
  Serial.println("");

  // Now dump "known" codes
  if (results->decode_type != UNKNOWN) {

    // Some protocols have an address
    if (results->decode_type == PANASONIC) {
      Serial.print("unsigned int  addr = 0x");
      Serial.print(results->address, HEX);
      Serial.println(";");
    }

    // All protocols have data
    Serial.print("unsigned int  data = 0x");
    Serial.print(results->value, HEX);
    Serial.println(";");
  }
}

Es: Replichiamo un comando IR di un telecomando ad infrarossi.

Usiamo il secondo codice, e otteniamo ad esempio:

Lettura da ricevitore IR con Arduino
Esempio di lettura da un telecomando Sony

Copiamo la riga “rawData[…] = {…};” e la incolliamo nel secondo codice dell’articolo precedente.

Carichiamo quel codice in un Arduino, con il led IR collegato, e inizierà ad inviare il comando!