Nikon D40 Intervalometer Project

So, I’ve been wondering how to get my camera (Nikon D40) to do time-lapse photography. I am going on a camping trip here in about 2 weeks and would love to be able to take some time-lapse shots of the night-time sky whilst we sit around the campfire.

A problem arises. The Nikon D40 does not have an intervalometer (nor does it support auto-bracketing, but that’s another post). This means no time-lapse photography with this camera.

Or does it?

A couple of generalized web searches brought me to some informative sites:
http://www.cibomahto.com/2008/10/october-thing-a-day-day-7-nikon-camera-intervalometer-part-1/
http://ilpleut.be/doku.php/code:nikonremote:start
http://www.bemasher.net/archives/114

I was in luck! I happen to have an Arduino board lying around doing nothing. Happy times!

I set off to the only place in town with electronic components, Radio Shack (I know). IR LED in hand, I proceeded to assemble my very simple circuits. I built a second circuit to blink a second LED for 2 seconds before the IR LED sequence is fired off for the camera. I chose to use the code from the bemasher link.

The Arduino microcontroller board that I have has a 220 ohm resister built into digital pin 13 that I was not aware of. My IR LED was understandably dim as a consequence of my adding a second 220 ohm resister to the circuit. The camera wasn’t taking pictures when it should have been. With that problem solved, I edited the code to include a timer that I can set easily to whatever number of seconds I need. I set it to 10 seconds and tested the camera out again.

Success!

I built a small enclosure for everything, soldered a few wires together, and tested again to make sure I had put it all back together correctly. It works from about 10-12 feet away, but I shouldn’t need it for anything that far away. The idea is to just place the IR LED directly on the IR receiver and let it take a picture every 60 seconds for hours at a time. Simple.

Code I am using:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/*
Author:         BeMasher
Description:    Code sample in C for firing the IR sequence that mimics the
ML-L1 or ML-L3 IR remote control for most Nikon SLR's.

Based off of:   http://make.refractal.org/?p=3
http://www.cibomahto.com/2008/10/october-thing-a-day-day-7-nikon-camera-intervalometer-part-1/
http://ilpleut.be/doku.php/code:nikonremote:start
http://www.bigmike.it/ircontrol/

Notes:          This differs slightly from the other 3 versions I found in that this doesn't use the built in
delay functions that the Arduino comes with. I discovered that they weren't accurate enough for
the values I was trying to give them. The delayMicrosecond() function is only accurate between about
4uS and 16383uS which isn't a very workable range for the values we need to delay in for this project.
The ASM code that Matt wrote works well but is limited to only pin 12 and I haven't got a good enough
grasp of the architecture to modify the code to work on any pin. So this is what I've come up with to
produce the same result.
*/


#define IND_LED 10       //Pin the Indicator LED is on
#define IR_LED 13        //Pin the IR LED is on
#define DELAY 13         //Half of the clock cycle of a 38.4Khz signal
#define DELAY_OFFSET 4   //The amount of time the micros() function takes to return a value
#define SEQ_LEN 4        //The number of long's in the sequence

unsigned long seq_on[] = {2000, 390, 410, 400};        //Period in uS the LED should oscillate
unsigned long seq_off[] = {27830, 1580, 3580, 0};      //Period in uS that should be delayed between pulses
int interval=0;
int time=0;

void setup() {
Serial.begin(19200);        //Initialize Serial at 19200 baud
pinMode(IR_LED, OUTPUT);    //Set the IR_LED pin to output
pinMode(IND_LED, OUTPUT);   //Set the IR_LED pin to output
}

void customDelay(unsigned long time) {
unsigned long end_time = micros() + time;    //Calculate when the function should return to it's caller
while(micros() < end_time);                  //Do nothing 'till we get to the end time
}

void oscillationWrite(int pin, int time) {
unsigned long end_time = micros() + time;    //Calculate when function should return to it's caller
while(micros() < end_time) {                 //Until we get to the end time oscillate the LED at 38.4Khz
digitalWrite(pin, HIGH);
customDelay(DELAY);
digitalWrite(pin, LOW);
customDelay(DELAY - DELAY_OFFSET);        //Assume micros() takes about 4uS to return a value
}
}

void triggerCamera() {
for(int i = 0; i < SEQ_LEN; i++) {            //For each long in the sequence
oscillationWrite(IR_LED, seq_on[i]);      //Oscillate for the current long's value in uS
customDelay(seq_off[i]);                  //Delay for the current long's value in uS
}
customDelay(63200);                            //Wait about 63mS before repeating the sequence
for(int i = 0; i < SEQ_LEN; i++) {
oscillationWrite(IR_LED, seq_on[i]);
customDelay(seq_off[i]);
}
}

/*
void loop() {
if(Serial.available()) {        //Wait 'till something is connected
if(Serial.read() != 0) {    //If anything but 0 is sent take a photo
triggerCamera();        //Take a photo
}
delay(100);                 //Delay an arbitrary amount of time, serial isn't instantaneous
}
}
*/


void loop() {
if(interval == 10) {
digitalWrite(IND_LED, HIGH);
delay(245);
digitalWrite(IND_LED, LOW);
delay(250);
digitalWrite(IND_LED, HIGH);
delay(250);
digitalWrite(IND_LED, LOW);
delay(250);
digitalWrite(IND_LED, HIGH);
delay(245);
digitalWrite(IND_LED, LOW);
delay(250);
digitalWrite(IND_LED, HIGH);
delay(250);
digitalWrite(IND_LED, LOW);
delay(250);
triggerCamera();
interval = 2;
}
delay(995);
interval += 1;

//Serial.print("Time: ");   //This is to get timing as close as possible
// time = (millis()/100);
//prints time since program started
// Serial.println(time);

}

This is probably boring to almost all of you, but I just thought I would share. :)

This entry was posted in Uncategorized. Bookmark the permalink.

One Response to Nikon D40 Intervalometer Project

  1. BeMasher says:

    Glad to see others are finding my code useful!

    If you’re going to be posting a lot more code on your site you should take a look at a wordpress plugin called CodeColorer.

    http://wordpress.org/extend/plugins/codecolorer/

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>