Tag Archives: Arduino Uno

Re-programmable IR Camera Remote for Sony NEX-5

I’ve been putting off this post for quite a while because I wanted to do much more and then share this one particular project I’ve invested a lot of time and effort in. Instead I thought I’d share my progress till now.
( I have a working prototype by the way, I just wanted to modify it a lot more, and make the schematics etc properly.)
This post happens to be a lot like a general informal blog post because I plan to make a detailed instructable some time later with all the involved stages and iterations for the remote.

The ultra-short version? It’s an IR remote for a Sony NEX 5.

Video demo:
http://www.facebook.com/photo.php?v=10151647956756594&l=8701802626708426185

The slightly detailed one?

It has 2 modes; Manual:Whenever you press the button it clicks, Auto: It clicks every few seconds (the duration can be set), intention behind this mode was trying to do time-lapse photography.

It also has Tx and Rx headers for easily re-programming the Atmega 328P to play with the code and, for instance, include Canon/Nikon codes, or use the remote platform to control other devices like TVs, A/Cs etc.

And now I commence with the full plunge.

I really wanted to try timelapse photography with my camera, Sony NEX, but unfortunately there wasn’t any proper software that I could find at the time, or any way of doing proper tethered shooting with it. I was too scared to mess with the firmware, and I wanted to make my own remote for the camera as well. So instead of buying an intervalometer/remote, I started setting up an Arduino based circuit.

Some specifics of the circuit:

-Arduino bootloader on the Atmega 328P which I made the remote around, working on 8MHz internal clock.
-Hardware debouncing using schmitt triggered inverters and RC circuits for the Push-buttons
-Runs on a 9V battery, used a LM7805 get it down to 5V to power the board.
-BJT based amplifier circuit to maximize the range of the remote (4.5 meters as of now)
-Onboard 10k potentiometer to set the delay for the timelapse mode, as of now calibrated to give min. 10s to max 45s delay between clicks.

Future plans:

-Shifting it to the AtTiny2313 to avoid wastage of pins and to make it smaller
-Running it on 3V3 logic so that I could use a lighter battery
-Modifying the code to incorporate Sebastian Setz’s library
-Actually implementing the time-lapse functionality properly
-Adding a batter indicator as per Lucky Larry’s project.

http://luckylarry.co.uk/arduino-projects/arduino-ir-remote-intervalometer-for-nikon-d80-that-means-timelapse-photography-yarrr/

http://sebastian.setz.name/arduino/my-libraries/multi-camera-ir-control/

There and back again:

The entire exercise turned out to be a great learning process. I started off with the basics of IR remotes, IR protocols, Sony, NEC, and the Ken Shirriff library for IR control for Arduino. I checked out the Adafruit tutorials for making a canon/nikon camera remote. I struggled a lot while looking for the exact click code for my camera, but finally stumbled upon Marc Lane’s blog:

http://www.l8ter.com/?p=333

Once I was able to click using a normal Arduino Uno and an IR Led connected to it, I wanted to make a compact version with custom button positions,a hardware debouncing circuit for them,  a range booster and have the Atmega 328P run the Arduino bootloader.

I laid out the design on a breadboard and followed :http://arduino.cc/en/Tutorial/ArduinoToBreadboard

Once I was done with the basic setup, I started to optimize my code by using interrupts. I wasn’t happy with the multiple presses the “mode button” was registering when I pressed it. I then found Jeremy Blum’s excellent lesson for hardware debouncing.

http://www.jeremyblum.com/2011/03/07/arduino-tutorial-10-interrupts-and-hardware-debouncing/

After a lot of frustrating debugging, my final breadboard setup looked something like this:

Remote Fritzing Schematic
The remote during various stages of development:

This slideshow requires JavaScript.

The code as of now is mainly Lucky Larry’s code, modified to use interrupts and to work as per my hardware setup and use the Sony NEX click IR Code instead of the Nikon one. Here’s the original code again:

http://luckylarry.co.uk/arduino-projects/arduino-ir-remote-intervalometer-for-nikon-d80-that-means-timelapse-photography-yarrr/

And the one I’m using on my setup:


/* Mayank Joneja;
Implementation of Lucky Larry's code for a custom IR remote for the Sony NEX 5 */

/*
LUCKYLARRY.CO.UK - IR Remote control for Nikon using Arduino
Mimics the infrared signal to trigger the remote for any Nikon camera
which can use the ML-L1 and ML-L3 remotes. Can be used as an intervalometer
for time lapse photography.
The IR sequence I used is originally taken from: http://www.bigmike.it/ircontrol/
You should be able to use my pulse methods to alter to suit other cameras/ hardware.
micros() is an Arduino function that calls the time in Microseconds since your program
first ran. Arduino doesn't reliably work with microseconds so we work our timings by
taking the current reading and then adding our delay on to the end of it rather than rely
on the in built timer.
*/

int pinIRLED = 12; // assign the Infrared emitter/ diode to pin 12
int LEDgreen = 13; // use onboard led for battery status
int batteryIn = 0; // set pin to get power data from
int batLevel = 0; // variable to get details on battery power level from analog input
int lowPower = 0; //count to keep track of lowpower state
long int td; //delay between shots
volatile boolean mode = false;

int modeButton = 0; // Mode button wired to INT0
int clickButton = 8;// Click button wired to digital pin 8

int modeLed = 7; //An indicator LED to show the mode
int clickLed = 13; //An indicator LED for the clicking in mode2

void setup() {
pinMode(pinIRLED, OUTPUT);
pinMode(modeLed,OUTPUT);
pinMode(A0,INPUT); // set the pin as an output
attachInterrupt(modeButton, modeSwitch, RISING);
}

void modeSwitch()
{
mode =!mode;
digitalWrite(modeLed,mode);
return;
}

// sets the pulse of the IR signal.
void pulseON(int pulseTime) {
unsigned long endPulse = micros() + pulseTime; // create the microseconds to pulse for
while( micros() < endPulse) {
digitalWrite(pinIRLED, HIGH); // turn IR on
delayMicroseconds(13); // half the clock cycle for 38Khz - e.g. the 'on' part of our wave
digitalWrite(pinIRLED, LOW); // turn IR off
delayMicroseconds(13); // delay for the other half of the cycle to generate wave/ oscillation
}
}
void pulseOFF(unsigned long startDelay) {
unsigned long endDelay = micros() + startDelay; // create the microseconds to delay for
while(micros() < endDelay);
}
void takePicture() {
for (int i=0; i < 2; i++) {
pulseON(2336);
pulseOFF(646);
pulseON(1168);
pulseOFF(621);
pulseON(572);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(572);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(572);
pulseOFF(646);
pulseON(572);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(572);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(572);
pulseOFF(621);
pulseON(572);
pulseOFF(646);
pulseON(572);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1168);
pulseOFF(11008);
pulseON(2336);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(572);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(572);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(572);
pulseOFF(646);
pulseON(572);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(572);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(572);
pulseOFF(621);
pulseON(572);
pulseOFF(646);
pulseON(572);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1168);
pulseOFF(11008);
pulseON(2336);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(572);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(572);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(572);
pulseOFF(646);
pulseON(572);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(572);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1093);
pulseOFF(696);
pulseON(572);
pulseOFF(621);
pulseON(572);
pulseOFF(621);
pulseON(572);
pulseOFF(621);
pulseON(572);
pulseOFF(1218);
pulseON(497);
pulseOFF(1292);
pulseON(422);
pulseOFF(1367);
pulseON(373);
pulseOFF(11803);
pulseON(298);
pulseOFF(2659);
pulseON(199);
pulseOFF(1590);
pulseON(174);
pulseOFF(1019);
pulseON(174);
pulseOFF(1615);
pulseON(174);
pulseOFF(1615);
pulseON(149);
pulseOFF(1044);
pulseON(149);
pulseOFF(1640);
pulseON(124);
pulseOFF(1093);
pulseON(149);
pulseOFF(1044);
pulseON(124);
pulseOFF(1665);
pulseON(124);
pulseOFF(1068);
pulseON(124);
pulseOFF(1665);
pulseON(99);
pulseOFF(1690);
pulseON(99);
pulseOFF(1690);
pulseON(99);
pulseOFF(1093);
pulseON(99);
pulseOFF(1118);
pulseON(99);
pulseOFF(1093);
pulseON(99);
pulseOFF(1690);
pulseON(99);
pulseOFF(1690);
pulseON(75);
pulseOFF(1715);
pulseON(75);
pulseOFF(12101);
pulseON(149);
pulseOFF(2833);
pulseON(75);
pulseOFF(1715);
pulseON(75);
pulseOFF(1118);
pulseON(75);
pulseOFF(1715);
pulseON(75);
pulseOFF(1715);
pulseON(75);
pulseOFF(1118);
pulseON(75);
pulseOFF(1715);
pulseON(75);
pulseOFF(1118);
pulseON(99);
pulseOFF(1093);
pulseON(99);
pulseOFF(1690);
pulseON(99);
pulseOFF(1093);
pulseON(99);
pulseOFF(1690);
pulseON(99);
pulseOFF(1690);
pulseON(99);
pulseOFF(1690);
pulseON(99);
pulseOFF(1093);
pulseON(99);
pulseOFF(1118);
pulseON(99);
pulseOFF(1093);
pulseON(99);
pulseOFF(1690);
pulseON(99);
pulseOFF(1690);
pulseON(99);
pulseOFF(1690);
pulseON(99);
pulseOFF(646);
} // loop the signal twice.
}
void batterytestdelay(unsigned long delaytime){ // Function to check battery level and flash the led if its low battery
long tempdelay = 0;
while(delaytime > tempdelay){
delay(100);
tempdelay = tempdelay + 100;
batLevel = analogRead(batteryIn);
if (batLevel < 720){
lowPower++;
}
if (lowPower > 100){
lowPower = 0;
}
if (lowPower < 50){
digitalWrite(LEDgreen, LOW);
}
else{
digitalWrite(LEDgreen, HIGH);
}
}
}

void loop() {

if(mode==false) // mode1
{
while(mode == false) // as long as the device is in mode1 (will switch modes if interrupted by mode switch being pressed
{
td=(analogRead(A0)*25);
takePicture();
delay(td);
}
}
if ((digitalRead(clickButton) == HIGH) && (mode == true)) //Click is pressed and device is in mode2
{
digitalWrite(clickLed,HIGH); //indicator LED
delay(100);
takePicture();
digitalWrite(clickLed,LOW);
}
}

I plan on making a better attempt at cataloging this project and implementing all the things I mentioned in the beginning. I hope I can then end up with a better post with all the rough edges, like the code formatting, the actual PCB Design, etc taken care of. I also plan on making my own PCB for the next prototype instead of hand soldering it the way I did with this one.

In case you read this till the end, thanks a lot for your time!
I hope this post can be of some level of assistance in case you’re planning on making something similar. Do check out all the links I mentioned 🙂