Usando a interrupção externa no seu Arduino
Imagine que você esteja fazendo seu bolo e no meio da receita seu telefone toque. Possivelmente você irá parar o que está fazendo e irá atender o telefone, assim que encerrar a chamada você irá retornar ao ponto que parou em sua receita. Quando estamos executando um tarefa muitas vezes temos que a interromper para resolver outra tarefa importante para só depois retornar do ponto que se parou. Isso se chama interrupção e é usada com frequência na programação de microcontroladores, tais como o Arduino. Uma interrupção tem dois pontos chaves, são eles:
- Condição de interrupção: É a condição que indica uma interrupção. Ela avisa ao programa que é a hora de executar uma tarefa extraordinária. No nosso exemplo, essa condição é o toque do telefone.
- Função a ser executada: Quando algo indica a interrupção, temos que executar uma lista de instruções referentes a essa interrupção. No exemplo dado, temos que parar de fazer o bolo e ir atender ao telefone. A função atender telefone é uma função extraordinária que só é executada pelo fato de ter ocorrido a condição de interrupção, o toque do telefone.
Para aprender como implementar uma interrupção, vamos fazer uma experiência simples para depois explicá-la. Nela você poderá entender melhor esse conceito de interrupção em um microcontrolador.
[toc]
Mãos à obra – Implementando uma interrupção
Componentes necessários
- Arduino Uno ou placa similar
- Botão de pressão
- LED 5mm
- Resistor 1kΩ
- Resistor 470Ω
- Fios Jumper’s
- Protoboard
Montando o projeto
Agora vamos conectar os componentes do projeto. Para isso, monte seu circuito conforme a figura a seguir.
Lembre-se: Garanta que seu Arduino esteja desligado durante a montagem e que o seu LED esteja conectado corretamente, com a perna mais longa (Anodo) conectado ao resistor e a perna menor (catodo) ao GND.
Conectando o Arduino ao computador
Conecte seu Arduino ao computador e abra a IDE Arduino.
Antes de carregar um programa, você precisa selecionar qual porta você deseja usar para fazer carregar o programa no Arduino (upload). Dentro do Arduino IDE, clique no menu Ferramentas (tools) e abra o submenu Porta(Port). Clique na porta que seu Arduino está conectado, tal como COM3 ou COM4. Geralmente aparece o nome da placa Arduino : “COM3 (Arduino/Genuino Uno)”.
Você também precisa garantir que o tipo de placa apropriado está selecionado em Ferramentas(Tools) no submenu Placa (Board).
Programando
Crie um programa (sketch) e salve com o nome de “programa_interrupcao_externa”.
Com o seu programa salvo, escreva nele o código conforme escrito abaixo.
// Daremos um nome ao pino que ficara o LED: int led = 13; void interrupcao(){ digitalWrite(led, HIGH); // Liga o LED (HIGH = nível lógico alto) delay(5000); } // Esta função "setup" roda uma vez quando a placa e ligada ou resetada void setup() { pinMode(led, OUTPUT); // Configura o pino do led (digital) como saída attachInterrupt(0,interrupcao,RISING); //Configurando a interrupção } // Função que se repete infinitamente quando a placa é ligada void loop() { digitalWrite(led, HIGH); // Liga o LED (HIGH = nível lógico alto) delay(1000); // Espera um segundo digitalWrite(led, LOW);// Desliga o LED (LOW = nível lógico baixo) delay(1000); // Espera um segundo }
Após escrever o código, clique em Carregar (Upload) para que o programa seja transferido para seu Arduino.
Colocando para funcionar
Caso tenha ocorrido tudo como esperado, o LED deve piscar intermitentemente. Quando você apertar o botão, o LED da protoboard permanecerá aceso por 5 segundos. Caso você não pressione o botão novamente, ele voltará a piscar.
Entendendo a fundo
Entendendo o Hardware
As placas Arduino possuem pinos que podem desempenhar a função de entrada de sinal para interrupção externa. No Arduino UNO são as portas digitais 2 e 3, que para tal função são nomeadas de INT0 e INT1, respectivamente. Veja a tabela a seguir com os pinos de cada placa Arduino que possuem essa qualidade.
Board | Digital Pins Usable For Interrupts |
Uno, Nano, Mini, other 328-based | 2, 3 |
Mega, Mega2560, MegaADK | 2, 3, 18, 19, 20, 21 |
Micro, Leonardo, other 32u4-based | 0, 1, 2, 3, 7 |
Zero | all digital pins, except 4 |
MKR1000 Rev.1 | 0, 1, 4, 5, 6, 7, 8, 9, A1, A2 |
Due | all digital pins |
101 | all digital pins (Only pins 2, 5, 7, 8, 10, 11, 12, 13 work with CHANGE |
Board | int.0 | int.1 | int.2 | int.3 | int.4 | int.5 |
Uno, Ethernet | 2 | 3 | ||||
Mega2560 | 2 | 3 | 21 | 20 | 19 | 18 |
32u4 based (e.g Leonardo, Micro) | 3 | 2 | 0 | 1 | 7 | |
Due, Zero, MKR1000, 101 | interrupt number = pin number |
Dessa forma, para que seja possível o uso da interrupção externa, escolhemos o pino digital 2 (INT0), no qual conectamos o botão.
Entendendo o programa
Considerando que você já sabe o básico , você já pode entender a maioria dos programas. Dessa forma, iremos nos ater às novidades.
Configurando a interrupção externa no Arduino
Para que o Arduino leia uma interrupção, devemos configurá-lo. Para tal usaremos o comando attachInterrupt().
attachInterrupt(INT,FUNCAO,MODO); //Configurando a interrupção
INT: Número da porta usada para a interrupção. No Arduino UNO INT 0 corresponde à porta digital 2 e INT 1 corresponde à porta digital 3; Como explicado anteriormente, numa interrupção temos dois pontos chaves: a condição da interrupção e a função que será executada. Dessa forma, o comando attachInterrupt é usado para informar ao programa esses dados. São eles:
FUNÇÃO: Nome da função que será chamada e executada quando ocorrer a interrupção;
MODO: Define em qual tipo de variação do sinal a interrupção será disparada. As opções são:
- LOW: Dispara a interrupção quando a tensão no pino está em 0V
- CHANGE: Dispara sempre que o sinal no pino muda de estado, borda 0V (0) para 5V(1) ou vice-versa;
- RISING: Dispara somente borda de subida, 0v (0) para 5V (1);
- FALLING: Dispara somente borda de descida, 5V (1) para 0V (0)
Em nosso programa, usaremos esse comando da seguinte forma:
attachInterrupt(0,interrupcao,RISING); //Configurando a interrupção
Portanto, temos como condição de interrupção a mudança de estado de 0V (0) para 5V(1) no pino digital 2 (INT 0) e a função a ser executa se chama interrupção.
Função interrupcao()
Função é um bloco de tarefas a serem executadas pelo programa quando solicitada.
void interrupcao(){ //Função executada quando ocorre a interrupção externa digitalWrite(led, HIGH); // Liga o LED (HIGH = nível lógico alto) delay(5000); }
No nosso caso, a função será solicitada quando ocorrer a interrupção. As tarefas a serem executadas serão: acender o LED e esperar 5 segundos.
Caso você queira saber mais sobre interrupção externa no Arduino, você pode ler sobre ela no site oficial da Arduino. Link
Fechamento
Esperamos que tenham gostado, deixe seu comentário com duvidas, sugestões ou com a foto ou vídeo de seu projeto!! Compartilhe à vontade.
função delay não funciona em funcçao e ISR
otimo tutorial, testei e funcionou redondinho, uma duvida, estou testando a função interrupt no esp8266 e nao consigo usar, o modulo fica reiniciando, alguma duvida ou sugestão? Obs: usei o mesmo código
Caros amigos estou passando a vocês a maneira de ativar a interrupção do pino através de outro pino sem ser o dois, no caso do arduino UNO são dois os pinos de interrupção os pinos digitais 2 e 3. Para ativar dois sensores de vazão a ideia é essa estou colocando um link da arduino onde disponibilizam os pinos de interrupção das outras placas.
pinMode(3,INPUT);
attachInterrupt(1, incpulso, RISING); //Configura o pino 3(Interrupção 1) para trabalhar como interrupção// Essa é a primeira opção
attachInterrupt(digitalPinToInterrupt(3), incpulso, RISING); //Configura o pino 3 como interrupção // Essa é a segunda opção
vale ressaltar que quando utilizar uma das opções a outra deve ser colocada como comentário para não haver divergências.
https://www.arduino.cc/reference/pt/language/functions/external-interrupts/attachinterrupt/
Boa tarde. É possível fazer uma interrupção no Arduino usando outra forma de iniciá-la ? Por exemplo, em vez de usar uma porta digital (2 ou 3, no caso do UNO) usar o valor de uma variável. Por exemplo, quando uma variável agisse o valor igual a 3400?
atingisse*
Tente usar o método map() e faça uma conversão
Eu tenho dois sensores, eu preciso fazer uma função ser executada qndo o sensor 1 for ativado, porem ela fica executando até q o sensor 2 seja ativado. Posso usar um while() dentro da função de interrupção? Se sim, qual parametro devo colocar no while para que verifique o sensor 2 ?
Lucas, o ideal é você não ficar muito tempo dentro da função interrupção para não “prender” seu Arduino. Uma forma é você criar variável auxiliar que trabalhará como uma bandeira. Quando a interrupção atuar você entra na função interrupção, altera essa variável e logo sai. Depois você vai usar essa variável dentro do seu código (Função loop) em um IF por exemplo (Caso a variável seja igual a tal valor execute tal coisa e depois limpa a variável).
Veja que nesse caso você pode estar em um lugar qualquer do seu programa e quando a interrupção acontecer, você rapidamente vai “levantar uma bandeira” colocando um valor nessa variável auxiliar e em seguida vai voltar a sua execução normal e só vai atender ao chamado quando for pertinente.
Olá Allan.
Infelizmente a função delay não funciona dentro da função de interrupção.
Aqui está explicando na referência do próprio Arduino:
Note
Inside the attached function, delay() won’t work and the value returned by millis() will not increment. Serial data received while in the function may be lost. You should declare as volatile any variables that you modify within the attached function. See the section on ISRs below for more information.
https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/
Abraços.
Estranho, apesar de não ser usual colocar um delay dentro da interrupção, esse programa funcionava até então. Vou ler a respeito, testar novamente e adicionar a informação nesse tutorial. Obrigado por compartilhar.
Artigo excelente! Ótimos exemplos!
Estou usando interrupção para fazer um delay no programa.
Mas está acontecendo algum problema que faz a interrupção ser ativada mesmo sem pressionar o pushbutton.
Talvez por que esteja variando a voltagem no pino e o programa detecta e aciona a interrupção.
Talvez colocar um filtro ajude nessa questão?
Valeu!
Você fez o pull-up do pino? Pode ser que está com a tensão flutuando no pino de interrupção
É possível o arduino ler 2 pinos de interrupção simultaneas? estou fazendo um projeto de sensor de fluxo so que vou usar 2 sensores de fluxo cada um numa porta pra interrupção o arduino consegue ligar 2 interrupção em 2 pinos diferentes?
consegue sim. no entendendo o Hardware mostro os pinos disponíveis para interrupções em algumas placas Arduíno.
Muito bom, obrigado!
Muito bom este post. Parabéns peça iniciativa!
Obrigado Alvacir!
Essa função interruptButton1 não é para ter esse parâmetro “estado”. Caso precise usar algum dado dentro da função, você pode usar uma variável global.
Ex.:
int estado
void interruptButton1(){
estado=estado+1;
…}
Essa variável estado pode ser usada no loop para verificar uma condição, por exemplo.
Boa noite.
Como é possível adicionar um parâmetro à função a ser chamada na interrupção? Usei o seguinte:
void interruptButton1(int estado){
…}
void setup(){
(…)
attachInterrupt(0, interruptButton1(estado), RISING);
…
}
e obtive o seguinte error de compilação:
error: invalid use of void expression
Gostei muito, claro, direto e tem tudo o que precisa, obrigado