ir remote for canon digital camera

Hello,

I try to create a remote infrared controler from arduino. I begin to emulate the canon wl-dc100 remote because the only digital camera I have is a Canon one.
I find the ir code for this remote here http://www.icb.chel.su/~sapa/lj/rc/pic_v4m.asm and here http://lirc.sourceforge.net/remotes/canon/WL-DC100.
Unfortunatly my code doesn't seem to work. The IR led work (I can see it lighting with my digital camera) but the camera doesn't seem to responde to my ir.
Do you see anything strange in my code?

/* Exemple Emetteur WL-DC100    */
/* Jean-Christophe DURANTON 24/12/2007  */

#define LEDIR 3  // n° broche numérique de l'anode de la LED infrarouge  

int wldc_zero[]   = {612,512};
int wldc_one[]    = {612,1621};
int wldc_header[] = {9042,4379};
int wldc_ptrail[] = {599,107448}; 
int wldc_repeat[] = {9039,2115};
int wldc_bits     = 16;
int wldc_prebits  = 16;
int wldc_predata  = 0x538D;       // 0101001110001101
int wldc_snap     = 0xF807;        // 1111100000000111
int wldc_zoomin   = 0x42BD;     // 0100001010111101
int wldc_zoomout  = 0xC23D;    // 1100001000111101

void sendIRvalue(int value[])
{
  digitalWrite(LEDIR, HIGH);
  delayMicroseconds(value[0]);
  digitalWrite(LEDIR, LOW);
   delayMicroseconds(value[1]);
}  

void sendIRCodes(int hexval,int bytval)
{
  int cmp;
  int result[bytval];
  for(int itmp=0; itmp < bytval; itmp++) 
  {
    int cmp = 1 << itmp;
    if ((hexval | cmp) == hexval)
    {
      result[bytval-1-itmp] = 1;
    }else
    {
      result[bytval-1-itmp] = 0; 
    }
  }
  for(int jtmp=0; jtmp < bytval; jtmp++)
  {
    if(result[jtmp] == 1)
    {
      sendIRvalue(wldc_one);
    }else
    { 
      sendIRvalue(wldc_zero);
    }  
  }  
}

void setup ()
{
  pinMode (LEDIR, OUTPUT); 
}

void loop () 
{
  //header
  sendIRvalue(wldc_header);
  //predata
  sendIRCodes(wldc_predata,wldc_prebits); 
  //snap
  sendIRCodes(wldc_snap,wldc_bits);
  //ptrail
  sendIRvalue(wldc_ptrail);
  delay(5000);
}

Any help will be appreciated.
Have a good day.

The most likely reason that it isn't working is because the IR needs to oscillate at a certain frequency (Usually 38kHz) so the reciever can see it. This is what's known as a carrier signal.

I'm looking at porting the TV-B-Gone to the Arduino, and along my travels I've learnt that modifying the PWM timers isn't the best way to go for this. Look at the 555 Timer ICs, with the correct capacitor and resistor combo you should be able to oscillate your IR LED at the right frequency - to find the correct frequency check the manual or look to your friend google.

On that note, does anyone out there know what cap/resistor I should go for in order to get a 555 timer to put out a 37.916kHz oscillation? I'm not even sure if you can get that precise, 38kHz should do fine.

  • plasma

The Canon remote just sends out 2 bursts at a frequency of 32.6 kHz, delayed by either 5300 or 7300 ns

Hello,

I just did a little bit of research on the project. The Canon remote just sends out 2 bursts at a frequency of 32.6 kHz. More info can be found here:

It seems to be the same protocol as for the RC-5 remotes of the Canon EOS Rebel (AKA Canon EOS 350).

You can use the internal timers of the microcontroller to produce the required oscillation (burst frequency). Information on how to do this ca be found here:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1209565937

Here is my test code:

extern volatile unsigned long timer0_millis; //timer0_millis is defined in wiring.c

#ifndef cbi // Definitions for setting and clearing register bits
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

#define SYSCLOCK 16000000  // main system clock of Arduino Board (Hz)

#define IROUT 11    // pin 11 is OC2A output from TIMER2
#define LED 13

#define BURST_FREQUENCY 32600 //IR Burst Frequency in Hz

unsigned long time = 0;

unsigned long pulses[] = {500,5300,500};
unsigned int count = 3;
boolean toggle = LOW;

unsigned long microseconds();
void setup_timer2(unsigned int freq);
uint8_t timer2top(unsigned int freq) ;

//#########################################################

void setup()
{
  pinMode(LED, OUTPUT);
  pinMode(IROUT, OUTPUT) ;
  
  setup_timer2(BURST_FREQUENCY);
}

//#########################################################

void loop()
{ 
  TCNT0 = 0;
  time = microseconds();
  digitalWrite(LED, HIGH) ;
  sbi(TCCR2A,COM2A0) ;   // connect pulse clock
  for(int i=0;i<count;i++)
  {
    time = time + pulses[i];
    while(microseconds()<time){};
    if(toggle)
    {
      digitalWrite(LED, HIGH) ;
      sbi(TCCR2A,COM2A0) ;   // connect pulse clock
    }
    else
    {
      digitalWrite(LED, LOW) ;
      cbi(TCCR2A,COM2A0) ;   // disconnect pulse clock
    }
    toggle = !toggle;
    

  }
  toggle = LOW;
  delay(6000);
}

//#########################################################

// return TIMER2 TOP value per given desired frequency (Hz)
uint8_t timer2top(unsigned int freq)
{
  return((byte)((unsigned long)SYSCLOCK/2/freq) - 1) ;
}

void setup_timer2(unsigned int freq)
{
  cbi(TCCR2A,COM2A1); // disconnect OC2A for now (COM2A0 = 0)
  cbi(TCCR2A,COM2A0);
  
  cbi(TCCR2B,WGM22);  // CTC mode for TIMER2
  sbi(TCCR2A,WGM21);
  cbi(TCCR2A,WGM20);
  
  TCNT2 = 0;
  
  cbi(ASSR,AS2);  // use system clock for timer 2
  
  OCR2A = timer2top(freq);
  
  cbi(TCCR2B,CS22);  // TIMER2 prescale = 1
  cbi(TCCR2B,CS21);
  sbi(TCCR2B,CS20);
  
  cbi(TCCR2B,FOC2A);  // clear forced output compare bits
  cbi(TCCR2B,FOC2B);
}

unsigned long microseconds()
{
  return (timer0_millis * 1000 + 4*TCNT0);
}

Mor info on the the internal timers can be found in the ATMega168 documentation:

One little problem I noticed with the original code is in the line

int wldc_ptrail[] = {599,107448};

107448 is too large to be encoded in a 16-bit int, so what you get is something like -23624 instead.

Mikal