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.
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/