Replicate BenQ IR remote

I am trying to get the arduino to replicate a IR remote from an BenQ W100 projector. I only need to replicate the power button.

So what I figured from searching the forum and the playgorund is. I need a IR reciever (that isn't a problem), and if I understand correctly this piece of code:
http://www.arduino.cc/playground/Code/InfraredReceivers

So if I am correct, I can get the IR code from the remote, the main question is - How can I replicate the button with arduino?

If you want to send the IR signal based on time, just include however much time delay you need. If you want to manually trigger it, hook a button up to one of the pins, and wait for a button press to execute the code.

Or are you asking how to actually transmit the IR signal?

Or are you asking how to actually transmit the IR signal?

This is what I want! ;D Me and english don't go well together ;D.

I used the program on that link and this is the result that I got using gnuplot:

What now? I have this so what can I do with it?

Looks good, now the next step would be to create a program that will digital write to an IR led at that modulation frequency. there are lots of examples around the forum (search IR remote, NEC or rc5). there is even an oscillationwrite function that will write at ~38khz floating around. Im guessing thats what your modulation freq is. Since you only want to use the power button, you can just store the pulse length values in an array and oscillationwrite them to the led. If you want more functions, it would be a good idea to convert pulse lengths to some sort of logic array then an integer you can define.

[edit]: one thing to watch out for is that some IR receivers are pin high when they are not receiving a signal and pin low when the tx led is high. this just means you might have to invert the signal you got from your ir receiver.

Maybe a little more information? Or much more :o.

I am looking at different IR protocols and arduino code, but I can't understand what the hell is going on there >:(. Some pulses, ones and zeroes.... I read the info about how these IR protocols work but I can't understand the half of it. I don't even know what IR reciever I am using - found it in an old satelite reciever years ago (probably something from VISHAY - and if I can read correctly there is something about 36Hz modulation).

Here is the data part of that image:

0              0
9008              0
9008              1
13540      1
13540      0
14100      0
14100      1
15796      1
15796      0
16360      0
16360      1
16936      1
16936      0
17472      0
17472      1
19168      1
19168      0
19728      0
19728      1
21424      1
21424      0
21988      0
21988      1
22564      1
22564      0
23124      0
23124      1
23704      1
23704      0
24268      0
24268      1
24844      1
24844      0
25412      0
25412      1
27180      1
27180      0
27720      0
27720      1
28300      1
28300      0
28860      0
28860      1
30556      1
30556      0
31116      0
31116      1
31696      1
31696      0
32256      0
32256      1
32840      1
32840      0
33400      0
33400      1
35096      1
35096      0
35632      0
35632      1
37324      1
37324      0
37884      0
37884      1
39580      1
39580      0
40140      0
40140      1
40828      1
40828      0
41392      0
41392      1
41968      1
41968      0
42528      0
42528      1
43108      1
43108      0
43676      0
43676      1
44252      1
44252      0
44816      0
44816      1
45400      1
45400      0
45956      0
45956      1
46532      1
46532      0
47096      0
47096      1
47672      1
47672      0
48240      0
48240      1
48820      1
48820      0
49380      0
49380      1
50068      1
50068      0
50600      0
50600      1
52296      1
52296      0
52856      0
52856      1
54552      1
54552      0
55112      0
55112      1
56808      1
56808      0
57344      0
57344      1
59040      1
59040      0
59604      0
59604      1
61296      1
61296      0
61856      0
61856      1
63552      1
63552      0
64084      0
64084      1

Ill try to give you a lot more info: :wink:
A majority of IR protocols work using a 36-40kHz modulation frequency also known as the carrier frequency. The meat and potatoes of each protocol is different but from a quick glance yours works as such:
1st. Header which is high and significantly longer than any other place in the code. It signifies to the receiver that the data is coming and can also be used to calibrate intensity
2nd. Lows of all uniform length. Because of this, they cannot carry any information.
3rd. Highs of varying lengths. This most likely means these are the data carriers of the signal. They transmit a binary code based on how long the high (led on oscillating at carrier freq) lasts. For your specific protocol, a binary one might be the longer high value, and the binary low might be the shorter high value.
For example, your data starts out as header, 1011000101.
The data usually terminates with a very long pinstate (usually low) and then repeats the same info starting with the header for as long as the button to transmit is held down.
For your project, since you only need to send one button(power), you shouldnt need to worry about decoding the protocol. All you need is to record how long the pulses stay on and off for and send them at the right carrier freq to the projector.
Try using this slightly modified ir analyzer program to find out the pulse lengths (only change is it subtracts one pulse time from the next to give length)

#include <avr/interrupt.h>
#include <avr/io.h>

#define TIMER_RESET  TCNT1 = 0
#define SAMPLE_SIZE  128

int txpin=7;
int IRpin = 2;
unsigned int TimerValue[SAMPLE_SIZE];
char direction[SAMPLE_SIZE];
byte change_count;
long time;
long time2;

void setup() {
  Serial.begin(115200);
  Serial.println("Analyze IR Remote");
  TCCR1A = 0x00;          // COM1A1=0, COM1A0=0 => Disconnect Pin OC1 from Timer/Counter 1 -- PWM11=0,PWM10=0 => PWM Operation disabled
  // ICNC1=0 => Capture Noise Canceler disabled -- ICES1=0 => Input Capture Edge Select (not used) -- CTC1=0 => Clear Timer/Counter 1 on Compare/Match
  // CS12=0 CS11=1 CS10=1 => Set prescaler to clock/64
  TCCR1B = 0x03;          // 16MHz clock with prescaler means TCNT1 increments every 4uS
  // ICIE1=0 => Timer/Counter 1, Input Capture Interrupt Enable -- OCIE1A=0 => Output Compare A Match Interrupt Enable -- OCIE1B=0 => Output Compare B Match Interrupt Enable
  // TOIE1=0 => Timer 1 Overflow Interrupt Enable
  TIMSK1 = 0x00;          
  pinMode(IRpin, INPUT);
}

void loop()
{
  Serial.println("Waiting...");
  change_count = 0;
  while(digitalRead(IRpin) == HIGH) {}                                 
  TIMER_RESET;
  TimerValue[change_count] = TCNT1;
  direction[change_count++] = '0';
  while (change_count < SAMPLE_SIZE) {
    if (direction[change_count-1] == '0') {
      while(digitalRead(IRpin) == LOW) {}
      TimerValue[change_count] = TCNT1;
      direction[change_count++] = '1';
    } else {
      while(digitalRead(IRpin) == HIGH) {}
      TimerValue[change_count] = TCNT1;
      direction[change_count++] = '0';
    }
  }
  Serial.println("Bit stream detected!");
  change_count = 0;
  time = (long) TimerValue[change_count] * 4;
  time2 = (long) TimerValue[change_count+1] * 4;
  Serial.print(time2-time);
  Serial.print("\t");
  Serial.println(direction[++change_count]);
  while (change_count < SAMPLE_SIZE) {
    time = (long) TimerValue[change_count] * 4;
    time2 =(long) TimerValue[change_count+1] * 4;
    Serial.print(time2-time);
    Serial.print("\t");
    Serial.println(direction[++change_count]);    
  }
  Serial.println("Bit stream end!");
  delay(2000);
}

Here is the output of that script. The last bit is a little strange.

9028      1
4564      0
556      1
1672      0
588      1
580      0
560      1
1668      0
556      1
1728      0
532      1
584      0
580      1
564      0
560      1
552      0
584      1
1748      0
576      1
568      0
556      1
1700      0
560      1
608      0
508      1
580      0
568      1
1716      0
560      1
1696      0
528      1
1700      0
560      1
688      0
556      1
560      0
608      1
556      0
584      1
564      0
552      1
588      0
556      1
584      0
552      1
564      0
608      1
532      0
584      1
664      0
608      1
1652      0
576      1
1648      0
584      1
1672      0
584      1
1700      0
556      1
1652      0
580      1
1696      0
588      1
1644      0
584      1
1620      0
584      1
39124      0
9028      1
4540      0
552      1
1704      0
584      1
556      0
532      1
1700      0
556      1
1700      0
556      1
584      0
580      1
560      0
556      1
588      0
556      1
1776      0
532      1
584      0
560      1
1696      0
556      1
584      0
560      1
584      0
560      1
1696      0
528      1
1700      0
560      1
1696      0
560      1
688      0
556      1
584      0
560      1
584      0
560      1
584      0
552      1
588      0
556      1
588      0
560      1
580      0
556      1
584      0
584      1
664      0
528      1
1728      0
528      1
1704      0
556      1
1700      0
504      1
1724      0
580      1
-117016      ?

The last one looks like a variable with too litle space. Or a simple error :P.

If I understand this correctly, these are durations of the on-of pulses. So I need to send these pulses to the projector to tun it on. Only question is how? PRobably it isn't as simple as turning IR LED on and of for specified time?

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1176098434
Seventh post from the top by david cuartielles at the bottom of sender is the oscillationwrite() function you want. as is, it will flash the pin at ~38Khz. So by a combo of oscillationwrite for highs at the right pulse length and delaymicroseconds for lows, you can use just an ir led and a resistor. And remember that depending on the IR receiver you use, you may have to invert the values oh highs and lows. So try one way first, if that doesnt work switch oscillationwrites with delaymicroseconds and vice versa

And the last reading on the code i posted is always messed up as a result of quick and dirty programming. just ignore it entirely.

So this is what I did:

#define ir 13

int vrednost(int stevilka)
{
  int vrednost = 0;
  int xx[127];
  xx[0] =       1      ;
xx[1] =      0      ;
xx[2] =       1      ;
xx[3] =      0      ;
xx[4] =       1      ;
xx[5] =      0      ;
xx[6] =       1      ;
xx[7] =      0      ;
xx[8] =       1      ;
xx[9] =      0      ;
xx[10] =       1      ;
xx[11] =      0      ;
xx[12] =       1      ;
xx[13] =      0      ;
xx[14] =       1      ;
xx[15] =      0      ;
xx[16] =       1      ;
xx[17] =      0      ;
xx[18] =       1      ;
xx[19] =      0      ;
xx[20] =       1      ;
xx[21] =      0      ;
xx[22] =       1      ;
xx[23] =      0      ;
xx[24] =       1      ;
xx[25] =      0      ;
xx[26] =       1      ;
xx[27] =      0      ;
xx[28] =       1      ;
xx[29] =      0      ;
xx[30] =       1      ;
xx[31] =      0      ;
xx[32] =       1      ;
xx[33] =      0      ;
xx[34] =       1      ;
xx[35] =      0      ;
xx[36] =       1      ;
xx[37] =      0      ;
xx[38] =       1      ;
xx[39] =      0      ;
xx[40] =       1      ;
xx[41] =      0      ;
xx[42] =       1      ;
xx[43] =      0      ;
xx[44] =       1      ;
xx[45] =      0      ;
xx[46] =       1      ;
xx[47] =      0      ;
xx[48] =       1      ;
xx[49] =      0      ;
xx[50] =       1      ;
xx[51] =      0      ;
xx[52] =       1      ;
xx[53] =      0      ;
xx[54] =       1      ;
xx[55] =      0      ;
xx[56] =       1      ;
xx[57] =      0      ;
xx[58] =       1      ;
xx[59] =      0      ;
xx[60] =       1      ;
xx[61] =      0      ;
xx[62] =       1      ;
xx[63] =      0      ;
xx[64] =       1      ;
xx[65] =      0      ;
xx[66] =       1      ;
xx[67] =      0      ;
xx[68] =       1      ;
xx[69] =      0      ;
xx[70] =       1      ;
xx[71] =      0      ;
xx[72] =       1      ;
xx[73] =      0      ;
xx[74] =       1      ;
xx[75] =      0      ;
xx[76] =       1      ;
xx[77] =      0      ;
xx[78] =       1      ;
xx[79] =      0      ;
xx[80] =       1      ;
xx[81] =      0      ;
xx[82] =       1      ;
xx[83] =      0      ;
xx[84] =       1      ;
xx[85] =      0      ;
xx[86] =       1      ;
xx[87] =      0      ;
xx[88] =       1      ;
xx[89] =      0      ;
xx[90] =       1      ;
xx[91] =      0      ;
xx[92] =       1      ;
xx[93] =      0      ;
xx[94] =       1      ;
xx[95] =      0      ;
xx[96] =       1      ;
xx[97] =      0      ;
xx[98] =       1      ;
xx[99] =      0      ;
xx[100] =       1      ;
xx[101] =      0      ;
xx[102] =       1      ;
xx[103] =      0      ;
xx[104] =       1      ;
xx[105] =      0      ;
xx[106] =       1      ;
xx[107] =      0      ;
xx[108] =       1      ;
xx[109] =      0      ;
xx[110] =       1      ;
xx[111] =      0      ;
xx[112] =       1      ;
xx[113] =      0      ;
xx[114] =       1      ;
xx[115] =      0      ;
xx[116] =       1      ;
xx[117] =      0      ;
xx[118] =       1      ;
xx[119] =      0      ;
xx[120] =       1      ;
xx[121] =      0      ;
xx[122] =       1      ;
xx[123] =      0      ;
xx[124] =       1      ;
xx[125] =      0      ;
xx[126] =       1      ;
vrednost = xx[stevilka];
return vrednost;
}
int cas(int stevilka) 
{
int  vrednost = 0;
int xx[127];
xx[0] = 9028;
xx[      1] =      4564      ;
xx[       2] =       556      ;
xx[      3] =      1672      ;
xx[       4] =       588      ;
xx[       5] =       580      ;
xx[      6] =      560      ;
xx[       7] =       1668      ;
xx[      8] =      556      ;
xx[       9] =       1728      ;
xx[       10] =       532      ;
xx[      11] =      584      ;
xx[       12] =       580      ;
xx[      13] =      564      ;
xx[       14] =       560      ;
xx[       15] =       552      ;
xx[      16] =      584      ;
xx[       17] =       1748      ;
xx[      18] =      576      ;
xx[       19] =       568      ;
xx[       20] =       556      ;
xx[      21] =      1700      ;
xx[       22] =       560      ;
xx[      23] =      608      ;
xx[       24] =       508      ;
xx[       25] =       580      ;
xx[      26] =      568      ;
xx[       27] =       1716      ;
xx[      28] =      560      ;
xx[       29] =       1696      ;
xx[       30] =       528      ;
xx[      31] =      1700      ;
xx[       32] =       560      ;
xx[      33] =      688      ;
xx[       34] =       556      ;
xx[       35] =       560      ;
xx[      36] =      608      ;
xx[       37] =       556      ;
xx[      38] =      584      ;
xx[       39] =       564      ;
xx[       40] =       552      ;
xx[      41] =      588      ;
xx[       42] =       556      ;
xx[      43] =      584      ;
xx[       44] =       552      ;
xx[       45] =       564      ;
xx[      46] =      608      ;
xx[       47] =       532      ;
xx[      48] =      584      ;
xx[       49] =       664      ;
xx[       50] =       608      ;
xx[      51] =      1652      ;
xx[       52] =       576      ;
xx[      53] =      1648      ;
xx[       54] =       584      ;
xx[       55] =       1672      ;
xx[      56] =      584      ;
xx[       57] =       1700      ;
xx[      58] =      556      ;
xx[       59] =       1652      ;
xx[       60] =       580      ;
xx[      61] =      1696      ;
xx[       62] =       588      ;
xx[      63] =      1644      ;
xx[       64] =       584      ;
xx[       65] =       1620      ;
xx[      66] =      584      ;
xx[       67] =       39124      ;
xx[      68] =      9028      ;
xx[       69] =       4540      ;
xx[       70] =       552      ;
xx[      71] =      1704      ;
xx[       72] =       584      ;
xx[      73] =      556      ;
xx[       74] =       532      ;
xx[       75] =       1700      ;
xx[      76] =      556      ;
xx[       77] =       1700      ;
xx[      78] =      556      ;
xx[       79] =       584      ;
xx[       80] =       580      ;
xx[      81] =      560      ;
xx[       82] =       556      ;
xx[      83] =      588      ;
xx[       84] =       556      ;
xx[       85] =       1776      ;
xx[      86] =      532      ;
xx[       87] =       584      ;
xx[      88] =      560      ;
xx[       89] =       1696      ;
xx[       90] =       556      ;
xx[      91] =      584      ;
xx[       92] =       560      ;
xx[      93] =      584      ;
xx[       94] =       560      ;
xx[       95] =       1696      ;
xx[      96] =      528      ;
xx[       97] =       1700      ;
xx[      98] =      560      ;
xx[       99] =       1696      ;
xx[       100] =       560      ;
xx[      101] =      688      ;
xx[       102] =       556      ;
xx[      103] =      584      ;
xx[       104] =       560      ;
xx[       105] =       584      ;
xx[      106] =      560      ;
xx[       107] =       584      ;
xx[      108] =      552      ;
xx[       109] =       588      ;
xx[       110] =       556      ;
xx[      111] =      588      ;
xx[       112] =       560      ;
xx[      113] =      580      ;
xx[       114] =       556      ;
xx[       115] =       584      ;
xx[      116] =      584      ;
xx[       117] =       664      ;
xx[      118] =      528      ;
xx[       119] =       1728      ;
xx[       120] =       528      ;
xx[      121] =      1704      ;
xx[       122] =       556      ;
xx[      123] =      1700      ;
xx[       124] =       504      ;
xx[       125] =       1724      ;
xx[      126] =      580      ;
vrednost = xx[stevilka];
return vrednost;
}

void setup()
{
  pinMode(ir,OUTPUT);
}
void loop() 
{
for (int i =0;i<=126;i++)
{
  if (vrednost(i) == 1)
  {
    oscillationWrite(13,cas(i));
    
  }
  else
  {
    delayMicroseconds(cas(i));
  }
  
}
}

void oscillationWrite(int pin, int time) {
  for(int i = 0; i <= time/26; i++) {
    digitalWrite(pin, HIGH);
    delayMicroseconds(13);
    digitalWrite(pin, LOW);
    delayMicroseconds(13);
  }
}

Sory for spaces! I built that using excel :P.

It doesn't work. I tryed inverting the oscillationwrite and delaymicroseconds - no luck. The IR LED that I am using is from an old universal remote and my camera shows me it is working - even if it isn't realy strong. I tryed it pointing directly into the reciever but it didn't work.

So
a) I am complete idiot and did something realy stupid
b) Something is wrong

The first option sounds right because it is 3 in the morning here and I am going to bed ;D.

Have a look at an IR catching sketch I've written. It might be useful.

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1234957671

Plus I'm trying to catch air conditioner codes, but I'm in trouble due to my non-existent know-how, anyone with some suggestions?
I'll share the codes once I'll be able to capture them.

I have IR codes but I don't know how to send them correctly. So any ideas? Why isn't that code working?

And I burned my IR LED so I will need to buy some. Probably at the end of the month. So until then I am waiting for ideas!

I think your IR sensor is inverted and thus, your remotes IR code should be:
10110001010011100000000011111111
Which means:

device code:
10110001
device code inverted:
01001110

command code:
00000000
command code inverted:
11111111

First thing you need is to understand how the signal is sent. First you start with a 8ms preamble (oscillationWrite) followed by a 4ms OFF. After this:

0 = 560us oscillationWrite, 565us OFF
1 = 560us oscillationWrite, 1690us OFF

I'm no good at explaining things, but perhaps the code I finally got to work with my tv at home will make things a bit clearer. Simplified it a bit and added your IR code. The sketch below will wait for serial input and when it gets whatever data, it transmits your POWER IR-code.

int irPin = 13;
int data[32] = {0,1,0,0,1,1,1,0,1,0,1,1,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0};
int val;

void setup()
{
      pinMode(irPin, OUTPUT);
      Serial.begin(115200);
      Serial.println("System ready!");
}

void loop()
{

      if(Serial.available())
      {
            val = Serial.read();
            
            //send preamble
            oscWrite(irPin, 8000);
            delayMicroseconds(4000);

            //send data
            for(int i = 0; i < 32; i++)
            {
                  //space
                  oscWrite(irPin, 560);

                  //data
                  if(data[i] == '0')
                  {
                        delayMicroseconds(565);
                  }
                  else
                  {
                        delayMicroseconds(1690);
                  }
            }
            oscWrite(irPin, 560);
      }
}

void oscWrite(int pin, int time)
{
      for(int i = 0; i < (time / 26) - 1; i++)
      {
            digitalWrite(pin, HIGH);
            delayMicroseconds(13);
            digitalWrite(pin, LOW);
            delayMicroseconds(13);
      }
}

I will try it as soon as I get a new IR diode! >:(

EDIT: found one - but the code doesn't work!

I found something:

In that file that was attached to the original post is a spreadsheet with RS232 control codes and smaller spreadsheet for IR codes (I don't know if it means anything). So does this help in any way?

I know this is old, but I repurposed a tv-b-gone to emit the same exact code you were trying to do for a benq projector. You can check out the project here:

http://outroot.com/blog/2010/02/23/repurposed-tv-b-gone-to-turn-off-benq-projector/

It really wouldn't be hard to do this with a regular arduino. Just use this library: http://www.arcfn.com/2009/08/multi-protocol-infrared-remote-library.html and emit the code: B14E00FF to turn off/on the benq projector.