Interrupts!
Interrupts, what are they? They are people that intermittently prevent you from doing your current work. Haha, well maybe… but we really want to know is what are they in the context of embedded electronics and microprocessors.
So, what really is an interrupt in that context? Well, there is a method by which a processor can execute its normal program while continuously monitoring for some kind of event, or interrupt. This event can be triggered by some sort of sensor, or input like a button, or even internally triggered by a timer counting to a particular number.
What are the advantages of this method?
At this point you might wonder, why use an interrupt at all? Why not just occasionally use a digitalRead on pin 2 to check its status? Won’t that do the same thing? The answer depends on the situation. If you only cared what the status of the pin was at a certain point in your code or time frame, then a digitalRead will probably suffice. If you wanted to continuously monitor the pin, you could poll the pin frequently with digitalReads. However, you could easily miss data in between reads. This missed information could be vital in many real time systems. Not to mention, the more often you’re polling for data, the more processor time that is being wasted doing that rather than executing useful code.
A quick check can solve the matter
One common problem with interrupts is they often can trigger multiple times for a single event. If we run the code above, you’ll notice that even if you press the button just once, x will increment many times. To explore why this happens, we have to take a look at the signal itself. If we took an oscilloscope to monitor the voltage of the pin at the moment we pressed the button, it would look something like this:
While the main transition of the pin is from high to low, during the process, there are several spikes which can cause multiple interrupts. There are several ways to remedy this. Often you can fix it with hardware by adding an appropriate RC filter to smooth the transition or you can fix it in software by temporarily ignoring further interrupts for a small time frame after the first interrupt is triggered. Going back to our old example, lets add in a fix that allows the variable x to only be incremented once each button press instead of multiple times.
/* Simple Interrupt example 2 by: Jordan McConnell SparkFun Electronics created on 10/29/11 license: Beerware- feel free to use this code and maintain attribution. If we ever meet and you are overcome with gratitude, feel free to express your feelings via beverage. */ int ledPin = 13; // LED is attached to digital pin 13 int x = 0; // variable to be updated by the interrupt //variables to keep track of the timing of recent interrupts unsigned long button_time = 0; unsigned long last_button_time = 0; void setup() { //enable interrupt 0 which uses pin 2 //jump to the increment function on falling edge attachInterrupt(0, increment, FALLING); Serial.begin(9600); //turn on serial communication } void loop() { digitalWrite(ledPin, LOW); delay(3000); //pretend to be doing something useful Serial.println(x, DEC); //print x to serial monitor } // Interrupt service routine for interrupt 0 void increment() { button_time = millis(); //check to see if increment() was called in the last 250 milliseconds if (button_time - last_button_time > 250) { x++; digitalWrite(ledPin, HIGH); last_button_time = button_time; } }
This fix works because each time the interrupt handler is executed, it compares the current time retrieved by the function millis() with the time the handler was last called. If its within a certain defined window of time, in this case a fourth of a second, the processor immediately goes back to what it was doing. If not, it executes the code within the if statement updating the variable x, turning on the LED and updating the last_button_time variable so the function has a new value to compare to when its triggered in the future.
Leave a Reply
You must be logged in to post a comment.