0

Interrupções e Timer no Arduino

Hoje vamos falar um pouco sobre como fazer Interrupções, muito importantes mas pouco usado no Arduino.
As interrupções permitem que os microcontroladores respondam a eventos sem que seja preciso a todo o momento comunicar com o Arduino para verificar se sofreu alteração de estado.

 

Tipos de interrupção

Existem 2 tipos de interrupção; a externa e a interna. O Arduino UNO, Nano e Mini utilizam os pinos 2 e 3 para interrupção, o Leonardo utiliza o 0,1,2,3 e o 7. O DUE utiliza todos.
No Arduino UNO podemos usar apenas dois pinos para as interrupções de hardware, sendo essa uma das razões de serem pouco utilizadas. Abaixo temos uma tabela com algumas placas e seus respectivos pinos de interrupções.

 

 

Função (ou ISR – Interrupt Service Routine)

Quando uma interrupção acontece, uma rotina será executada, caso a interrupção esteja sendo tratada. Logo, cria-se uma função de um nome qualquer que não tenha retorno (deve ser ‘void’) e que não receba parâmetros.

Quando se pretende tratar interrupções, sua inicialização deve ser feita em setup(), desse modo:

 

//attachInterrupt(PIN,ISR,CONDITION);
attachInterrupt(digitalPinToInterrupt(2), changeState, FALLING);
//attachInterrupt(PIN,ISR,CONDITION);
attachInterrupt(digitalPinToInterrupt(2), changeState, FALLING);

 

Desse modo, quando ocorrer o evento na queda de tensão do pino, a função changeState() será chamada. Pode parecer um exemplo estúpido, mas fará bastante sentido observando o seguinte código.

 

boolean ON_OFF = 0;
void changeState(){
    ON_OFF = !ON_OFF;
}

void setup(){
    Serial.begin(9600);
    attachInterrupt(digitalPinToInterrupt(2), changeState, FALLING);
}

void loop(){
    while(1){
        //considere que o programa morreria aqui, porque mais nada pode acontecer
        delay(1000);
    }
    Serial.println("Nunca irá ver esta mensagem");
}

boolean ON_OFF = 0;
void changeState(){
    ON_OFF = !ON_OFF;
}
 
void setup(){
    Serial.begin(9600);
    attachInterrupt(digitalPinToInterrupt(2), changeState, FALLING);
}
 
void loop(){
    while(1){
        //considere que o programa morreria aqui, porque mais nada pode acontecer
        delay(1000);
    }
   Serial.println("Nunca irá ver esta mensagem");
}

 

Como podem ver, na função loop() tem um outro loop while(1) (que não deveria existir, é errado fazer isso, uma vez que a função loop() já mantém o programa rodando ‘infinitamente’). Esse loop while() prende a execução do código para sempre, tanto que a mensagem nunca será observada. O loop while() não faz nada a não ser gerar delays.

 

Como funciona a interrupção?

Interrupções tem maior prioridade para a MCU, então quando uma interrupção ocorre (e ela está sendo tratada), a função (ISR) relacionada ao tratamento é executada, depois o código principal é retomado de onde parou.

Isso funciona como uma thread. No Arduino é bastante simplificado esse procedimento, de forma que erros são evitados.
Se necessário, podemos desativar as interrupções por tempo e depois reativá-las em outra parte do código:

noInterrupts();
//executa alguma coisa que não deve ser tratada...
interrupts();
//volta à rotina comum.
noInterrupts();
//executa alguma coisa que não deve ser tratada...
interrupts();
//volta à rotina comum.

Se quiser desabilitar a interrupção em apenas um determinado pino, também é fácil:

detachInterrupt(digitalPinToInterrupt(pin));
detachInterrupt(digitalPinToInterrupt(pin));

 

Timer com Arduino

Deixemos de lado as interrupções por enquanto e vamos entrar em outro assunto; contagem de tempo, ou timer.
Mais uma vez, o Arduino permite a utilização de tempo de uma maneira muito simples:

int secs    = 0;
int minutes = 0;
int hours   = 0;
long interval = 1000; //ms
long previous = 0;
unsigned long current = millis();

void myClock(){
  secs +=1;
  if (secs> 59){
    minutes +=1;
    secs = 0;
  }
  if (minutes> 59){
    hours += 1;
    minutes = 0;
  }
  if (hours> 24){
    ...
  }
}
...
loop(){
...
  if(current - previousMillis> interval) {
    //guarda o novo periodo...
    previou = current;
    // inverte o estado do LED
    ON_OFF = !ON_OFF;
    digitalWrite(PIN_LED, ON_OFF);
    myClock();
  }
}

int secs    = 0;
int minutes = 0;
int hours   = 0;
long interval = 1000; //ms
long previous = 0;
unsigned long current = millis();
 
void myClock(){
  secs +=1;
  if (secs> 59){
    minutes +=1;
    secs = 0;
  }
  if (minutes> 59){
    hours += 1;
    minutes = 0;
  }
  if (hours> 24){
    ...
  }
}
...
loop(){
...
  if(current - previousMillis> interval) {
    //guarda o novo periodo...
    previou = current;
    // inverte o estado do LED
    ON_OFF = !ON_OFF;
    digitalWrite(PIN_LED, ON_OFF);
    myClock();
  }
}

Gostaram deste artigo ? Deixem o vosso comentário no formulário a baixo.

Não se esqueçam de fazer like na nossa <a href="https://www.facebook.com/arduinoportugal.pt/" target="_blank">Página no Facebook</a>.

Podem ainda colocar as vossas dúvidas no nosso <a href="https://arduinoportugal.pt/forums/">Forum da Comunidade Arduino em Portugal</a> ou no nosso<a href="https://www.facebook.com/groups/arduinoportugal" target="_blank"> Grupo no Facebook Arduino Portugal - Qual o teu projeto?</a>

Comments

Comentários

Admin

Deixar uma resposta