Arduino IDE Programming - Simple Interrupt Application
Arduino IDE Programming - Simple Interrupt Application
Microcontroller ATmega328P
Operating Voltage 5V
ICSP Header 2
32 KB (ATmega328P)
Flash Memory
of which 0.5 KB used by the bootloader
SRAM 2 KB (ATmega328P)
EEPROM 1 KB (ATmega328P)
LED_BUILTIN 13
Length 68.6 mm
Width 53.4 mm
Weight 25 g
Interrupt
Interrupts stop the current work of Arduino such that some other work can be done.
Suppose you are sitting at home, chatting with someone. Suddenly the telephone rings.
You stop chatting, and pick up the telephone to speak to the caller. When you have finished
your telephonic conversation, you go back to chatting with the person before the telephone
rang.
Similarly, you can think of the main routine as chatting to someone, the telephone
ringing causes you to stop chatting. The interrupt service routine is the process of talking on the
telephone. When the telephone conversation ends, you then go back to your main routine of
chatting. This example explains exactly how an interrupt causes a processor to act.
The main program is running and performing some function in a circuit. However, when
an interrupt occurs the main program halts while another routine is carried out. When this
routine is finished, the processor goes back to the main routine again.
Here are some important features about interrupts −
• Interrupts can come from various sources. In this case, we are using a hardware
interrupt that is triggered by a state change on one of the digital pins.
• Most Arduino designs have two hardware interrupts (referred to as "interrupt0" and
"interrupt1") hard-wired to digital I/O pins 2 and 3, respectively.
• The Arduino Mega has six hardware interrupts including the additional interrupts
("interrupt2" through "interrupt5") on pins 21, 20, 19, and 18.
• You can define a routine using a special function called as “Interrupt Service Routine”
(usually known as ISR).
• You can define the routine and specify conditions at the rising edge, falling edge or both.
At these specific conditions, the interrupt would be serviced.
• It is possible to have that function executed automatically, each time an event happens
on an input pin.
Types of Interrupts
There are two types of interrupts −
IV. Diagram
The Arduino UNO Board
Microcontroller:
It is the most prominent black rectangular chip with 28 pins. Think of it as the brains of your Arduino.
The microcontroller used on the UNO board is Atmega328P by Atmel ( a major microcontroller
manufacturer). Atmega328P has the following components in it:
• Flash memory of 32KB. The program loaded from Arduino IDE is stored here.
• RAM of 2KB. This is a runtime memory.
• CPU: It controls everything that goes on within the device. It fetches the program instructions
from flash memory and runs them with the help of RAM.
• Electrically Erasable Programmable Read Only Memory (EEPROM) of 1KB. This is a type of
nonvolatile memory, and it keeps the data even after device restart and reset.
• Atmega328P is pre-programmed with bootloader. This allows you to directly upload a new
Arduino program into the device, without using any external hardware programmer, making the
Arduino UNO board easy to use.
Digital pins:
You can find these pins labeled “Digital 0 to 13.” These pins can be used as either input or output pins.
When used as output, these pins act as a power supply source for the components connected to them.
When used as input pins, they read the signals from the component connected to them.
When digital pins are used as output pins, they supply 40 milliamps of current at 5 volts, which is more
than enough to light an LED.
Some of the digital pins are labeled with tilde (~) symbol next to the pin numbers (pin numbers 3, 5, 6, 9,
10, and 11). These pins act as normal digital pins but can also be used for Pulse-Width Modulation
(PWM), which simulates analog output like fading an LED in and out.
Reset switch:
When this switch is clicked, it sends a logical pulse to the reset pin of the Microcontroller, and now runs
the program again from the start. This can be very useful if your code doesn’t repeat, but you want to
test it multiple times.
Crystal oscillator:
This is a quartz crystal oscillator which ticks 16 million times a second. On each tick, the microcontroller
performs one operation, for example, addition, subtraction, etc.
TX – RX LEDs:
TX stands for transmit, and RX for receive. These are indicator LEDs which blink whenever the UNO
board is transmitting or receiving data.
2. Connect the Arduino board to the computer by using the provided USB cable. It is
necessary to be able to access the board using the integrated development
environment.
3. Open the Arduino IDE installed in the computer and from the menu bar on top, open
tools and choose the right board that is being connected. In this case, Arduino Uno.
4. Also, from the tools, choose the port that the board is connected. In this case, it is in
COM13.
5. The board is now ready to be programmed using Arduino IDE.
Sample Program
Now, I will be running a sample blink program which can be already found in the
Arduino IDE. It can be accessed from the File in the menu bar, then Examples, Basics, and Blink.
This is now the sample program:
/*
Blink
Turns an LED on for one second, then off for one second, repeatedly.
Most Arduinos have an on-board LED you can control. On the UNO, MEGA and ZERO
it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN is set to
the correct LED pin independent of which board is used.
If you want to know what pin the on-board LED is connected to on your Arduino
model, check the Technical Specs of your board at:
https://www.arduino.cc/en/Main/Products
http://www.arduino.cc/en/Tutorial/Blink
*/
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
}
The result shown at the output pane found at the bottom will indicate that the program
has been successfully loaded to the board.
It can be observed that the built-in pin in the board which is located at the pin 13 will
start to blink or turn on and off continuously with a delay of 1000 ms or 1 second.
void loop() { // This contains the main code which will be run repeatedly.
for (int a = 1; a<=5; a++)
Sequence(a); // The sequence function is called here for the first to fifth sequence to be performed.
}
void setup()
{
DDRD |= 0b01111100; // This will set the digital pins 2-6 as output pins.
PORTD = ledPattern1; // This will initialize the pins on PORTD to be the first pattern.
cli(); // This will disable all interrupts.
TCCR1A = 0; // This will initialize timer1 registerA to 0.
TCCR1B = 0; // This will initialize timer1 registerB to 0.
bitSet(TCCR1B, CS12); // This will enable CS12 with clki/o/256 pre-scaler.
TCNT1 = 3036; // This will set the initial count to interrupt every second.
bitSet(TIMSK1, TOIE1);// This will enable timer1 overflow interrupt.
sei(); // This will enable all interrupts.
}
void loop() {
}
ISR (TIMER1_OVF_vect) { // The following codes will be executed if the interrupt is triggered.
TCNT1 = 3036; // The initial count will start from 3036 to 65535 to overflow every 1 second.
for (i; i <= 5;) { // In this for loop, for i = 1 to 5, it will perform the codes inside the bracket.
Sequence(i); // The sequence function created below is called in the for loop.
break;
}
}
VII. Observations
If we were to compare the ordinary delay wherein we are using the function delay(time in
milliseconds); and when we are using the interrupt service routine to function like a delay by
the Arduino, we can say that for the ordinary delay, it will not automatically have a delay unless
its function is called in the main program. However, for the interrupt service routine, we
already have a main program running, and it halts every time there is a trigger. Just like in the
running lights wherein we used the interrupt service routine to function like a delay, we set the
interrupt to be triggered every time an overflow occurs in the timer. We can set the initial
count of the timer to lengthen or shorten the time that it will take to count from the initial
count up to the maximum bit that it can handle and overflow.
If we are to load and compile our codes in the Arduino IDE, we will result to further
observations.
Delay-based
Interrupt-based
We can observe the difference between the delay-based and interrupt-based when
compiled using the Arduino IDE. When using delay-based, it takes more program storage space
of 1392 bytes which is 4%. On the other hand, when using interrupt-based, it takes less
program storage space of only 714 bytes which is 2%. When it comes to the dynamic memory,
the delay-based program makes use of 19 bytes dynamic memory while the interrupt-based
program makes use of only 11 bytes of dynamic memory.
VIII. Conclusions
In conclusion, using timers instead of delays can improve the functionality of our programs
especially when it requires precise timing. The idea of delay-based timing is simple and clear,
however, using timer-based or interrupt-based timing can provide us much more advantages
despite of being more complex such as saving CPU time and processing power. Using of delay-
based timing can significantly affect the performance of the response of the system.
IX. Recommendations
When developing programs which require precise timing, it is recommend to make use of
the interrupt service routine instead of the ordinary delay(); function as it is more accurate and
is not dependent on the number of lines a certain program has. We should avoid the use of
delay(); function for timing of events longer than 10’s of milliseconds unless the Arduino sketch
is very simple and does not require precise timing and wherein inaccuracies are negligible. It is
also recommended to access and make use of the registers within the microcontroller
embedded in the system rather than using the built-in functions by the Arduino.
X. Design Applications
For the design application, a simple blinking lights will be created wherein 2 sets of red and
green colored LEDs will blink every 0.25 seconds alternately. Therefore, I will be making use of
interrupt wherein it will be triggered every 0.25 seconds. In order to set the period of
interruption, the initial count must be altered.
Since CS12 will be used,
16 𝑀𝐻𝑧
= 62500/𝑠
256
For the quarter of a second,
62500/𝑠 ∗ 0.25 𝑠 = 15625
In order to obtain the initial count,
216 − 15625 = 49911
Therefore, TCNT1 = 49911 in order to achieve 0.25 seconds before overflowing.
Program
byte ledPortB = 0b01010101; // This will be used to initialize PORTB.
byte ledPortD = 0b01010100; // This will be used to initialize PORTD.
void setup() {
DDRB |= 0b00001111; // This will set the digital pins 8-11 as output pins.
PORTB = ledPortB; // This will initialize the pins on PORTB.
DDRD |= 0b11111100; // This will set the digital pins 2-7 as output pins.
PORTD = ledPortD; // This will initialize the pins on PORTD.
cli(); // This will disable all interrupts.
TCCR1A = 0; // This will initialize timerl register to 0.
TCCR1B = 0; // This will initialize timerl registerB to 0.
bitSet(TCCR1B, CS12); // This will enable CS12 with clki/o/256 pre-scaler.
TCNT1 = 49911; // This will set the initial count to interrupt every quarter of a second.
bitSet(TIMSK1, TOIE1); // This will enable timerl overflow interrupt.
sei(); //This will enable all interrupts.
Serial.begin(9600);
}
void loop() {
}
ISR (TIMER1_OVF_vect) { // The following codes will be executed if the interrupt is triggered.
TCNT1 = 49911; // This will set the initial count up to 65535.
Serial.println (millis());
PORTB = ~(PINB & 0b11111111); // This will perform the NAND operation in the pins of PORTB.
PORTD = ~(PIND & 0b11111111); // This will perform the NAND operation in the pins of PORTD.
}