Arduino: Temporizadores e Interrupcoes: mudanças entre as edições

De Wiki Cursos IFPR Foz
Ir para navegaçãoIr para pesquisar
Linha 48: Linha 48:
As '''interrupções''' permitem detectar mudanças em uma entrada sem a necessidade de checar constantemente seu estado. Quando uma interrupção é detectada uma '''rotina de tratamento de interrupção''' é chamada.
As '''interrupções''' permitem detectar mudanças em uma entrada sem a necessidade de checar constantemente seu estado. Quando uma interrupção é detectada uma '''rotina de tratamento de interrupção''' é chamada.
<!--[[Arquivo:Interrupcao.png]]-->
<!--[[Arquivo:Interrupcao.png]]-->
[[Arquivo:Interrupcao.png]]


A sintaxe das interrupções segue o comando:
A sintaxe das interrupções segue o comando:

Edição das 17h27min de 1 de agosto de 2023

Arduíno e ESP: Temporizadores e Interrupções

Temporizadores

O Arduíno e o ESP possuem várias funções que permitem implementar temporizadores e realizar medidas de tempo.

Funções de pausa temporizada no programa
delay(ms)
Pausa o programa por uma quantidade de tempo especificada como parâmetro em milissegundos. (onde 1000 milissegundos é 1 segundo).
delayMicroseconds(us)
Equivalente ao delay() com tempo especificado microssegundos.
Funções para medidas de tempo
millis()
Retorna o número de milissegundos decorridos desde que a placa Arduíno foi iniciada com o programa atual.
micros()
Equivalente ao millis() retornando o número de microssegundos.

Laboratório 1: Blink sem pausar o programa em execução

Uma aplicação interessante da função millis() é poder realizar temporizações sem pausar o programa em execução.

  • Programa Blink sem pausar programa [1]:
/*
 * Blink sem delay();
 */
const int ledPin =  13;           // pino do led
int ledState = LOW;               // estado do led
unsigned long previousMillis = 0; // tempo anterior no qual o led foi chaveado
const long interval = 1000;       // intervalo para piscar led (milliseconds)
void setup() {
  pinMode(ledPin, OUTPUT);
}
void loop() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis; // salva o tempo atual
    ledState = !ledState;           // chaveia o led    
    digitalWrite(ledPin, ledState); // atualiza estado do led
  }
}
  • Carregar e testar o programa.

Interrupções

As interrupções permitem detectar mudanças em uma entrada sem a necessidade de checar constantemente seu estado. Quando uma interrupção é detectada uma rotina de tratamento de interrupção é chamada.

A sintaxe das interrupções segue o comando:

attachInterrupt(digitalPinToInterrupt(pin), ISR, mode)

na qual:

  • digitalPinToInterrupt(pin) informa o pino de interrupção;
  • ISR é o nome da rotina de tratmento de interrupção;
  • mode indica o modo de acionamento da interrupção externa.

No Arduíno UNO as interrupções externas são acionadas pelo pino 2 (interrupção 0) e/ou pino 3 (interrupção 1).

No ESP8266 as interrupções externas são acionadas pino GPIO especificado pelo parâmetro digitalPinToInterrupt(GPIO)[2].

No Arduíno e no ESP as interrupções externas podem ser acionadas de diferentes modos:

  • CHANGE: Quando o valor do pino muda;
  • RISING: Quando o valor do pino sobe de baixo para alto;
  • FALLING: Quando o valor do pino desce de alto para baixo;

A cada mudança nos pinos de interrupção uma rotina de tratamento de interrupção será acionada.

Laboratório 2: Blink por interrupção

  • Programa Blink acionado com chave e interrupção [3]:

Conectar chave push button entre o pino 2 e o terra.

const byte ledPin = 13;
const byte interruptPin = 2;
volatile byte state = LOW;
void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), blink, FALLING);
}
void loop() {
  digitalWrite(ledPin, state);
}
void blink() {
  state = !state;
}
  • Carregar e testar o programa.
Detalhe do acionamento da interrupção
  • A função pinMode(interruptPin, INPUT_PULLUP) [4] [5] define a entrada como INPUT_PULLUP, isto é, uma entrada com resistor interno pull-up, de forma que se estiver desconectado tem valor HIGH. Assim, quando levamos a LOW através de uma chave a entrada a interrupção é acionada na transição negativa do pino FALLING.
  • Em caso de múltiplas transições no led, pode estar ocorrendo trepidações na chave (bounce).

Laboratório 3: Blink/Button

Construa um programa para acionar dois leds, um piscando em uma frequência constante (Blink) e outro que pisque quando uma chave for acionada (Button).

A chave pode ser substituída, por exemplo, por um sensor de movimento do tipo PIR. Neste caso, quando um movimento for detectado, o programa é interrompido e uma rotina de tratamento de interrupção é chamada.

Medida do período de um sinal periódico

pulseIn()

A função pulseIn() permite ler um pulso em um pino. Por exemplo, se o valor do pino é HIGH, a função espera o pino ir de LOW para HIGH, inicia uma temporização, espera o pino ir novamente para LOW e pára a temporização. Retorna o comprimento do pulso em microssegundos (ou retorna 0 em caso de erro na leitura) [6].

Esta função permite implementar, por exemplo, medidores de velocidade que emitem um pulso a cada volta, como o caso do anemômetro de uma estação meteorológica, ou do velocímetro de uma bicicleta.

Exemplos de Aplicação

Veja os exemplos de aplicação no projeto da Estação Meteorológica desenvolvida no IFPR:

  • Pluviômetro -> Emite um pulso cada 0.2794 mm de chuva dispara uma rotina de interrupção (AttachInterrupt()) para incrementar o total de mm de chuva.
  • Anemômetro -> A cada volta do anemômetro fecha um contato com a ajuda de um ímã. Para medir a velocidade do vento, mede-se o tempo médio entre cada pulso (pulseIn()) e realiza um cálculo onde se considera que, para uma velocidade do vento de 2.4 km/h, o interruptor fecha uma vez por segundo.

RTC - Real Time Clock

Um RTC (Real Time Clock) é um módulo com relógio e bateria, muito útil para montar algum tipo de temporizador ou relógio acoplado ao Arduíno, para dispor de data e hora atualizada visando setar alarmes ou executar ações em horários predeterminados.

Um RTC é capaz de armazenar e fornecer informações completas de data e hora, nos formatos de 12 ou 24 horas, incluindo dia da semana, dia do mês e ano. O número de dias de cada mês, assim como anos bissextos são ajustados automaticamente.

Os módulos RTC geralmente de comunicam com o Arduíno através de comunicação serial baseada no protocolo I2C. Este protocolo utiliza duas linhas bidirecionais denominadas Dados Seriais (SDA - Serial Data) e Relógio Serial (SCL - Serial Clock). O SDA é responsável pela troca de dados e o SCL é responsável pela sincronização entre os dispositivos.

O protocolo I2C é um protocolo tipo mestre/escravo, onde um dispositivo mestre pode controlar, pelo mesmo barramento de comunicação, até 127 dispositivos escravos, cada um identificado por um endereço formado por um byte hexadecimal.

Na comunicação entre um Arduíno e um módulo RTC, normalmente, além da alimentação e terra, são utilizados duas entradas para as linhas de comunicação SDA e SCL. Além disto, cada módulo RTC normalmente tem uma biblioteca própria, com diversas funções para trabalhar e manipular os dados do relógio, incluindo conversões para diferentes tipos de apresentação da data e hora.

Referências


Evandro.cantu (discussão) 09h51min de 9 de novembro de 2021 (-03)