triggerman:
Hello, i am new to the whole Arduino concept.I basically bought an Arduino starter kit for experimenting but i want to use it (if this is possible) in a project at university. I want to know if there is a way to detect when a flash (let's say from an ordinary camera) is on because i want to know the exact time the flash is triggered.Is this possible with Arduino?
Thanks in advance
Absolutely. You can build a simple circuit that uses a photodetector of some kind, and have the Arduino sense when the output from that changes suddenly. I used a similar setup to create a trigger for my camera when it detected lightning. Search for "arduino phototransistor" on the web to get started.
Here is my hacked version of stuff I stole fromfound on the web. It "works" but is in a state of disrepair. I offer it not as a good example of Arduino hacking, but as a reference for the sort of direction one can go in to teach themselves how to interface to a simple circuit.
I just used the simple circuit from the phototransistor datasheet and fed the output of that into the Arduino.
If I were to rewrite this, I'd use interrupts instead of depending on delays. How to do that is left up as an exercise for the reader (and me.) The timer stuff used here is an egregious hack. I make no apologies for this.
/* $Id: LightningRider.pde,v 1.2 2009/04/16 01:19:17 clvrmnky Exp clvrmnky $
Author: BeMasher
Description: Code sample in C for firing the IR sequence that mimics the
ML-L1 or ML-L3 IR remote control for most Nikon SLR's.
Based off of: http://make.refractal.org/?p=3
http://www.cibomahto.com/2008/10/october-thing-a-day-day-7-nikon-camera-intervalometer-part-1/
http://ilpleut.be/doku.php/code:nikonremote:start
http://www.bigmike.it/ircontrol/
Notes: This differs slightly from the other 3 versions I found in that this doesn't use the built in
delay functions that the Arduino comes with. I discovered that they weren't accurate enough for
the values I was trying to give them. The delayMicrosecond() function is only accurate between about
4uS and 16383uS which isn't a very workable range for the values we need to delay in for this project.
The ASM code that Matt wrote works well but is limited to only pin 12 and I haven't got a good enough
grasp of the architecture to modify the code to work on any pin. So this is what I've come up with to
produce the same result.
*/
//#define MY_DEBUG 1 // If set, send debug messages to serial. This will probably mess up timings.
#define LIGHT_DETECTOR 0 // Analog pin that we read for light sensor data
#define IR_LED 7 //Pin the IR LED is on
// TODO:
#define DELAY 13 //Half of the clock cycle of a 38.4Khz signal
#define DELAY_OFFSET 4 //The amount of time the micros() function takes to return a value
#define SEQ_LEN 4 //The number of long's in the sequence
#define SHOTS 3 // Number of shots in a row to take (for bracketing)
#define SLEEP 100 // We can only accurately sample the analog inputs about 10,000 times/sec.
// Time to wait, in uS, between shutter releases
// TODO: figure out how much time to wait between subsequent shots based on shutter speed and
// whatever Nikon needs between IR triggers.
#define CAMERA_WAIT 370000
// Positive difference between analog pin samples must be larger than this to trigger
// TODO: Need to calibrate based on real-world trials.
#define TRIGGER_THRESHOLD 10
// Nikon magic
// TODO: Place in a header file
unsigned long seq_on[] = {2000, 390, 410, 400}; //Period in uS the LED should oscillate
unsigned long seq_off[] = {27830, 1580, 3580, 0}; //Period in uS that should be delayed between pulses
unsigned int oldval = 1023; // Init w/ max analog value can be so we never trigger on start
void setup() {
Serial.begin(57600); // Initialize Serial
pinMode(IR_LED, OUTPUT); // Set the IR_LED pin to output...
digitalWrite(IR_LED, LOW); // ... and reset it to LOW (just in case)
}
/*
* Another attempt at a more reliable timer routine.
* TODO: determine if this is actually accurate enough. Do we need to implement timer2?
*/
void customDelay(unsigned long time) {
unsigned long end_time = micros() + time; //Calculate when the function should return to it's caller
while(micros() < end_time); //Do nothing 'till we get to the end time
}
void oscillationWrite(int pin, int time) {
unsigned long end_time = micros() + time; //Calculate when function should return to it's caller
while(micros() < end_time) { //Until we get to the end time oscillate the LED at 38.4Khz
digitalWrite(pin, HIGH);
customDelay(DELAY);
digitalWrite(pin, LOW);
customDelay(DELAY - DELAY_OFFSET); //Assume micros() takes about 4uS to return a value
}
}
void triggerCamera() {
for(byte i = 0; i < SEQ_LEN; i++) { //For each long in the sequence
oscillationWrite(IR_LED, seq_on[i]); //Oscillate for the current long's value in uS
customDelay(seq_off[i]); //Delay for the current long's value in uS
}
customDelay(63200); //Wait about 63mS before repeating the sequence
for(byte i = 0; i < SEQ_LEN; i++) {
oscillationWrite(IR_LED, seq_on[i]);
customDelay(seq_off[i]);
}
}
/*
* isTriggered -- return true if the int we read from the analog changes in a positive
* direction since the last time we sampled it.
*/
boolean isTriggered() {
unsigned int val;
int diff;
val = analogRead(LIGHT_DETECTOR);
#ifdef MY_DEBUG
Serial.println(val);
#endif
// Calculate diff between last two samples
diff = val - oldval;
oldval = val;
if (diff > TRIGGER_THRESHOLD)
return true;
else
return false;
}
void loop() {
if (isTriggered()) {
// We take SHOTS shots in a row for bracketing.
for(byte i = 0; i < SHOTS; i++) {
triggerCamera();
customDelay(CAMERA_WAIT); // Total magic. Number of uS to wait between triggers.
}
#ifdef MY_DEBUG
Serial.println("Oh, snap!");
#endif
}
// We can only read the analog inputs so often, so sleep here.
customDelay(SLEEP);
}