2

This is something I'm struggling with for a while and fail to find solid solution. The Arduino IR library provides method for recording arbitrary IR code and re-sending it. This gave me different results every time I recorded the IR remote, so I wrote a little code, based on interrupts, that try to record the IR rise/fall as accurately as possible. I am working with ATTiny85 running at 8Mhz on internal oscillator.

Here is the code:

#include <SoftwareSerial.h>

SoftwareSerial mySerial(4,3);

const int dataSize = 40;
int data[dataSize];
int dataLength[dataSize];


void setup() {
  pinMode(0, OUTPUT); // 0 is IR receiver pin
  mySerial.begin(9600);
  mySerial.println("Start");
  attachInterrupt(0,IR_ISR,CHANGE); 
  mySerial.println("Registered");
  sei();
}
volatile unsigned long prev = micros();
volatile unsigned long curr = -1;
volatile unsigned short index = 0;
volatile bool rising = true;
void IR_ISR()
{
  if (!rising)
  {
    dataLength[index] = micros() - curr;
    rising = !rising;
    return;
  }

  curr = micros();

  data[index++] = (int)curr-prev;

  prev = curr; 
  rising = !rising;
}

void loop() {

  delay(5000);
  for (int i=1; i<dataSize; i++)
  {
    mySerial.print(data[i]);
    mySerial.print("(");
    mySerial.print(dataLength[i]);
    mySerial.print(")");
    mySerial.print("; ");
  }
  mySerial.println();
  index = 0;
}

Problem is that the milliseconds alter on each record of the remote control, here is an example of the output of 3 attempts of clicking at the same button of the remote control (I pasted only the first 5 IR modulations to avoid too much text, total is about 39):

Start
Registered

14104(9496); 1184(672); 1184(616); 1160(656); 1176(672); ...

14096(9480); 1184(664); 1208(568); 1136(616); 1184(664); ...

14096(9384); 1216(576); 1136(616); 1184(664); 1208(560); ...

The format is: [microseconds from previous falling edge](microseconds from rise to fall);

As you can see, the results vary. According to the arduino.cc website, the micros() function has a 8 microseconds resolution on 8Mhz AVR's, but the difference between reads is bigger than that.

This is not reliable enough for me to solidly duplicate a remote control, and I'm looking for a resolution that will provide accurate results, as the magnitude of every deviation increases when the voltages are low (for example, with a 3v 2032 coin battery half discharged).

  • While the AVR is 8MHz, there is latency to service the ISR. Hence your observed differences. – mpflaga Aug 6 '14 at 14:53
  • This is true that ISR has some delay and does not provide real time values, but if what you say is correct, I should have measured the same deviation on every attempt, and this is not happening. – Omer Aug 6 '14 at 16:36
3

The exact duration of the pulses don't matter much. In your example, you see that in all three recorded samples that's

about 14000 (about 9400); about 1200 (about 600); about 1200 (about 600) etc.

What matters is that nowhere you have pulses of about 900 : in other words if the receiver detects a 672 pulse it will know that it's definitely a 600, not a 1200.

So if you send exactly those values, the receiver will recognize it.

  • That's an interesting observation; do you have a thumb rule about the rounding? – Omer Aug 6 '14 at 9:06
  • 1
    I use 412-712 for detect a zero, and 1187-2187 for detecting a one. 412-712 for the ir-burst between them. It looks like the remote is using the NEC protocol. I actually used excel to convert the raw data into a number, and to test if the boundaries were sufficient. I actually had to increase the boundaries a few times to catch the IR signal reliably. The values above are what I ended up with. – Gerben Aug 6 '14 at 14:46
  • I used NEC remote for the post, but my intention is to reliably adjust to any custom protocol. Hence I am not sure that NEC values will suite me. Also, my final goal is to make the entire processing dynamically on the AVR itself, making it a real adjustable remote control, thus excel is not an option here :) I'll try to play with the rounding using code, see if that helps (if it will do the trick, I'll accept your answer). – Omer Aug 6 '14 at 16:35
  • Just sample n times the same code, and record the averages of pulse lengths. If you reemit that, you'll be sure you sent the same code. The way that code is interpreted by the receiver (NEC, rc-6, whatever) is irrelevant. – Nicolas D Aug 8 '14 at 5:19
  • Eventually I decided not to use ATtiny85 since, even if using PROGMEM, it's just not up to the job of being a 'universal remote control', memory wise. But this is indeed the correct answer to my question. – Omer Feb 14 '15 at 18:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.