Difference between revisions of "IR Sensor"

From LinkSprite Playgound
Jump to: navigation, search
(Additional Sources on IR Remote Control)
Line 86: Line 86:
  
 
=== Background on IR codes ===
 
=== Background on IR codes ===
 +
 +
An IR remote works by turning the LED on and off in a particular pattern.  However, to prevent interference from IR sources such as sunlight or lights, the LED is not turned on steadily, but is turned on and off at a modulation frequency (typically 36, 38, or 40KHz).  The time when a modulated signal is being sent will be called a mark, and when the LED is off will be called a space.
 +
 +
Each key on the remote has a particular code (typically 12 to 32 bits) associated with it, and broadcasts this code when the key is pressed.  If the key is held down, the remote usually repeatedly broadcasts the key code.  For an NEC remote, a special repeat code is sent as the key is held down, rather than repeatedly sending the code.  For Philips RC5 or RC6 remotes, a bit in the code is toggled each time a key is pressed.  The receiver uses this toggle bit to determine when a key is pressed down a second time.
 +
 +
On the receiving end, the IR detector demodulates this signal, and outputs a logic-level signal indicating if it is receiving a signal or not.  The IR detector will work best when its frequency matches the sender's frequency, but in practice it doesn't matter a whole lot.
 +
 +
=== Handling Raw Codes ===
 +
 +
The library provides support for sending and receiving raw durations.  This is intended mainly for debugging, but can also be used for protocols the library doesn't implement, or to provide universal remote functionality.
 +
 +
The raw data for received IR measures the duration of successive spaces and marks in 50us ticks.  The first measurement is the gap, the space before the transmission starts.  The last measurement is the final mark.
 +
 +
The raw data for sending IR holds the duration of successive marks and spaces in microseconds.  The first value is the first mark, and the last value is the last mark.
 +
 +
There are two differences between the raw buffers for sending and for receiving.  The send buffer values are in microseconds, while the receive buffer values are in 50 microsecond ticks.  The send buffer starts with the duration of the first mark, while the receive buffer starts with the duration of the gap space before the first mark.  The formats are different because it useful for the library to measure gaps between transmissions, but not useful for the library to provide these gaps when transmitting. 
 +
 +
For receiving, 50us granularity is sufficient for decoding and avoids overflow of the gaps, while for transmitting, 50us granularity is more than 10% error so 1us granularity seemed better.
 +
 +
===  Obtaining Codes for Your Remote ===
 +
 +
The easiest way to obtain codes to work with your device is to use this library to decode and print the codes from your existing remote.
 +
 +
Various libraries of codes are available online, often in proprietary formats. The Linux infrared Remote Control project (LIRC), however, has an open format for describing codes for many remotes.  Note that even if you can't find codes for your exact device model, a particular manufacturer will usually use the same codes for multiple products.
 +
 +
Beware that other sources may be inconsistent in how they handle these protocols, for instance reversing the order, flipping 1 and 0 bits, making start bits explicit, dropping leading or trailing bits, etc.  In other words, if the “IRremote” library yields different codes than you find listed elsewhere, these inconsistencies are probably why.
 +
 +
=== Details of the Receiving Library ===
 +
 +
The “IRrecv” library consists of two parts.  An interrupt routine is called every 50 microseconds, measures the length of the marks and spaces, and saves the durations in a buffer.  The user calls a decoding routine to decode the buffered measurements into the code value that was sent (typically 11 to 32 bits).
 +
 +
The decode library tries decoding different protocols in succession, stopping if one succeeds.  It returns a structure that contains the raw data, the decoded data, the number of bits in the decoded data, and the protocol used to decode the data.
 +
 +
For decoding, the match macro determine if the measured mark or space time is approximately equal to the expected time.
 +
 +
The RC5/6 decoding is a bit different from the others because RC5/6 encode bits with mark + space or space + mark, rather than by durations of marks and spaces.  The get RC level helper method splits up the durations and gets the mark/space level of a single time interval.
 +
 +
For repeated transmissions (button held down), the decoding code will return the same decoded value over and over.  The exception is NEC, which sends a special repeat code instead of repeating the transmission of the value.  In this case, the decoding routine returns a special repeat value.
 +
 +
In more detail, the receiver’s interrupt code is called every time the Timer1 overflows, which is set to happen after 50 microseconds.  At each interrupt, the input status is checked and the timer counter is incremented.  The interrupt routine times the durations of marks (receiving a modulated signal) and spaces (no signal received), and records the durations in a buffer.  The first duration is the length of the gap before the transmission starts.  This is followed by alternating mark and space measurements.  All measurements are in “ticks” of 50 microseconds.
 +
 +
The interrupt routine is implemented as a state machine.  It starts in “STATE_IDLE”, which waits for the gap to end.  When a mark is received, it moves to “STATE_MARK” which times the duration of the mark.  It then alternates between “STATE_MARK” and “STATE_SPACE” to time marks and spaces.  When a space of sufficiently long duration is received, the state moves to “STATE_STOP”, indicating a full transmission is received.  The interrupt routine continues to time the gap, but blocks in this state.
 +
 +
The “STATE_STOP” is used a flag to indicate to the decode routine that a full transmission is available.  When processing is done, the resume() method sets the state to “STATE_IDLE” so the interrupt routine can start recording the next transmission.  There are a few things to note here.  Gap timing continues during “STATE_STOP” and “STATE_IDLE” so an accurate measurement of the time between transmissions can be obtained.  If resume() is not called before the next transmission starts, the partial transmission will be discarded.  The motivation behind the stop/resume is to ensure the receive buffer is not overwritten while it is still being processed.  Debugging becomes very difficult if the buffer is constantly changing.

Revision as of 09:44, 7 December 2012

Introduction

The IR sensor is miniaturized receivers for infrared remote control systems.

The pin diode and preamplifier are assembled on lead frame, the epoxy package is designed as IR filter.

The demodulated output signal can directly be decoded by a microprocessor. The IR sensor is the standard IR remote control receiver series, supporting all major transmission codes.

IR sensor.jpg

Example Project

Hardware Setup

We can use any of the digital input signals to receive the input from a 38KHz IR receiver module.

Simply wire power to pin 1, ground to pin 2, and the pin 3 output to an arduino digital input pin, e.g. 11.

These receivers provide a filtered and demodulated inverted logic level output. You can't just use a photodiode or phototransistor. These detectors have pretty good range and easily work across a room.

Hardware setup.jpg

For output, connect an IR LED and appropriate resistor to PWM output pin 3. Make sure the polarity of the LED is correct, or it won't illuminate - the long lead is positive.

How to send

This infrared remote library consists of two parts: the “IRsend” transmits IR remote packets, while the “IRrecv” receives and decodes an IR message. The “IRsend” uses an infrared LED connected to output pin 3.

To send a message, call the send method for the desired protocol with the data to send and the number of bits to send. The “examples/IRsendDemo” sketch provides a simple example of how to send codes:

<syntaxhighlight lang="c">

  1. include <IRremote.h>

IRsend irsend;

void setup() {

 Serial.begin(9600);

}

void loop() {

 if (Serial.read() != -1) {
   for (int i = 0; i < 3; i++) {
     irsend.sendSony(0xa90, 12); // Sony TV power code
     delay(100);
   }
 }

}

</syntaxhighlight>

This sketch sends a Sony TV power on/off code whenever a character is sent to the serial port, allowing the arduino to turn the TV on or off. (Note that Sony codes must be sent 3 times according to the protocol.)

How to receive

The “IRrecv” uses an infrared detector connected to any digital input pin.

The “examples/IRrecvDemo” sketch provides a simple example of how to receive codes:

<syntaxhighlight lang="c">

  1. include <IRremote.h>

int RECV_PIN = 11; IRrecv irrecv(RECV_PIN); decode_results results;

void setup() {

 Serial.begin(9600);
 irrecv.enableIRIn(); // Start the receiver

}

void loop() {

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

}

</syntaxhighlight>

The “IRrecv” class performs the decoding, and is initialized with enableIRIn(). The decode() method is called to see if a code has been received. If so, it returns a nonzero value and puts the results into the decode_results structure. (For details of this structure, see the “examples/IRrecvDump” sketch.) Once a code has been decoded, the resume() method must be called to resume receiving codes. Note that decode() does not block. The sketch can perform other operations while waiting for a code because the codes are received by an interrupt routine.

Additional Sources on IR Remote Control

Background on IR codes

An IR remote works by turning the LED on and off in a particular pattern. However, to prevent interference from IR sources such as sunlight or lights, the LED is not turned on steadily, but is turned on and off at a modulation frequency (typically 36, 38, or 40KHz). The time when a modulated signal is being sent will be called a mark, and when the LED is off will be called a space.

Each key on the remote has a particular code (typically 12 to 32 bits) associated with it, and broadcasts this code when the key is pressed. If the key is held down, the remote usually repeatedly broadcasts the key code. For an NEC remote, a special repeat code is sent as the key is held down, rather than repeatedly sending the code. For Philips RC5 or RC6 remotes, a bit in the code is toggled each time a key is pressed. The receiver uses this toggle bit to determine when a key is pressed down a second time.

On the receiving end, the IR detector demodulates this signal, and outputs a logic-level signal indicating if it is receiving a signal or not. The IR detector will work best when its frequency matches the sender's frequency, but in practice it doesn't matter a whole lot.

Handling Raw Codes

The library provides support for sending and receiving raw durations. This is intended mainly for debugging, but can also be used for protocols the library doesn't implement, or to provide universal remote functionality.

The raw data for received IR measures the duration of successive spaces and marks in 50us ticks. The first measurement is the gap, the space before the transmission starts. The last measurement is the final mark.

The raw data for sending IR holds the duration of successive marks and spaces in microseconds. The first value is the first mark, and the last value is the last mark.

There are two differences between the raw buffers for sending and for receiving. The send buffer values are in microseconds, while the receive buffer values are in 50 microsecond ticks. The send buffer starts with the duration of the first mark, while the receive buffer starts with the duration of the gap space before the first mark. The formats are different because it useful for the library to measure gaps between transmissions, but not useful for the library to provide these gaps when transmitting.

For receiving, 50us granularity is sufficient for decoding and avoids overflow of the gaps, while for transmitting, 50us granularity is more than 10% error so 1us granularity seemed better.

Obtaining Codes for Your Remote

The easiest way to obtain codes to work with your device is to use this library to decode and print the codes from your existing remote.

Various libraries of codes are available online, often in proprietary formats. The Linux infrared Remote Control project (LIRC), however, has an open format for describing codes for many remotes. Note that even if you can't find codes for your exact device model, a particular manufacturer will usually use the same codes for multiple products.

Beware that other sources may be inconsistent in how they handle these protocols, for instance reversing the order, flipping 1 and 0 bits, making start bits explicit, dropping leading or trailing bits, etc. In other words, if the “IRremote” library yields different codes than you find listed elsewhere, these inconsistencies are probably why.

Details of the Receiving Library

The “IRrecv” library consists of two parts. An interrupt routine is called every 50 microseconds, measures the length of the marks and spaces, and saves the durations in a buffer. The user calls a decoding routine to decode the buffered measurements into the code value that was sent (typically 11 to 32 bits).

The decode library tries decoding different protocols in succession, stopping if one succeeds. It returns a structure that contains the raw data, the decoded data, the number of bits in the decoded data, and the protocol used to decode the data.

For decoding, the match macro determine if the measured mark or space time is approximately equal to the expected time.

The RC5/6 decoding is a bit different from the others because RC5/6 encode bits with mark + space or space + mark, rather than by durations of marks and spaces. The get RC level helper method splits up the durations and gets the mark/space level of a single time interval.

For repeated transmissions (button held down), the decoding code will return the same decoded value over and over. The exception is NEC, which sends a special repeat code instead of repeating the transmission of the value. In this case, the decoding routine returns a special repeat value.

In more detail, the receiver’s interrupt code is called every time the Timer1 overflows, which is set to happen after 50 microseconds. At each interrupt, the input status is checked and the timer counter is incremented. The interrupt routine times the durations of marks (receiving a modulated signal) and spaces (no signal received), and records the durations in a buffer. The first duration is the length of the gap before the transmission starts. This is followed by alternating mark and space measurements. All measurements are in “ticks” of 50 microseconds.

The interrupt routine is implemented as a state machine. It starts in “STATE_IDLE”, which waits for the gap to end. When a mark is received, it moves to “STATE_MARK” which times the duration of the mark. It then alternates between “STATE_MARK” and “STATE_SPACE” to time marks and spaces. When a space of sufficiently long duration is received, the state moves to “STATE_STOP”, indicating a full transmission is received. The interrupt routine continues to time the gap, but blocks in this state.

The “STATE_STOP” is used a flag to indicate to the decode routine that a full transmission is available. When processing is done, the resume() method sets the state to “STATE_IDLE” so the interrupt routine can start recording the next transmission. There are a few things to note here. Gap timing continues during “STATE_STOP” and “STATE_IDLE” so an accurate measurement of the time between transmissions can be obtained. If resume() is not called before the next transmission starts, the partial transmission will be discarded. The motivation behind the stop/resume is to ensure the receive buffer is not overwritten while it is still being processed. Debugging becomes very difficult if the buffer is constantly changing.