Main Content

Circuitos_1

No circuito de hoje iremos construir o detector de infravermelhos. Adicionalmente iremos construir um circuito para detetar o tipo de frequência e a que fabricante pertencem os códigos. Este ultimo recorre a utilização de um Arduino e de uma biblioteca para obter esta informação.

A luz infravermelho que tem um comprimento de onda que se situa entre os 870 nm e os 930-950 nm.
Foram desenvolvidos alguns protocolos por empresas que comercializam de electrónica de consumo como a Philips com o RC-5 e o RC-6.
Tipicamente estes protocolos usam uma trama (stream) de bits codificada através do código Manchester ou outro modulando uma portadora de 36 kHz ou 38 kHz.

Infelizmente não existe um standard e as bibliotecas têm que implementar os protocolos de cada um dos fabricantes.

Esquemático

Circuitos_3_Schematics

Componentes (BOM)

Circuito 1:

  • 1x NPN Transístor 2N2222 (Q1)
  • 1x Resistência de 1K Ohms (R1)
  • 1x Resistência de 100 Ohms (R2)
  • 1x Infrared Receiving Diode LED (D1)
  • 1x LED 3mm (D2)

Circuito 2:

  • 1x IR Receiver Module TSOP2438 (U1)

Pin-out dos IC

Circuitos_4_Pinout

Código

Encontrei várias fontes de informação interessantes de partilhar.

O primeiro sketch não usa qualquer biblioteca e permite observar a codificação em RAW. Este sketch foi publicado neste site.

/* Raw IR decoder sketch!

 This sketch/program uses the Arduno and a TSOP2438 to
 decode IR received. This can be used to make a IR receiver
 (by looking for a particular code)
 or transmitter (by pulsing an IR LED at ~38KHz for the
 durations detected

 Code is public domain
 */
// We need to use the 'raw' pin reading methods
// because timing is very important here and the digitalRead()
// procedure is slower!
//uint8_t IRpin = 2;
// Digital pin #2 is the Pin D19 on the Mega2560(PD2)
// see http://arduino.cc/en/Hacking/PinMapping168 for the
// UNO pin mapping with ATMega168/328

#define IRpin_PIN      PIND
#define IRpin          2

// the maximum pulse we'll listen for - 65 milliseconds is a long time
#define MAXPULSE 65000

// what our timing resolution should be, larger is better
// as its more 'precise' - but too large and you wont get
// accurate timing
#define RESOLUTION 20

// we will store up to 100 pulse pairs (THIS IS A LOT)
uint16_t pulses[100][2];  // pair is high and low pulse
uint8_t currentpulse = 0; // index for pulses we're storing

void setup(void) {
  Serial.begin(9600);
  Serial.println("Ready to decode IR!");
}

void loop(void) {
  uint16_t highpulse, lowpulse;  // temporary storage timing
  highpulse = lowpulse = 0; // start out with no pulse length


//  while (digitalRead(IRpin)) { // this is too slow!
    while (IRpin_PIN & _BV(IRpin)) {
     // pin is still HIGH

     // count off another few microseconds
     highpulse++;
     delayMicroseconds(RESOLUTION);

     // If the pulse is too long, we 'timed out' - either nothing
     // was received or the code is finished, so print what
     // we've grabbed so far, and then reset
     if ((highpulse >= MAXPULSE) && (currentpulse != 0)) {
       printpulses();
       currentpulse=0;
       return;
     }
  }
  // we didn't time out so lets stash the reading
  pulses[currentpulse][0] = highpulse;

  // same as above
  while (! (IRpin_PIN & _BV(IRpin))) {
     // pin is still LOW
     lowpulse++;
     delayMicroseconds(RESOLUTION);
     if ((lowpulse >= MAXPULSE)  && (currentpulse != 0)) {
       printpulses();
       currentpulse=0;
       return;
     }
  }
  pulses[currentpulse][1] = lowpulse;

  // we read one high-low pulse successfully, continue!
  currentpulse++;
}

void printpulses(void) {
  Serial.println("\n\r\n\rReceived: \n\rOFF \tON");
  for (uint8_t i = 0; i < currentpulse; i++) {
    Serial.print(pulses[i][0] * RESOLUTION, DEC);
    Serial.print(" usec, ");
    Serial.print(pulses[i][1] * RESOLUTION, DEC);
    Serial.println(" usec");
  }
}

// Sketch uses 2,354 bytes (7%) of program storage space. Maximum is 32,256 bytes.
// Global variables use 659 bytes (32%) of dynamic memory, leaving 1,389 bytes for local variables. Maximum is 2,048 bytes.

O segundo código para o Arduino foi desenvolvido pelo Ken Shirriff e o sketch apresentado é um dos exemplos que vem na biblioteca dele - IRremote.

Esta biblioteca pode ser descarregada do seguinte link. Pode igualmente ser descarregado daqui.

/*
 * IRremote: IRrecvDump - dump details of IR codes with IRrecv
 * An IR detector/demodulator must be connected to the input RECV_PIN.
 * Version 0.1 July, 2009
 * Copyright 2009 Ken Shirriff
 * http://arcfn.com
 * JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post)
 * LG added by Darryl Smith (based on the JVC protocol)
 */

#include <IRremote.h>

int RECV_PIN = 11;

IRrecv irrecv(RECV_PIN);

decode_results results;

void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
}

// Dumps out the decode_results structure.
// Call this after IRrecv::decode()
// void * to work around compiler issue
//void dump(void *v) {
//  decode_results *results = (decode_results *)v
void dump(decode_results *results) {
  int count = results->rawlen;
  if (results->decode_type == UNKNOWN) {
    Serial.print("Unknown encoding: ");
  }
  else if (results->decode_type == NEC) {
    Serial.print("Decoded NEC: ");
  }
  else if (results->decode_type == SONY) {
    Serial.print("Decoded SONY: ");
  }
  else if (results->decode_type == RC5) {
    Serial.print("Decoded RC5: ");
  }
  else if (results->decode_type == RC6) {
    Serial.print("Decoded RC6: ");
  }
  else if (results->decode_type == PANASONIC) {
    Serial.print("Decoded PANASONIC - Address: ");
    Serial.print(results->panasonicAddress,HEX);
    Serial.print(" Value: ");
  }
  else if (results->decode_type == LG) {
     Serial.print("Decoded LG: ");
  }
  else if (results->decode_type == JVC) {
     Serial.print("Decoded JVC: ");
  }
  Serial.print(results->value, HEX);
  Serial.print(" (");
  Serial.print(results->bits, DEC);
  Serial.println(" bits)");
  Serial.print("Raw (");
  Serial.print(count, DEC);
  Serial.print("): ");

  for (int i = 0; i < count; i++) {
    if ((i % 2) == 1) {
      Serial.print(results->rawbuf[i]*USECPERTICK, DEC);
    }
    else {
      Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC);
    }
    Serial.print(" ");
  }
  Serial.println("");
}


void loop() {
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    dump(&results);
    irrecv.resume(); // Receive the next value
  }
}

// Sketch uses 10,618 bytes (32%) of program storage space. Maximum is 32,256 bytes.
// Global variables use 628 bytes (30%) of dynamic memory, leaving 1,420 bytes for local variables. Maximum is 2,048 bytes.