Introduction: Nikon Time Lapse Controller
This timer requires an Android for the bluetooth module I am using because an iPhone will not connect to the module using the Blynk app.
You can use a bluetooth low energy (Bluetooth LE or BLE) module for iPhone. It works with the Blynk app as far as I've read. You will need to modify this project to accommodate it. I don't have that module, so I'm not sure of the connections needed and code necessary to use it.
Step 1: Parts
For this build you will need the following parts:
- Arduino Nano
- Infrared LED module
- Bluetooth module HC-06 or equivalent (I like the ones already shrink wrapped in plastic to protect part)
- 2 Resistors: 5k Ohm resistor and 10k Ohm resistor (or any combination of two resistors where one is 1/2 the resistance of the other, for example 10k and 20k, 330 and 660, 100 and 200, etc.)
- Controller box (I built and 3D printed my own with the following models)
Controller box
Controller box lid
- Mini small solderless breadboard
- 4 short male to female wires for breadboard
- 2 short male to male wires for breadboard
Step 2: Assembly
Let's assemble the parts. You will want to assemble the board outside the box.
Trim off the square nubs on the sides of the breadboard so the board fits in the box.
Next we will mount the resistors, as it is easier to mount them with nothing on the board. I cut the pins on each side of the resistors to about 1/3" long so they are flush with the board when placed.
Next we will mount the Arduino Nano to the board. We want it so that the digital row (D2 through D12) are 1 space away from the edge of the board. The nano will straddle the center groove of the board. It will also be placed centered so that 1 space is on each end of the board that is unused.
Next we will bend the pins of the two modules (IR LED) and Bluetooth. Be careful and take it slow, so you don't snap the pins off. I bend the pins so that they are 90 degrees to the modules, any further usually results in broke pins.
Next connect the wires to the board as shown.
Finally, sand or file off the back of the IR LED module (nearest the pins) so that there is a thin portion of the module behind the solder points of the pins. This is needed so that the module will fit on the breadboard and the back of the module will be up against the Nano board. Insert the breadboard into the box so that the board is at the back of the box (furthest away from the LED hole of the box) and USB connection faces the square hole for it. Now slide the bulb portion of the IR LED module through the hole in the box you built or printed (it will be a snug fit so a little force is needed to press it in) while pressing the pins of the IR LED module into the space next to the Nano and centered behind the hole in the box. The module should (because of the sanding we did) sit snug next to the Nano board.
Wrap the wires into loops and fit it all inside the box. Close the lid and admire your handiwork!
Step 3: Programming
The code I use to program the Nano is listed below (also attached as an INO file for use in the Arduino IDE). Libraries that you will need to include in the Arduino IDE are below. If you don't have the libraries installed, you can find them in Arduino under the menu Sketch->Include Library->Manage Libraries...
- SoftwareSerial - Included with Arduino
- Blynk
- TaskScheduler
The code may seem odd as I use Arduino pins as grounds and power. This saves me from building a bigger box to fit a larger board and more wiring. The code is:
/* Blynk virtual pin usage: V1 = Toggle picture taking state V2 = Add 1 second to timer V3 = Subtract 1 second from timer (minimum 2 seconds) V4 = Send picture count to Blynk V5 = Send timer to Blynk */ const int pinLEDIrPos = A3; // IR Led + const int pinLEDIrNeg = A5; // IR Led - const int pinVCC = 6; // Bluetooth VCC const int pinGND = 5; // Bluetooth GND const int pinTX = 4; // Bluetooth TXD const int pinRX = 3; // Bluetooth RXD const int pinGNDDivider = 13; // Divider pin to drop voltage to 3.3 volts const int iTimerMin = 2; // My camera can't take pictures faster than 2 seconds using a remote /* You should get Auth Token in the Blynk App. Go to the Project Settings (nut icon). */ const char authToken[] = "AuthCodeFromBlynkApp"; #include <softwareserial.h> SoftwareSerial debugSerial(pinRX, pinTX); // RX, TX #define BLYNK_PRINT debugSerial #include <blynksimpleserialble.h> #include <taskscheduler.h> /***************************************************************************************************/ /*** Variables *************************************************************************************/ /***************************************************************************************************/ uint16_t iCount = 0; uint16_t iTimer = iTimerMin; /***************************************************************************************************/ /*** Callback method prototypes for Tasks **********************************************************/ /***************************************************************************************************/ void transmitPulses(); void updateBlynk(); /***************************************************************************************************/ /*** Class variables *******************************************************************************/ /***************************************************************************************************/ Scheduler sTasks; Task tPictures(0, TASK_FOREVER, &transmitPulses, &sTasks, false); Task tUpdateBlynk(200, TASK_FOREVER, &updateBlynk, &sTasks, false); /***************************************************************************************************/ /*** User functions ********************************************************************************/ /***************************************************************************************************/ BLYNK_WRITE(V1) { int pinValue = param.asInt(); // assigning incoming value from pin V1 to a variable /* You can also use: String i = param.asStr(); double d = param.asDouble(); */ if (pinValue == 0) { tPictures.disable(); } else if (pinValue == 1) { tPictures.restart(); } } BLYNK_WRITE(V2) { int pinValue = param.asInt(); // assigning incoming value from pin V2 to a variable if (pinValue == 0) { iTimer++; tPictures.setInterval(iTimer * 1000); } } BLYNK_WRITE(V3) { int pinValue = param.asInt(); // assigning incoming value from pin V3 to a variable if (pinValue == 0) { if (iTimer > iTimerMin) { iTimer--; tPictures.setInterval(iTimer * 1000); } } } void sendBlynkRunningState() { if (tPictures.isEnabled()) { Blynk.virtualWrite(V1, 1); } else { Blynk.virtualWrite(V1, 0); } } void sendBlynkCount() { Blynk.virtualWrite(V5, iCount); } void sendBlynkTimer() { Blynk.virtualWrite(V6, iTimer); } void transmitPulses() { /* 3 rapid signals for Nikon camera remote customized to Arduino, which is why there is use of delay instead of delayMicroseconds. For some reason delay(2) == delayMicroseconds(800) */ iCount++; for (int iNdx = 0; iNdx < 3; iNdx++) { tone(pinLEDIrPos, 38000); delay(2); noTone(pinLEDIrPos); delay(28); tone(pinLEDIrPos, 38000); delayMicroseconds(200); noTone(pinLEDIrPos); delayMicroseconds(1500); tone(pinLEDIrPos, 38000); delayMicroseconds(200); noTone(pinLEDIrPos); delayMicroseconds(3300); tone(pinLEDIrPos, 38000); delayMicroseconds(200); noTone(pinLEDIrPos); delayMicroseconds(100); delay(63); } } void updateBlynk() { sendBlynkRunningState(); sendBlynkCount(); sendBlynkTimer(); } /***************************************************************************************************/ /*** Default functions *****************************************************************************/ /***************************************************************************************************/ void setup() { pinMode(pinGNDDivider, OUTPUT); digitalWrite(pinGNDDivider, LOW); // Set divider pin to ground (LOW) pinMode(pinGND, OUTPUT); digitalWrite(pinGND, LOW); // Set BT GND pin to ground (LOW) pinMode(pinVCC, OUTPUT); digitalWrite(pinVCC, HIGH); // Set BT VCC pin to 5 volts (HIGH) pinMode(pinLEDIrNeg, OUTPUT); digitalWrite(pinLEDIrNeg, LOW); // Set IRLed GND pin to ground (LOW) pinMode(pinLEDIrPos, OUTPUT); tPictures.setInterval(iTimer * 1000); delay(5000); // Bluetooth module powerup delay (not sure if needed) debugSerial.begin(9600); // Debug console /* Blynk will work through Serial 9600 is for HC-06. For HC-05 default speed is 38400 Do not read or write to Serial manually in your sketch */ Serial.begin(9600); Blynk.begin(Serial, authToken); tUpdateBlynk.restartDelayed(500); } void loop() { Blynk.run(); sTasks.execute(); }
Attachments
Step 4: Build Your Blynk Project
I use Blynk to build an app and connect to the board. Here is how I have it set up.
- Pictures Taken label
- Input is Virtual Pin 5 (V5)
- Reading Rate is PUSH
- Bluetooth accessory (near the bottom of list in Blynk)
- Select your bluetooth device from the list (box must be powered on and connected to phone via bluetooth)
- Timer label
- Input is Virtual Pin 6 (V6)
- Reading Rate is PUSH
- Start/Stop button
- Output is Virtual Pin 1 (V1)
- Mode is SWITCH
- Label on is STOP
- Label off is START
- Add Time button
- Output is Virtual Pin 2 (V2)
- Mode is PUSH
- Label on and off is +
- Subtract Time button
- Input is Virtual Pin 3 (V3)
- Mode is PUSH
- Label on and off is -
I skipped V4 because I am planning on adding a motorized mount later to rotate the camera between shots if selected.
*DON'T FORGET TO COPY THE AUTHENTICATION CODE IN THE APP INTO YOUR ARDUINO CODE*
Step 5: Testing the Finished Product
Connect the device to a USB power source (computer, plug in or my favorite, a portable power supply with USB ports which is usually used to charge cell phones).
On your cell phone, pair the bluetooth device (mine was listed as HC-06). The passphrase/pin/code was 1234.
Start the Blynk app and select your project. It should connect to the bluetooth device. Power up your Nikon camera, switch it to remote control mode and press buttons on the Blynk app as you see fit!
I hope you enjoy this project.