Arduino IDE Programming - Simple Interrupt Application

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 18

ECEL 12 Experiment 1: Arduino IDE Programming

Name: Pearl Joyce A. Subere Section: BSECE-4A

I. Introduction and Basic Theory

The Arduino Uno is an open-source microcontroller board designed by Arduino.cc and


based on the Microchip ATmega328 microprocessor by Atmel. It can be programmed using the
Arduino IDE (Integrated Development Environment) installed in a computer and is connected
by using a type B USB cable. It can be powered via the USB cable or by using an external battery
since it accepts voltages from 7V-12V. It has three ports namely, port B, port C, and port D.
Port B corresponds to the pins D8 to D13 on the Arduino and can be used as PCINT0 to
PCINT5. Pin D8 can be configured as ICP1 (input capture pin for timer/counter1). Pins D8 to D11
can be used as CLK0 (Divided System Clock Output), OC1A (Timer/Counter1 Output Compare
Match A Output), OC1B (Timer/Counter1 Output Compare Match B Output), and OC2A
(Timer/Counter2 Output Compare Match A Output) respectively. It also provides the serial
peripheral interface through pins D10 to D13 which can function as SS (Slave Select), MOSI
(Master Out Slave In), MISO (Master In Slave Out), and SCK (Serial Clock) respectively.
Port C corresponds to pins A0 to A5 and reset pin on the Arduino and can be used as PCINT0
to PCINT6. These analog pins utilize ADC (Analog-to-Digital Converter). For A4 and A5, they can
be configured as SDA and SCL. SDA is a data line where data is exchanged and SCL is the clock
pin.
Port D corresponds to pins D0 to D7 on the Arduino and can be used as PCINT16 to
PCINT23. Among the 14 digital I/O pins, 6 have an alternate function for PWM, and these are
pins D3, D5, D6, D9, D10, and D11. Digital I/O pins D0 and D1 are serial pins for the
communication protocol which have alternate functions of RXD (receive) and TXD (transmit)
respectively. For the pin D2 and D3, they have alternate functions of INT0 and INT1 wherein
these two pins can serve as external interrupt sources. Also, pin D3 can function as OC2B
(Timer/Counter2 Output Compare Match B Output).
The Arduino UNO Specifications Table

Microcontroller ATmega328P

Operating Voltage 5V

Input Voltage (recommended) 7-12V

Input Voltage (limit) 6-20V

Digital I/O Pins 14 (of which 6 provide PWM output)

PWM Pins 6 (Pin 3, 5, 6, 9, 10, and 11)

Analog Input Pins 6

Communication protocol UART x 1, SPI x 1, I2C x 1

DC Current per I/O Pin 20 mA

DC Current for 3.3V Pin 50 mA

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)

Clock Speed 16 MHz

LED_BUILTIN 13

Power Sources Power Jack, USB port, Vin pin

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 −

• Hardware Interrupts − They occur in response to an external event, such as an external


interrupt pin going high or low.
• Software Interrupts − They occur in response to an instruction sent in software. The only
type of interrupt that the “Arduino language” supports is the attachInterrupt() function.
II. Objectives
1. To be able to connect the Arduino Board with the Arduino IDE
2. To load a sample program from the Arduino IDE
3. To create a simple program for running lights with 5 possible sequence using 5 LEDs
4. To be able to differentiate the ordinary delay and the Arduino timer interrupt delay
5. To design a simple application program using the Arduino time delay for light sequences

III. Equipment/Tools/Materials/Components Needed


1. Arduino UNO Board with USB Cable
2. Computer
3. Arduino IDE (which will be installed in the computer)
4. Tinkercad
5. UnoArduSim
6. For the procedure, 5 red LEDs and 1 100Ω resistor.
7. For the design application, 5 red LEDs, 5 green LEDs and 1 100Ω resistor.

IV. Diagram
The Arduino UNO Board

The major components of Arduino UNO board are as follows:


USB connector
Power port
Microcontroller
Analog input pins
Digital pins
Reset switch
Crystal oscillator
USB interface chip
TX RX LEDs
USB connector:
This is a printer USB port used to load a program from the Arduino IDE onto the Arduino board. The
board can also be powered through this port.
Power port:
The Arduino board can be powered through an AC-to-DC adapter or a battery. The power source can be
connected by plugging in a 2.1mm center-positive plug into the power jack of the board.
The Arduino UNO board operates at a voltage of 5 volts, but it can withstand a maximum voltage of 20
volts. If the board is supplied with a higher voltage, there is a voltage regulator (it sits between the
power port and USB connector) that protects the board from burning out.

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.

Analog input pins:


The Arduino UNO board has 6 analog input pins, labeled “Analog 0 to 5.” These pins can read the signal
from an analog sensor like a temperature sensor and convert it into a digital value so that the system
understands. These pins just measure voltage and not the current because they have very high internal
resistance. Hence, only a small amount of current flows through these pins.
Although these pins are labeled analog and are analog input by default, these pins can also be used for
digital input or output.

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.

USB interface chip:


Think of this as a signal translator. It converts signals in the USB level to a level that an Arduino UNO
board understands.

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.

The Aruino UNO Pinout Diagram


V. Procedure
How to Connect the Arduino Board into the Arduino IDE
1. Download and install the Arduino IDE from the arduino.cc using the internet. It is
necessary to choose the appropriate version of the software that is suitable to the
computer.

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

modified 8 May 2014


by Scott Fitzgerald
modified 2 Sep 2016
by Arturo Guadalupi
modified 8 Sep 2016
by Colby Newman

This example code is in the public domain.

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 loop function runs over and over again forever


void loop() {
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
By clicking the upload button, this program will be uploaded to the board.

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.

Revised Circuit with 5 LEDs


Revised Program
int timer = 1000; // This is the delay in milliseconds.
int ledPins[] = {
2, 3, 4, 5, 6
}; // This creates an array of pins where the 5 LEDs are connected.
int pinCount = 5; // This is the number of pins.

void setup() { // This will be run once.


for (int i = 0; i < pinCount; i++) { // The array of pins are number from 0 to 4.
pinMode(ledPins[i], OUTPUT); // The values of i will be used and each of these pins will be set as
output pins.
}
}

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 Sequence(int a) { // This function is created to represent the 5 sequences.


if (a == 1) // This represents the first sequence.
{ // Sequence 1 will do the following:
for (int i = 0; i < pinCount; i++) { // As the LEDs increment by 1 starting from zero,
digitalWrite(ledPins[i], HIGH); // LEDs 0 - 4 will turn on with a delay of 1 second.
delay(timer); // It will have a delay before turning back off.
digitalWrite(ledPins[i], LOW); // LEDs 0 - 4 will turn off after the delay.
}
}
if (a == 2) // This represents the second sequence.
{ // Sequence 2 will do the following:
for (int i = pinCount - 2; i >= 0; i--) { // As the LEDs decrement by 1 starting from pinCount-2,
digitalWrite(ledPins[i], HIGH); // LEDs 3-0 will turn on with a delay of 1 second.
delay(timer); // It will have a delay before turning back off.
digitalWrite(ledPins[i], LOW); // LEDs 3-0 will turn off after the delay.
}
}
if (a == 3) // This represents the third sequence.
{ // Sequence 3 will do the following:
for (int i = 0; i < pinCount - 2; i++) { // As the LEDs increment by 1 starting from zero,
digitalWrite(ledPins[i], HIGH); // LED i will turn on
digitalWrite(ledPins[i+1], HIGH); // The consecutive LED i+1 will also turn on at the same time.
delay(timer); // It will have a delay before turning back off.
digitalWrite(ledPins[i], LOW); // LED i will turn off
digitalWrite(ledPins[i+1], LOW); // The consecutive LED i+1 will also turn off at the same time.
}
}
if (a == 4) // This represents the fourth sequence.
{ // Sequence 4 will do the following:
for (int i = pinCount - 2; i >= 0; i--) { // As the LEDs decrement by 1 starting from pinCount-2,
digitalWrite(ledPins[i], HIGH); // LED i will turn on
digitalWrite(ledPins[i+1], HIGH); // The consecutive LED i+1 will also turn on at the same time.
delay(timer); // It will have a delay before turning back off.
digitalWrite(ledPins[i], LOW); // LED i will turn off
digitalWrite(ledPins[i+1], LOW); // The consecutive LED i+1 will also turn off at the same time.
}
}
if (a == 5) // This represents the fifth sequence.
{ // Sequence 5 will do the following:
digitalWrite(ledPins[0], HIGH); // LEDs 0-4 will turn on all at the same time.
digitalWrite(ledPins[1], HIGH);
digitalWrite(ledPins[2], HIGH);
digitalWrite(ledPins[3], HIGH);
digitalWrite(ledPins[4], HIGH);
delay(timer); // After the delay of 1 second,
for (int i = 0; i < pinCount; i++) { // Each will turn off by an increment of 1 after every second.
digitalWrite(ledPins[i], LOW); // This sets the LEDs 0 to 4 to low or off.
delay(timer); // It will have a delay of 1 second before the loop starts again.
}
}
}

Using Arduino Timer Interrupt


byte ledPattern1 = 0b00000100; // This sets the starting pin in byte that will be used for pattern 1.
byte ledPattern2 = 0b01000000; // This sets the starting pin in byte that will be used for pattern 2.
byte ledPattern3 = 0b00001100; // This sets the starting pin in byte that will be used for pattern 3.
byte ledPattern4 = 0b01100000; // This sets the starting pin in byte that will be used for pattern 4.
byte ledPattern5 = 0b01111100; // This sets the starting pin in byte that will be used for pattern 5.
int i = 1; // This sets the initial value of variable i.

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;
}
}

void Sequence(int z) { // This function is created to represent 5 sequences in only 1 function.


if (z == 1) { // This will represent sequence 1.
PORTD = (PIND << 1) & 0b11111100; // This will shift up PIND by 1 and perform AND operation.
if (PORTD == 0b01000000) { // If this condition is satisfied,
PORTD = ledPattern2; // PORTD will write the 2nd pattern.
i++; // Proceed to the next sequence.
}
}
if (z == 2) { // This will represent sequence 2.
PORTD = (PIND >> 1) & 0b11111100; // This will shift down PIND by 1 and perform AND operation.
if (PORTD == 0b00000000) { // If this condition is satisfied,
PORTD = ledPattern3; // PORTD will write the 3rd pattern.
i++; // Proceed to the next sequence.
}
}
if (z == 3) { // This will represent sequence 3.
PORTD = (PIND << 1) & 0b11111100; // This will shift up PIND by 1 and perform AND operation.
if (PORTD == 0b01100000) { // If this condition is satisfied,
PORTD = ledPattern4; // PORTD will write the 4th pattern.
i++; // Proceed to the next sequence.
}
}
if (z == 4) { // This will represent sequence 4.
PORTD = (PIND >> 1) & 0b11111100; // This will shift down PIND by 1 and perform AND operation.
if (PORTD == 0b0000100) { // If this condition is satisfied,
PORTD = ledPattern5; // PORTD will write the 5th pattern.
i++; // Proceed to the next sequence.
}
}
if (z == 5) { // This will represent sequence 5.
PORTD = (PIND << 1) & 0b11111100; // This will shift up PIND by 1 and perform AND operation.
if (PORTD == 0b00000000) { // If this condition is satisfied,
PORTD = ledPattern1; // PORTD will write the 1st pattern.
i=1; // Reset to the 1st sequence.
}
}
}

VI. Results and Discussions


If we are to observe the difference between the delay() function and the interrupt service
routine, we can observe the serial monitor and display the time it takes for the program to
execute every action.
We have modified the programs to be able to display data in the serial monitor. We
added the functions Serial.begin(); and Serial.println(); in order to display the delay in every
action that the Arduino executes.
This is now the serial monitor for the program that we
created using the ordinary delay() function of the Arduino. It can
be observed that as the program becomes longer, the delay()
function becomes less accurate. Overtime, this inaccuracy will
become significant and will affect the overall performance of the
program or project especially when precise timing is required.

This is now the serial monitor for the program that we


created using the interrupt service routine of the Arduino. It can
be clearly seen that the delay is more accurate which is 1000
milliseconds or 1 second. When creating programs that require
accurate timing, the interrupt service routine is preferrable.

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.
}

In order to observe the behavior of the blinking, we have to view the


serial monitor. It can be observed from the serial monitor that the
interrupt is executed every 250 milliseconds or 0.25 seconds.

You might also like