IR remote control for Nikon
Introduction
In fact, I don’t need a remote control ![]()
I was searching a way to:
- automatically trigger my camera (sound, light … any trigger),
- make time lapse photography.
But if I could program my arduino to emit the Nikon remote IR sequence, my problem will be solved ![]()
In the web
Make.refractal
At first, I tried this code make.refractal
in theory, it should work, but like his author said, it doesn’t
I found 2 possibles reasons:
1. oscillationWrite takes more time than delayMicroseconds
before=millis(); for(i=0;i<1000;i++) oscillationWrite(outPin, 1000); intervalle=millis()-before; Serial.println(intervalle); before=millis(); for(i=0;i<1000;i++) delayMicroseconds(1000); intervalle=millis()-before; Serial.println(intervalle); Serial.println(”“);
result in millisecond:
1306 1009 1305 1008
2. I added a variable in the oscillationWrite function to count the number of oscillation.
And this figure doesn’t match 38400Hz at all.
Why 38400Hz ?
Most infrared transmissions operate by modulating the led with a relatively high frequency (in most cases 38 or 40KHz).
This means that when we have to send a bit value “1” the led is turned on and off 38000 or 40000 times in one second. (from bigmike ).
For Nikon remote, it’s 38400Hz.
Cibomahto
I also try this one, cibomahto , completely written in asm,
it looks great, but I never achieved to make it work (compilation problems).
And even if I understand the code, ASM is less flexible than C (at least for me !http://ilpleut.be/ip2-static/face-blink.png!)
A new version
This code is based on 3 ideas:
- it has to find hardware related parameters by itself, I’m way too lazy to calculate delay to obtain the accurate frequency.
- waiting & emitting IR must be done by the same function.
- open to other IR waveform emission (tv-B-gone …)
How it works
The code knows it has to modulate its IR emission at 38400Hz
without a delay at each oscillation, my arduino can emit IR at 100.000hz, too much.
The first part of the code will process the most accurate delay.
It tried to find it in a range of 1 to 100 micro second (min/max variable).
(it’s not exactly a microsecond, but it’s not important)
Once it has this value (called oscd in the code).
It will rewrite the emission sequence. (on,off,on,off…)
the original sequence is {2000,27830,390,1580,410,3580,400,63200,2000,27830,390,1580,410,3580,400,0}
This sequence is in micro second, the code will rewrite it in number of arduino oscillation.
When the setup() is done,
it just has to read the IR emission sequence and call the ‘oscillation’ function.
Output
Ready
2122 : 1<->50 # time in millisecond : next range to test
1154 : 1<->25
689 : 13<->25
921 : 19<->25
1038 : 19<->22
961 : 20<->22
999 : 21<->22
1000 : 21<->21 # it found the most accurate delay with 21 microsecond
oscd: 21
2000->76 #start to convert the emission sequence, 2000 micro second = 76 oscillations
27830->1068
390->14
1580->60
410->15
3580->137
400->15
63200->2426
2000->76
27830->1068
390->14
1580->60
410->15
3580->137
400->15
0->0
#start the emission
Self-portrait

The code
// ----- C -------
/**
* arduino Nikon IR remote
* @license Creative commons: Attribution-Noncommercial-Share Alike 3.0 (http://creativecommons.org/licenses/by-nc-sa/3.0/)
* @author Aurelien ANTOINE
* version 1
* date 20081217
**/
#define PIN_STATUS 13
#define PIN_IR_LED 12
#define FREQ 38400 // IR frequence
//shutter sequence (on,off,on,off ... in microsecond)
unsigned long sequence[] = {2000,27830,390,1580,410,3580,400,63200,2000,27830,390,1580,410,3580,400,0};
int seq_l;
//oscd is a delay in microsecond used at each oscillation.
int oscd;
void oscillate(int pin, unsigned long n, int shine){
int ir_status=0;
while(n>0){
n--;
delayMicroseconds(oscd);
ir_status = !ir_status;
digitalWrite(pin, ir_status && shine);
}
}
void snap(){
int i;
digitalWrite(PIN_STATUS, 1);
for(i=0;i<seq_l;i++){
oscillate(PIN_IR_LED, sequence[i], i%2==0);
}
digitalWrite(PIN_STATUS, 0);
}
void setup() {
int min=1, max=100, i;
int last_oscd=0;
unsigned long before, intervalle;
oscd=max;
seq_l = sizeof(sequence)/sizeof(unsigned long);
pinMode(PIN_STATUS, OUTPUT);
pinMode(PIN_IR_LED, OUTPUT);
Serial.begin(28800);
//this "while" will process the best "oscd"
Serial.println("Ready");
while(last_oscd!=oscd){
last_oscd=oscd;
oscd=(min+max)>>1;
before=millis();
oscillate(PIN_STATUS, FREQ, 1);
intervalle=millis()-before;
if(intervalle >= 1000) max=oscd;
else min=oscd;
Serial.print(intervalle);
Serial.print(" : ");
Serial.print(min);
Serial.print("<->");
Serial.println(max);
}
Serial.print("oscd: ");
Serial.println(oscd);
//rewrite the sequence array, we replace all values in microsecond by the number of oscillation
for(i=0;i<seq_l;i++){
Serial.print(sequence[i]);
Serial.print("->");
sequence[i] = (sequence[i] * FREQ) / (intervalle * 1000);
Serial.println(sequence[i]);
}
}
void loop() {
//make a photo, wait 10 seconds
snap();
delay(10000);
}
Notes
- Don’t forget to put a resistor with your IR LED, 220 ohm will be fine.
- It works great in liveview mode with face detection on my D90 !!!!

Links
Those links helped me a lot !!