No último tutorial, vimos como funcionam os tempos de espera no nosso Arduino, abordamos as funções delay e micros, funções estas que nos permitem fazer “tempos de espera” na execução dos nos nossos códigos no Arduino. Hoje vamos falar de interrupções ou Interrupts.
Mas, o que são Interrupts ou interrupção?
Uma interrupção é um sinal emitido para o nosso programa que interrompe o que quer que o processador esteja a calcular naquele momento, para executar outra função distinta.
A interrupção pode acontecer através de um sinal externo (por exemplo, o pressionar de um botão) ou de um sinal interno (por exemplo, um temporizador ou um sinal de software). Uma vez chamada, a interrupção pausa o que o processador estiver a fazer naquele momento, e faz com que se execute uma outra função conhecida como Rotina de Serviço de Interrupção (ou ISR, sigla em inglês). Uma vez que a ISR tenha finalizado, o programa volta à função, que estava a ser executada antes de ocorrer a interrupção. Para saber mais sobre interrupções, podes visitar a página de referência aqui.
No Arduino podemos trabalhar com dois tipos de Interrupts os “Interrupts externos” e “Timer Interrupts” iremos agora abordar cada um destes dois tipos.
Mas, o que são Interrupts ou interrupção?
Uma interrupção é um sinal emitido para o nosso programa que interrompe o que quer que o processador esteja a calcular naquele momento, para executar outra função distinta.
A interrupção pode acontecer através de um sinal externo (por exemplo, o pressionar de um botão) ou de um sinal interno (por exemplo, um temporizador ou um sinal de software). Uma vez chamada, a interrupção pausa o que o processador estiver a fazer naquele momento, e faz com que se execute uma outra função conhecida como Rotina de Serviço de Interrupção (ou ISR, sigla em inglês). Uma vez que a ISR tenha finalizado, o programa volta à função, que estava a ser executada antes de ocorrer a interrupção. Para saber mais sobre interrupções, podes visitar a página de referência aqui.
No Arduino podemos trabalhar com dois tipos de Interrupts os “Interrupts externos” e “Timer Interrupts” iremos agora abordar cada um destes dois tipos.
Interrupts Externos
Os Interrupts, num modo geral, são efetuados ao nível do Hardware, onde um evento externo é acionado e envia um sinal para o processador. Por exemplo, quando um botão é premido ou quando recebemos informação de um sensor. Basicamente quando há uma ação ao nível do hardware e pretendemos que esta seja tida em conta ou efetuada de imediato ou seja que tenha prioridade sobre a execução do código atual. Contudo os Interrupts externos são uma ferramenta muito importante mas que se pode tornar um pouco limitada, não relativamente à sua capacidade mas em relação à sua quantidade, nem todas os pinos no Arduino suportam Interrupts externos. No caso do Arduino Uno/Duemilanove somente os pinos 2 e 3 digitais suporta Interrupts com os estados (0 e 1). Mas, em contra partida, o Arduino Due permite Interrupts em todos os pinos digitais. O código para os Interrupts externos é bastante simples e fácil de entender, basicamente basta indicar o pino de interrupt, o que irá fazer e quando irá ser executado.
Exemplo:
int interrupcao = 0;
//
Interrupt.0 encontra-se no pino digital 2
// Interrupt.1 encontra-se no pino digital 3
int botao = 2; // Pino de
ligação do botão
/* Criamos a variável do tipo “volatile”
para assegurar
que a variável estará acessível a partir
do fluxo normal
do programa e a partir da interrupção.
*/
volatile int numInterrupt = 0;
void setup()
{
Serial.begin(9600);
//
Sintaxe das interrupções:
// attachInterrupt(numero_interrupt,funcao_a_executar,modo);
// Modos LOW,CHANGE,RISING,FALLING
//
LOW: executa-se sempre que o valor no pino seja 0.
// CHANGE: executa-se
sempre que se produza uma alteração.
// RISING: executa-se
enquanto o valor vá de 0 até 1 (ou de 0 até 5 Volts).
// FALLING: executa-se
enquanto o valor vá de 1 a 0 (ou de 5 até 0 Volts).
attachInterrupt(interrupcao,
funcionInterrupcao, FALLING);
}
void loop()
{
/* Simulamos uma tarefa
que necessite de algum tempo.
Utilizamos
<em>while(true)</em> porque assim vai-se cumprir sempre a
condição e nunca
deixará de executar o código incluído.
*/
while(true)
{
Serial.print(".");
delay(500);
}
}
void funcionInterrupcao()
{
Serial.print("Interrupção número: ");
Serial.println(numInterrupt);
numInterrupt++; //Incremente o número
armazenado em “numInterrupt” em uma unidade.
}
Como podemos ver no código acima apresentado, somente temos que adicionar duas coisas para podermos usar um Interrupt externo, a declaração do Interrupt e uma função que contenha o código que queremos que seja executado. Nos parâmetros de entrada do attachInterrupt() é necessário colocar o número do Interrupt que vai ser usado, (no caso do Arduino Uno o Interrupt 0 está atrubuido ao pino digital 2 e o Interrupt 1 ao pino digital 3), a função que irá ser executada assim que o Hardware chama ou der sinal ao Arduino. No nosso código temos como último parâmetro RISING, isto significa que o Interrupt irá ser ativado quando o pino do Interrupt for de HIGH para LOW, ou seja, quando for de 0 para 1. Além do FALLING existem outros parâmetros, tais como:
No código apresentado irá imprimir pontos (.) com intervalo de meio segundo, sempre que o utilizador prima o botão que está ligado ao pino 2, uma interrupção ocorre no nosso programa e durante esse tempo é mostrada a mensagem “Interrupção número:" e indica o numero da interrupção.
- RISING – Quando vai de LOW para HIGH
- CHANGE – Quando o estado do pino é alterado
- LOW – Quando o nosso pino estiver em LOW
- HIGH – Quando o nosso pino estiver em HIGH ( esta opção só está disponível no Arduino DUE, Zero e MKR1000)
No código apresentado irá imprimir pontos (.) com intervalo de meio segundo, sempre que o utilizador prima o botão que está ligado ao pino 2, uma interrupção ocorre no nosso programa e durante esse tempo é mostrada a mensagem “Interrupção número:" e indica o numero da interrupção.
Timer Interrupts
Os Timer Interrupts têm um objetivo de funcionamento semelhante aos Interrupts Externos, só que somente é usado Software. Este tipo de Interrupts são muito pertinentes pois não contêm limitação de pinos, uma vez que tudo é tratado a nível do Software. Como não podemos ativar a interrupção segundo um tipo de estado de um determinado pino, para fazer a interrupção iremos usar o tempo. Ou seja de x em x de tempo uma interrupção vai acontecer no nosso programa e será executada uma determinada ação. Funciona exatamente da mesma maneira que os Interrupts externos, mas invés de estar à espera de uma determinada ação do Hardware, é através de tempo. Uma das utilizações para os Timer Interrupts é nas leituras dos Sonares, onde queremos que, num determinado tempo, o eco do nosso sonar seja lido, mas num tutorial mais à frente iremos falar do funcionamento dos Sonares e aí entramos em mais pormenor.
Para usarmos os Timer Interrupts no nosso Arduino é necessário usar a a biblioteca TimerOne. Podemos fazer o download da mesma nos repositórios oficiais do Arduino. Esta biblioteca pode ser usada em todos os Arduinos exceto no Arduino Due onde, neste caso, a biblioteca semelhante é a DuoTimer.
Para usarmos os Timer Interrupts no nosso Arduino é necessário usar a a biblioteca TimerOne. Podemos fazer o download da mesma nos repositórios oficiais do Arduino. Esta biblioteca pode ser usada em todos os Arduinos exceto no Arduino Due onde, neste caso, a biblioteca semelhante é a DuoTimer.
Exemplo:
#include <TimerOne.h>
unsigned long tempoanterior = 0;
const long intervalo = 1000;
void setup()
{
Timer1.initialize(2500) // Inicializa o Timer da interrupção(microsegundos)
Timer1.setPeriod(25000); // Define o Tempo em que irá ocorrer a próxima interrupção (microsegundos)
Timer1.attachInterrupt(funcionInterrupcao); // Atribui a função funcionInterrupcao ao Interrupt
Serial.begin(9600);
}
// Função para o Interrupt
void funcionInterrupcao()
{
Serial.println(“Timer Interrupt”);
}
void loop()
{
if (millis() – tempoanterior >= intervalo)
{
tempoanterior = millis();
Serial.println(“Programa a executar”);
}
}
O código acima apresentado tem o mesmo objetivo que o exemplo dos External Interrupts, mas fazendo uma pequena alteração: invés de a interrupção existir com a indicação do Hardware (neste caso do botão) é com uma indicação temporal, em cada 2,5 segundos irá haver uma interrupção no programa e irá ser executada a função funcionInterrupcao().
Como podemos observar neste artigo, o uso de Interrupts é muito simples e, ao mesmo tempo, muito útil. Após termos este conhecimento, podemos deixar de parte a função delay() que tantos problemas nos dá quando estamos a trabalhar em multitasking no nosso Arduino. Neste tutorial foi apenas exemplificado o básico da utilização dos Interrupts, iremos trabalhar mais neles em futuros projetos.
#include <TimerOne.h>
unsigned long tempoanterior = 0;
const long intervalo = 1000;
void setup()
{
Timer1.initialize(2500) // Inicializa o Timer da interrupção(microsegundos)
Timer1.setPeriod(25000); // Define o Tempo em que irá ocorrer a próxima interrupção (microsegundos)
Timer1.attachInterrupt(funcionInterrupcao); // Atribui a função funcionInterrupcao ao Interrupt
Serial.begin(9600);
}
// Função para o Interrupt
void funcionInterrupcao()
{
Serial.println(“Timer Interrupt”);
}
void loop()
{
if (millis() – tempoanterior >= intervalo)
{
tempoanterior = millis();
Serial.println(“Programa a executar”);
}
}
O código acima apresentado tem o mesmo objetivo que o exemplo dos External Interrupts, mas fazendo uma pequena alteração: invés de a interrupção existir com a indicação do Hardware (neste caso do botão) é com uma indicação temporal, em cada 2,5 segundos irá haver uma interrupção no programa e irá ser executada a função funcionInterrupcao().
Como podemos observar neste artigo, o uso de Interrupts é muito simples e, ao mesmo tempo, muito útil. Após termos este conhecimento, podemos deixar de parte a função delay() que tantos problemas nos dá quando estamos a trabalhar em multitasking no nosso Arduino. Neste tutorial foi apenas exemplificado o básico da utilização dos Interrupts, iremos trabalhar mais neles em futuros projetos.
Considerações Finais
As interrupções são uma ferramenta essencial e de grande importância no desenvolvimento de projetos que ajudam a controlar a execução do código garantindo uma execução correta e garantindo a leitura de sinais externos e mesmo internos na hora certa..
Esperamos que este artigo tenha sido útil e se gostaram comentem e partilhem. Alguma dúvida ou questão deixem em comentário ou utilizem o formulário de contatos.
Um bom dia em nome da TecnoDomos.
Conteúdo redigido ao abrigo do novo Acordo Ortográfico
Sem comentários:
Enviar um comentário