Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Identify a specific IR message with an Arduino
//------------------------------------------------------------------------------
// Interrupt 0 fires on pin D2
#define IR_PIN 2
// the maximum pulse we'll listen for
#define MAX_PULSE 30000
// the largest message we expect to receive (in bits)
#define MAX_MSG_SIZE 50
// These variables hold the info for the incoming IR message. If we have received
// a message, then these will hold the message length and the pulse width values.
// We'll store up to 50 pulse pairs (high and low), which is more than enough.
volatile uint8_t ir_msg_len = 0;
volatile uint16_t ir_msg[MAX_MSG_SIZE*2]; // pair is high and low pulse
//------------------------------------------------------------------------------
// Initialize the arduino, attach the interrupt that will fire whenever pin 2
// goes HIGH. (On the Uno, interrupt 0 goes to pin D2, but it depends on the
// model
void setup() {
Serial.begin(9600);
attachInterrupt( 0, captureIR, RISING );
Serial.println("Ready to capture message");
}
//------------------------------------------------------------------------------
// The loop function now does whatever you would normally want it to do, but
// each time through the loop, it'll look to see if a message is available, and
// then test to see if it's the target sequence (in my case, the power button
// on an old CD player remote, but use whatever you have around and paste in
// the result from ir_record.
void loop() {
// ... do your own thing ...
if (ir_msg_len > 0) {
if (is_match()) {
Serial.println("You pressed the right button!");
}
else {
Serial.println("You pressed some other button :(");
}
ir_msg_len = 0;
}
}
//------------------------------------------------------------------------------
// captureIR() captures the pulse-width data that is delivered to pin 2 when
// an infrared message triggers the IR sensor.
unsigned long last_time = 0;
const float cycle_time = (1.0/36000.0)*1000000; // 27.7778 uS per cycle
void captureIR() {
// If the previous call came in less than 0.25 seconds ago, just ignore it.
unsigned long now = micros();
if (now - last_time < 250000)
return;
last_time = now;
// Track the pin as it rises and falls and record the time it spends in HIGH
// then LOW state. If we pass MAX_PULSE uS, the message is over.
unsigned long hightime, lowtime;
ir_msg_len = 0;
while (ir_msg_len < MAX_MSG_SIZE*2) {
hightime = pulseIn(IR_PIN, HIGH, MAX_PULSE);
lowtime = pulseIn(IR_PIN, LOW, MAX_PULSE);
if ( (hightime == 0) || (lowtime == 0) ) {
// Finished with message
return;
}
ir_msg[ir_msg_len++] = round(hightime/cycle_time);
ir_msg[ir_msg_len++] = round(lowtime/cycle_time);
}
}
//------------------------------------------------------------------------------
// The messages are often not exactly the same (it's all timing measurements,
// and things vary). Measure the variance (the sum of the errors squared)
// between the expected message and the one we have here.
//
// Allow for up to 3 cycles difference per measurement, that means we allow for
// a delta up to 18 per pulse pair. If the variance is less than 18*len, then
// we call it 'close enough', and if it's more than it is not.
// Replace vv-- this line here --vv to change what signal to listen for.
uint16_t target_seq[16*2] = { 14,17, 15,17, 15,17, 15,17, 15,17, 15,16, 16,16, 48,16, 15,16, 16,16, 47,16, 48,16, 47,15, 47,16, 47,16, 16,16 };
boolean is_match() {
uint32_t sum_of_squares = 0;
// start at two because the first pair can vary wildly based on initial
// timing, but it's possible I should be starting with 1.
for (uint8_t i = 2; i < ir_msg_len; i++) {
int16_t delta = ir_msg[i] - target_seq[i];
sum_of_squares += (delta*delta);
}
// the variance is the sum of the squares of the error, divided by the
// size of the input.
uint16_t variance = sum_of_squares/(sizeof(target_seq)/sizeof(target_seq[0]));
Serial.print("variance: ");
Serial.println(variance);
// Call it a match if the average difference per reading is 3uS or less (squared).
return variance < 3*3;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.