Matt Mets has written a nice Nikon remote control library for Arduino. I used it to make a motion trigger and intervalometer. It looks like this:

Here’s a Fritzing image of the circuit (I finished it in Illustrator, because there’s no PIR part in Fritzing yet, and I have trouble with the part editor.)

And here’s the schematic:

And finally, the code:
/*
Intervalometer/Motion Sensitive trigger for Nikon digital SLRs
This sketch takes input from a motion sensor, a potentiometer, and a
group of switches, and outputs a control signal for a Nikon DSLR via
an IR LED.
It uses Matt Mets' NikonRemote library for Arduino:
http://www.cibomahto.com/2008/10/october-thing-a-day-day-7-nikon-camera-intervalometer-part-1/
Full code and schematics:
Created 16 Jan 2010
by Tom Igoe
*/
#include <NikonRemote.h>
// constants for LEDs:
const int irLedPin = 12;
const int motionSensorLedPin = 10;
const int intervalometerLedPin = 9;
const int powerLedPin = 8;
// constants for the switches and the motion sensor:
const int motionSensorPin = 7;
const int motionSensorSwitchPin = 6;
const int intervalometerSwitchPin = 5;
// constant for the pot:
const int potPin = 5;
// states of the motion sensor and intervalometer
// control switches:
int motionSensorState = LOW;
int intervalometerState = LOW;
int motionSensorReading = LOW; // current motion sensor reading
int lastSensorReading = LOW; // last motion sensor reading
long interval = 0; // interval between snaps, in ms
long lastSnap = 0; // time of the last snap, in ms
// instantiate the NikonRemote library:
NikonRemote camera(irLedPin);
void setup() {
// set up all inputs and outputs:
pinMode(irLedPin, OUTPUT);
pinMode(powerLedPin, OUTPUT);
pinMode(motionSensorLedPin, OUTPUT);
pinMode(intervalometerLedPin, OUTPUT);
pinMode(motionSensorPin, INPUT);
pinMode(motionSensorSwitchPin, INPUT);
pinMode(intervalometerSwitchPin, INPUT);
// turn on the power LED:
digitalWrite(powerLedPin,HIGH);
}
void loop() {
// read switches:
motionSensorState = !digitalRead(motionSensorSwitchPin);
intervalometerState = !digitalRead(intervalometerSwitchPin);
// set the LEDs:
digitalWrite(motionSensorLedPin, motionSensorState);
digitalWrite(intervalometerLedPin, intervalometerState);
// if the motion sensor is on, read it:
if (motionSensorState == HIGH) {
checkMotionSensor();
}
// if the intervalometer is on, read the pot and set the interval:
if (intervalometerState == HIGH) {
// map the pot to a range from 1-60 seconds
interval = map(analogRead(potPin), 1023, 0, 1, 60);
// convert to milliseconds:
interval = interval * 1000;
// check to see if you should snap a picture:
checkIntervalometer();
}
}
void checkMotionSensor() {
// read the motion sensor:
motionSensorReading = digitalRead(motionSensorPin);
// if the sensor has changed since last reading:
if (motionSensorReading != lastSensorReading) {
//... and the sensor is HIGH, then take a picture:
if (motionSensorReading == HIGH) {
camera.Snap();
}
}
// save the current state of the sensor
// to compare the next reading to:
lastSensorReading = motionSensorReading;
}
void checkIntervalometer() {
// if enough the interval has passed since the last
// camera snap, take another picture:
if (millis() - lastSnap > interval) {
camera.Snap();
// save the current time for use next check:
lastSnap = millis();
}
}