interrupt starts at different times depending on upload time of program

I'm trying to synchronize a camera with a very fast blinking LED (that I cannot control) which runs at about 230 Hz.
So when the Arduino detects a rising edge from the LED voltage supply (which rises from 2,2 to 3,2 V, so logical 0 to 1) it starts an interrupt routine which sends a trigger signal to the camera.

The code is:

int ledInput = 3;            
int cam = 10;

void blink()
{  
    digitalWrite(cam,HIGH);
    delayMicroseconds(800);
    digitalWrite(cam,LOW);
}
  
void setup()
{
   Serial.begin(9600);
   pinMode(ledInput, INPUT);
   pinMode(cam, OUTPUT);
  attachInterrupt(1, blink, RISING);
  digitalWrite(cam,LOW);
}

void loop()
{
}

which works like I expect. The LED is a blue LED that is part of a LED DLP projector, along with a red and green LED. The program works as expected, insofar I only see a blue picture on the camera.
However, depending on the upload of the program onto the arduino the picture will get brighter or darker, and stays this way until I upload the program onto the arduino again. It seems random whether the picture will be bright or not.

I assume it might be because the interrupt will be called at different times depending on when I upload the program to the arduino, but I have no idea how to fix this.

I hope this is the right part of the forum to ask this.
Thanks in advance for any help!

(which rises from 2,2 to 3,2 V, so logical 0 to 1)

2.2v is not logical 0. logical 0 is a voltage below 0.6v for a 5v Atmel chip.

Mark

I think it is time to drag out the scope. Also, unless the arduino is doing something else, I think straight hardware would be the best way to get low latency.

logical 0 is a voltage below 0.6v for a 5v Atmel chip.

sp. " logical 0 is a voltage below 1.5v for a 5v Atmel chip." (except for XTAL and /RESET, for a 5V supply.)

why is this in there?

Serial.begin(9600);

You seem to have an 800 millisec delay() in your interrupt routine. There should be NO delay in an interrupt routine. It should be as short as possible so it finishes in a few microseconds.

Your interrupt routine should set a flag variable that is used by another part of your code to decide to do whatever.

230Hz is very very slow for an Arduino. I can't imagine there is any need to use interrupts.

...R

That is 800 uS, not mS. It should be OK, given there is nothing else going on in the code.

holmes4:

(which rises from 2,2 to 3,2 V, so logical 0 to 1)

2.2v is not logical 0. logical 0 is a voltage below 0.6v for a 5v Atmel chip.

Mark

I checked it and the threshold for a logical "HIGH" seems to be 3V, which as I said works for me (otherwise the interrupt wouldn't get triggered and I wouldn't see a blue picture).

Robin2:
You seem to have an 800 millisec delay() in your interrupt routine. There should be NO delay in an interrupt routine. It should be as short as possible so it finishes in a few microseconds.

Your interrupt routine should set a flag variable that is used by another part of your code to decide to do whatever.

230Hz is very very slow for an Arduino. I can't imagine there is any need to use interrupts.

...R

I know that using delays in an interrupt is very very bad, however, the 800us are over before the next interrupt gets triggered and I'm doing this so the camera gets triggered right away with the rising edge and the shutter stays open during the puls width (800us). And to put this just within the loop didn't work, I tried it, but it was slow and the timing was not consistent enough to always trigger the camera after the same amount of time after the rising edge was detected (the brightness of the blue picture was flickering too much, which I got rid of using the interrupt).

JimEli:
why is this in there?

Serial.begin(9600);

This is in there because in a further part of the program I want to do a serial read that stops the interrupt when it receives a "1", you're right though, in this code snippet it diesn't do anything.

KeithRB:
I think it is time to drag out the scope. Also, unless the arduino is doing something else, I think straight hardware would be the best way to get low latency.

What do you mean by dragging out the scope? And using a hardware solution I couldn't use variable shutter times (I'm not sure whether I want to stay with 800us) and also couldn't just switch off the interrupt routine depending on user input, which is what I'm planning on adding later with a serial.read. But what would dragging out the scope mean?

Get out an oscilloscope to actually see what is going on. And a mono-stable multivibrator (555) will let you adjust the length of the response pulse.

Can you explain exactly what the timed sequence you're trying to achieve is, and what timing resolution you're trying to achieve for each part? I mean, I guess you're trying to trigger the camera while the LED is on, but I have no idea how long the LED will be on for, how much latency there is in the camera at the start of a shot or how long it needs to take a shot. Since the overall process is only repeating at 230 Hz this seems like the sort of problem that could probably be solved without interrupts but if you need really small latency you might be forced to use them.

Long story short - NO timewasting in an interrupt routine. NO exceptions.

Get out of it in as few microseconds as possible to let the rest of the Arduino system (such as micros() and millis()) function normally.

And don’t use interrupts if you can avoid them or you are expert at debugging them.

…R

OK during further testing today, including bypassing the arduino completely and just using hardware to get the signal from the LED to a trigger signal for the camera I have found out that it is not an arduino problem, but a problem with the camera. It is behaving irratically even though the trigger signal is always constant. So as for as the arduino site is concerned, the program is solved. I have moved the delay to another function that the interrupt routine calls, even though it doesn't really make a difference.

freda42:
I have moved the delay to another function that the interrupt routine calls, even though it doesn’t really make a difference.

That is not the correct idea.

In your code the function loop() will repeat frequently.

Your ISR should set a global variable to say that the interrupt has happened.

The code in loop() should check that variable and if it is set, do whatever and unset the variable.

…R

Robin2,
but what would you do if you did that (in the loop) and it wasn't fast / constant enough? When the arduino detects a rising edge, it needs to release the camera shutter IMMEDIATELY and / or always at the same time after the rising edge, otherwise the picture will be flickering with different intensities. So far, using the delay in the interrupt routine or calling a function from it was the only way it was fast / stable enough.

When the arduino detects a rising edge, it needs to release the camera shutter IMMEDIATELY and / or always at the same time after the rising edge,

So, what is the purpose of the delay? Releasing the shutter immediately does not require a delay.

So far, using the delay in the interrupt routine or calling a function from it was the only way it was fast / stable enough.

How does adding a delay make something faster?

If you look at the code, the camera output pin is set to HIGH at the beginning at the interrupt routine, which triggers the camera shutter immediately. It then needs to stay open for a certain amount of time, which has to always be the same.
Only after the camera output is set to HIGH do I have the delay, after this the camera output is set to LOW. The camera shutter stays open for the length of the pulse it receives and this pulse width needs to always be the same. That is what my delay is for.

What I would do is, in the ISR, open the shutter, and then set up a timer interrupt to fire the required amount of time later, and return. Fast and easy.

Later, when the timer interrupt happens, close the shutter, and disable the timer. Fast and easy.

No delay()s anywhere.