///////////////////////////////////////////////////////////////// // Time-lapse shutter release control based on an Arduino Nano // ///////////////////////////////////////////////////////////////// // A program to control the shutter of a Nikon DSLR to create a time-lapse video. // As the program is written right now, the interval increases for every exposure. // The program will probably have to be adapted for each specific case, but could // perhaps serve as a basis for programs with more advanced functionality. // // Written in 2013 by Per Magnusson, Axotron, http://axotron.se/index_en.php // v 0.1 // // // (c) 2013, Per Magnusson, Axotron, http://axotron.se/index_en.php // // License: // I make this code available in the hope that it might be educational and/or // inspirational. Feel free to use it, change it, include it in your own commercial // or non-commercial projects as you see fit. You do not have to attribute me, but // you are welcome to do so if you like. // I give no guarantee that it will be good for anything. // Below is some legalese I copied from a version of the BSD license: // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. const int focusPin = 2; const int shutterPin = 3; const int lampPin = 4; const unsigned int lampOnTime = 1500; // Lamp on time after shutter release in ms const unsigned long initialTimeLapseInterval = 2000; // In ms const unsigned int timeLapseDelta = 20; // Lengthening of interval for each frame, ms int incomingByte; byte timeLapseMode = 0; unsigned long timeLapseInterval; unsigned long nextTime; unsigned long photoCounter = 0; void setup() { // initialize serial communication: Serial.begin(9600); pinMode(focusPin, OUTPUT); pinMode(shutterPin, OUTPUT); pinMode(lampPin, OUTPUT); digitalWrite(focusPin, LOW); digitalWrite(shutterPin, LOW); digitalWrite(lampPin, LOW); Serial.println("Press 's' to take a picture"); Serial.println("Press 'L' to turn on lamp"); Serial.println("Press 'l' to turn off lamp"); Serial.print("Press 'F' to start time lapse mode with "); Serial.print(initialTimeLapseInterval); Serial.println(" ms initial interval."); Serial.println("Press 'f' to end time lapse mode"); } void loop() { static unsigned long startTime = 0; // see if there's incoming serial data: if (Serial.available() > 0) { // read the oldest byte in the serial buffer: incomingByte = Serial.read(); Serial.write(incomingByte); if (incomingByte == 's') { expose(); Serial.println("!"); } else if (incomingByte == 'L') { digitalWrite(lampPin, HIGH); Serial.println("!"); } else if (incomingByte == 'l') { digitalWrite(lampPin, LOW); Serial.println("!"); } else if (incomingByte == 'F') { Serial.println("!"); timeLapseInterval = initialTimeLapseInterval; Serial.print("Entering time lapse mode with interval "); Serial.print(timeLapseInterval); Serial.println(" ms."); timeLapseMode = 1; photoCounter = 0; startTime = millis(); nextTime = startTime; } else if (incomingByte == 'f') { Serial.println("!"); Serial.println("Exiting time lapse mode."); Serial.print(photoCounter); Serial.print(" pictures taken in "); Serial.print((millis()-startTime)/1000); Serial.println(" seconds."); timeLapseMode = 0; } else { Serial.println("?"); } } if(timeLapseMode) { if(millis() >= nextTime) { expose(); timeLapseInterval += timeLapseDelta; nextTime += timeLapseInterval; photoCounter += 1; Serial.print(photoCounter); Serial.print(" pictures taken in "); Serial.print((millis()-startTime)/1000); Serial.print(" seconds. Current interval is "); Serial.print(timeLapseInterval); Serial.println(" ms."); } } } void expose() { digitalWrite(lampPin, HIGH); delay(50); digitalWrite(focusPin, HIGH); delay(200); digitalWrite(shutterPin, HIGH); delay(50); digitalWrite(focusPin, LOW); digitalWrite(shutterPin, LOW); delay(lampOnTime); // The exposure time might be long, make sure this is longer digitalWrite(lampPin, LOW); }