I'm tring to implement an external interrupt on D2 on a Nano 3.0/328 that does other things. When the interrupt is triggered, it calls Timer1. When I enable the interrupt to activate on a falling edge, I can no longer get ethernet communication working. Does the external interrupt continuously poll for the D2 pin change state? Is is possible to run other stuff (ethernet, LCD, timer stuff) when the interrupt has not activated?
I assume I just don't know what I'm doing. Any guidence on properly setting up the external interrupt so my other code will run correctly is appreciated.
Interrupt Activation Code (From Nick Gammon's site):
Thanks, Nick. I've really been missing you. I didn't mean to accuse you of posting bad code!
I've got the code working with the attachInterrupt() function, so I must be setting up the interrupt incorrectly. Before I go through my code to post, can you tell me how much additional delay I would experience using this higher level C function? I'm scanning continuously moving film, so I want the delay as short as possible.
Nick, I just re-read you reponse and I see you advised the use of attachInterrupt(), so I guess I'm done. Do you know what kind of delay I would expect between the hardware triggering and the execution of the first line of the Interrupt Routine?
Yes, there is plenty of time. I just need to know the latency for calibration issues. Because the film is continuously moving, any delay in the triggering will result in a small vertical offset of the image, as the LED shuttering will capture it in motion. As long as the delay is consistent, it won't be a problem.
Does your Interrupt lesson discuss the +/- clock accuracy of multiple iterations of the external interrupt?
You can get perfectly consistent results (within a few nanoseconds) if you put the processor to sleep. Then the time taken to wake (from the interrupt) and start executing the ISR is always going to be a fixed amount.
I did that in this thread to draw to the VGA screen with no jitter between scan lines:
Of course, with the processor asleep, you need to turn off timer interrupts or they might throw things out, but you could work around that.
If you don't do that, I mention in the interrupt thread there will be some jitter because of various factors.
When I enable the interrupt to activate on a falling edge, I can no longer get ethernet communication working.
I'm not sure if trying to do ethernet access and processing film at a precise rate will work, but it might.
Unless I am mistaken its only timer0 that is going to cause a clash - a clash being one interrupt triggering while another is already being serviced leading to a lag while the first interrupt finishes before the second interrupt can be serviced.
So if I am correct wouldnt the easiest thing be to set the prescaler of timer0 to 0 effectivley switching it off - you will loose millis and micros but if your not using them, its a very quick and simple work around.
I think Timer0 is the only interrupt that is enabled by the init() function. You could turn off the interrupt (leave the timer running) and periodically check for an overflow. Maybe you don't need a timer.
OK, this is good stuff! If I put the Arduino to sleep, I have to figure out how to wake it up when I'm done capturing. I suppose the easiest way would be to create an interrupt on Pin 3, but I don't have any extra digital pins available. What do you think about using an analog input pin as a flag that I can check at the end of my ISR for Pin 2. If the analog pin is set HIGH, I would not put Arduino back to sleep. That will leave the Arduino available for other code servicing at the end of the capture series. For the first capture, I could put it to sleep directly with an ethernet command.
What do you think?
I'm not sure if trying to do ethernet access and processing film at a precise rate will work, but it might.
Nick, I described that problem before I started using the attachInterrupt() function at your recommendation. Everything works fine now so long as I don't attempt to make ethernet calls or do any other code servicing while the Arduino is servicing INT0. Since I write the Windows Application that interfaces with the Arduino, I can ensure that there are no extraneous calls.
renniejohnson:
I have to figure out how to wake it up when I'm done capturing. I suppose the easiest way would be to create an interrupt on Pin 3, but I don't have any extra digital pins available. What do you think about using an analog input pin as a flag that I can check at the end of my ISR for Pin 2. If the analog pin is set HIGH, I would not put Arduino back to sleep. That will leave the Arduino available for other code servicing at the end of the capture series. For the first capture, I could put it to sleep directly with an ethernet command.
I didn't totally understand that. My visualization of your requirements can't be totally matching reality.
Having said that, you can use analog ports as digital ones if you want, and also you can wake on pin-change interrupts, which can occur on any pin on the 328.
So, I can wake with analog 0. That solves that. Do I need to download the 'PinChangeInt.h' library, or can I create the PinChange interrupt with the Arduino 1.0 core library?
AmI correct in thinking the new interrupt mask will not defeat my Pin2 external interrupt routine.
This interrupt will trigger on a pin state change, right? So if I send 5v to the analog input, then run my INT0 routine, the PCINT8 interrupt will fire and wake the Arduino up when I set the input of analog 0 to 0v?
AmI correct in thinking the new interrupt mask will not defeat my Pin2 external interrupt routine.
This interrupt will trigger on a pin state change, right? So if I send 5v to the analog input, then run my INT0 routine, the PCINT8 interrupt will fire and wake the Arduino up when I set the input of analog 0 to 0v?
yes yes. The interrupt will fire again when you go back form 0v to 5v unless you disable it
I'm having trouble getting out of sleep mode after the first iteration of the pin 2 interrupt. The way my film scanning exposures work is as follows:
When INT0 on Pin 2 goes low and the INT0 ISR executes, I configure and start Timer1 for a single timed output execution of Pin9 (Timer 1 hardware pin). This Timer 1 setup was primarily designed by Nick Gammon on this forum in response to a prior post of mine.
The first time the Timer1 ISR() is called, I stop the timer.
Each time that Timer 1 completes its single iteration, I want to put the Arduino to sleep to reduce ISR jitter, as advised by Gammon earlier in this post. However, the Arduino continues to sleep and doesn't respond when the next trigger on INT0 is received. If I comment out the sleep_mode() call, it works fine.
THE CODE
This function is called once to put the Arduino into a continuous capture mode on INT0:
int LED_V3::EnableInterruptExposure()
{
pinMode (2, INPUT);
digitalWrite(2,HIGH);
g_InterruptEnabled = 1;
attachInterrupt(0, CaptureInterrupt, FALLING);
//Set Sleep Mode For Continuous Capture
set_sleep_mode (SLEEP_MODE_IDLE);
//Put Arduino To Sleep
sleep_mode ();
}
This is the ISR Function for INT0:
void CaptureInterrupt()
{
TCCR1A = 0; // reset timer 1
TCCR1B = 0;
digitalWrite (PIN_EXPOSE, HIGH); // ready to activate
pinMode (PIN_EXPOSE, OUTPUT);
//Configure Timer 1
TCNT1 = 0; // reset counter
OCR1A = g_timerCounter; // compare A register value
SetTimerMode (4, g_prescale, CLEAR_ON_COMPARE);
TIFR1 |= _BV (OCF1A); // clear interrupt flag
TIMSK1 = _BV (OCIE1A); // interrupt on Compare A Match
}
Perhaps if you describe in more detail what you are doing? You have a timer, and an external interrupt. What is connected to what? What does the timer do?