Last August I started a small project to use my Raspberry Pi to do bracketed image capture for HDR using my aging Nikon D40. My solution worked but was not complete. My solution required me to compose my scene and then connect and power on the RPi and wait for the script to complete and then shutdown the RPi. I wanted something that I could trigger with a switch.

After much trial and error — and a bit of panic — I have a fully functional solution written in Perl. This HDR Raspberry Pi project is based on other projects and ideas from several places including the comments section of my original post from last August. In particular I would like to recognize the following projects.

Zach Dwiel’s gphoto2-timelapse project is written in Python but I got the basic concept of what I needed to to from his project. Using a startup script and usbreset ideas were borrowed from his project.

After searching around for how to use the GPIO on the Rapberry Pi I found a link to gpio from WiringPi. This is an implementation of most of the Arduino Wiring functions for the Raspberry Pi. The gpio binary plus a very easy to understand diagram and some simple code from the TNET Raspberry Pi site helped complete my project. I also found the RPi low-level peripherals page on the eLinux.org site very useful.

This project allows you to create bracketed images for use in HDR photography using the Raspberry Pi, a supported DSLR camera connected via USB to the Raspberry Pi, and the gphoto2 program. The script is a Perl rewrite of an earlier BASH script. The goals for the Perl rewrite was to make things a little easier.

I’ve included the code for the main script and usbreset but the rest you’ll have to download and install yourself. Download and compile the WiringPi code to create gpio. You will need this to control the GPIO pins on the RPi and a switch to signal the main script to do it’s work.

You will also need to install usbutils – Linux USB utilities – to get lsusb. lsusb is a utility for displaying information about USB buses in the system and the devices connected to them. I found lsusb more useful for detecting when a camera was attached to the RPi and turned on. I could have used gphoto2 with the autodetect switch but I found lsusb was faster.

You will also need to compile usbreset. This handy piece of code helped reset the USB interface to the Nikon camera between brackets sets. I found that without usbreset that gphoto2 would generate a lot of errors using the Nikon.

You will need to install Perl to run the HDR scripts. This might already be a part of your library.

Once everything is installed, you need to tweak the script a bit to get it to work with different cameras. For example, I used lsusb to specific USB ID for my Nikon D40. I used that in the script. You will also need to find the proper gphotos2 parameters for you camera. Once you have the camera specific parameters and functions in place, you can use the Perl scripts to begin taking images.

perl hdr.pl

There is also an rc script which you can use to start the HDR script automatically when the computer (raspberry pi) is turned on. To setup this feature run the following commands:

sudo ln ./rc.hdr /etc/init.d/rc.hdr
cd /etc/init.d/
sudo update-rc.d rc.hdr defaults

The script is made up one main loop and four functions. One function uses the lsusb utility to get the bus and device information for the Nikon. This information is then used by usbreset to re-initialise the Nikon’s USB connection in between bracket captures. I found that this eliminated a lot of the error messages from gphoto2.

Two more functions control the gpio so that I can trigger the capture event. One funtion takes the five brackets images.

That’s it in a nutshell. I did notice that the slowest part of the script is the gphoto2 capture. I can’t explain why but I notice that gphoto2 takes about 5 seconds to setup before it will start capturing images.

Moments after completing this project I had some ideas for improvement. I want to reduce the time between pushing the button and capturing the last image. Currently this is five seconds. I suspect that calling out to gphoto2 from perl is slowing things down. I think maybe writing Perl binding to the gphoto2 library may help or perhaps writing the entire program in C. I’m not a big fan of C — I try to avoid strongly typed languages in general — but if I can find the time and motivation I will try.

You can find all the code on GitHub.