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 IR | 35kHz; 41kHz ottimo a 35kHz |
Lunghezza d’onda | 850nm; 1100nm ottimo tra 900nm e 1000nm |
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:
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!