domingo, 30 de setembro de 2018

Arduino - #08 Introdução à Programação (Interrupts)

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.

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:


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

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. 


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