Os horários são amplamente utilizados em todos os tipos de equipamentos eletrônicos modernos. De computadores, telefones celulares, lavadoras de roupas e carros modernos. Na indústria, quase todos os equipamentos eletrônicos usam temporizações. Neste artigo vamos aprender como gerar e usar timings e times com o Arduino.

 

 

 A placa Arduino Uno
A placa Arduino Uno

 

   Na Figura 1 podemos ver a placa Arduino Uno e a Figura 2 o IDE ou Interface de Desenvolvimento, onde os programas são escritos para o Arduino Uno, comumente chamado de Sketch. Este IDE pode ser baixado do site do Arduino.

 

 IDE ou interface de desenvolvimento
IDE ou interface de desenvolvimento

 

   O tempo é algo mensurável, isto é, podemos começar a medir o intervalo de tempo que uma determinada ação ou evento toma. Além disso, podemos programar o tempo que uma determinada ação ou evento dura. Para isso, podemos usar funções que medem ou atrasam o tempo. Na Figura 3 podemos ver a placa do Arduino Uno e como podemos transformá-lo em um temporizador. As temporizações podem ser de alto nível, conforme mostrado na Figura 4, ou de baixo nível, conforme mostrado na Figura 5.

 


 

 

 

 Legenda: 1 – Atraso de Tempo
Legenda: 1 – Atraso de Tempo

 

 

 Legenda: 1 - Atraso de tempo.
Legenda: 1 - Atraso de tempo.

 

   Isso depende do atuador que você deseja controlar, pois muitos são ativados por nível alto e outros por nível baixo. O IDE do Arduino, tem funções para fazer timings. Neste artigo, vamos estudar essas funções.

 

 

A FUNÇÃO delay ().

 

   A função delay () atrasa ou pausa o programa por um período de tempo em milissegundos. O valor do tempo em milissegundos é passado como um parâmetro para a função delay (). Lembre-se que um segundo tem 1000 milissegundos. A função delay () possui o seguinte protótipo:

atraso (ms)

Parâmetro:

ms: o número de milissegundos para pausar o programa.

Retorno:

Esta função não retorna nenhum valor.

 

 

LIGUE E DESLIGUE UM LED (BLINK) REPETIDAMENTE.

 

   Para realizar esta prática de código de exemplo, é necessária a placa Arduino Uno, como mostra a Figura 6.

 


 

 

   O LED para verificar se o programa está instalado na placa. Na Figura 6, está marcado com um círculo vermelho. O LED acenderá (ligado) e desligará (desligado) por um certo tempo. Você pode alterar o valor passado para a função delay (), para experimentar com este programa. O código de exemplo para esta prática pode ser encontrado no menu: File-> Examples-> 01.Basic-> Blink. Veja a Figura 7.

 


 

 

O seguinte é o código de exemplo:

// the setup function runs once when you press reset or power the board

void setup() {

 // initialize digital pin LED_BUILTIN as an output.

 pinMode(LED_BUILTIN, OUTPUT);

}

 

// the loop function runs over and over again forever

void loop() {

 digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)

 delay(1000);                       // wait for a second

 digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW

 delay(1000);                       // wait for a second

}

Na função setup (), o pino LED_BUILTIN é inicializado como saída. As placas Arduino Uno usam o pino 13 para conectar um LED, que está instalado na placa padrão. Para isso usamos a função:

pinMode (LED_BUILTIN, OUTPUT);

Então, na função loop (), ligamos o LED. Para isso, usamos a seguinte linha de código:

  digitalWrite (LED_BUILTIN, HIGH);

Agora, atrasamos o programa por um segundo (mil milissegundos). Fazemos isso com a linha de código:

delay (1000);

Então desligamos o LED. Fazemos isso com a linha de código:

digitalWrite (LED_BUILTIN, LOW);

Finalmente, nós retardamos o programa por um segundo. E assim, o programa continua indefinidamente, piscando o LED.

 

 

A função delayMicroseconds()

 

A função delayMicroseconds () atrasa ou pausa o programa por um período de tempo em microssegundos. O valor do tempo em microssegundos é passado como um parâmetro para a função delay (). Lembre-se que um segundo tem 1.000.000 microssegundos. A função delayMicroseconds () possui o seguinte protótipo:

delayMicroseconds (us)

Parâmetro:

us: o número de microssegundos para pausar o programa. Este parâmetro é unsignedint

Retorno:

   Esta função não retorna nenhum valor.

   Como o parâmetro passado para a função delayMicroseconds () é do tipo unsigned int, o Arduino IDE recomenda que o valor passado a essa função não seja maior que 16.383 microssegundos. Para atrasos mais longos, é melhor usar a função delay (), vista anteriormente neste artigo.

 

 

Temporização usando a função delayMicroseconds ().

 

Para verificar este programa, podemos montar um circuito conforme mostrado na Figura 8.

 


 

 

A seguir, um exemplo, em que usamos a função delayMicroseconds () para criar um atraso em microssegundos:

 

Int outPin = 8;

void setup() {

 // initialize digital pin outPin as an output.

 pinMode(outPin, OUTPUT);

}

 

// the loop function runs over and over again forever

void loop() {

 digitalWrite(outPin, HIGH);   // turn the LED on (HIGH is the voltage level)

 delayMicroseconds (50);                       // wait for 50 microseconds.

 digitalWrite(outPin, LOW);    // turn the LED off by making the voltage LOW

 delayMicroseconds (50);                       // wait for 50 microseconds.

}

Embora o atraso () e delayMicroseconds () possa ser usado para atrasos, não é recomendado o seu uso quando os atrasos são muito grandes, porque essas funções assumem o controle do programa e não permitem que outras tarefas possam ser executadas, tais como: leia sensores, verificar se um botão foi pressionado, ligar e desligue os atuadores (saídas) em momentos precisos. Para evitar o problema anterior, é necessário usar uma função chamada millis (), que permite criar atrasos e temporizações para que o programa principal possa continuar em execução e outras tarefas possam ser executadas.

 

 

A FUNÇÃO millis().

 

A função millis () retorna o número de milissegundos desde que a placa Arduino esteja executando o programa. Esse número é reiniciado, isto é, retorna a zero, após aproximadamente 50 dias. A função millis () possui o seguinte protótipo:

millis ()

Parâmetro:

Nenhum

Retorno:

O número de milissegundos desde o início do programa. O valor retornado é do tipo longo não assinado. Assim, o valor retornado é de 32 bits. Por este motivo, é necessário ter cuidado ao fazer operações aritméticas, com o valor retornado por esta função.

 

 

LIGAR E DESLIGAR UM LED (BLINK) SEM USAR A função delay ().

 

Arquivo-> exemplos-> 02.Digital-> BlinkWithoutDelay: Para executar esta prática placa Arduino Uno, como mostrado na Figura 6. O código de exemplo pode ser encontrado no menu é necessário. Observe a figura 9.

 


 

 

Temos então o seguinte código exemplo:

// constants won't change. Used here to set a pin number:

const int ledPin =  LED_BUILTIN;// the number of the LED pin

 

// Variables will change:

int ledState = LOW;             // ledState used to set the LED

 

// Generally, you should use "unsigned long" for variables that hold time

// The value will quickly become too large for an int to store

unsigned long previousMillis = 0;        // will store last time LED was updated

 

// constants won't change:

const long interval = 1000;           // interval at which to blink (milliseconds)

 

void setup() {

 // set the digital pin as output:

 pinMode(ledPin, OUTPUT);

}

 

void loop() {

 // here is where you'd put code that needs to be running all the time.

 

 // check to see if it's time to blink the LED; that is, if the difference

 // between the current time and last time you blinked the LED is bigger than

 // the interval at which you want to blink the LED.

 unsigned long currentMillis = millis();

 

 if (currentMillis - previousMillis >= interval) {

   // save the last time you blinked the LED

   previousMillis = currentMillis;

 

   // if the LED is off turn it on and vice-versa:

   if (ledState == LOW) {

     ledState = HIGH;

   } else {

     ledState = LOW;

   }

 

   // set the LED with the ledState of the variable:

   digitalWrite(ledPin, ledState);

 }

}

Todas as placas Arduino possuem um LED instalado, para fins de uso e teste. No caso da placa Arduino Uno, este LED está conectado ao pino 13. Com a seguinte linha de código podemos renomear este LED, que por padrão o compilador chama de LED_BUILTIN:

const int ledPin = LED_BUILTIN; // o número do pino do LED

   Em seguida, declaramos uma variável para armazenar o estado do LED. O nome dado a esta variável é: ledState. A seguinte linha de código faz isso:

int ledState = BAIXO; // ledState usado para definir o LED

   Para não usar a função delay (), precisamos de uma variável para armazenar a última vez que o LED mudou de estado. Esta variável deve ser do tipo unsigned long, (32 BITS), porque as vezes que vamos usar, tem esse tamanho. A seguinte linha de código faz isso:

unsigned long previousMillis = 0;        // irá armazenar a última vez que o LED foi atualizado

   A variável declarada é chamada de previousMillis e nós a inicializamos com o valor 0.

   Então, declaramos um intervalo constante chamado, ao qual atribuímos o valor de 1000. Vamos usá-lo para o intervalo para o qual ele será ligado e desligar o LED (piscar). Fazemos isso com a seguinte linha de código:

const long interval = 1000;           // intervalo das piscadas em milissegundos

   Em seguida, encontramos a função setup (), na qual o pino do LED é colocado ou configurado, como uma saída. Para isso usamos a função pinMode (), que recebe 2 parâmetros. O primeiro é o número do pino onde o LED está conectado. A segunda indica se será entrada (INPUT) ou saída (OUTPUT). Como o LED é emitido, é por isso que enviamos o valor OUTPUT para a função pinMode (). Fazemos isso com a seguinte linha de código:

pinMode (ledPin, OUTPUT);

   Então, encontramos a função loop (), que é sempre chamada e é onde escrevemos o programa. A primeira linha de código declara uma variável do tipo unsigned long, chamada currentMillis, para armazenar a hora atual ou atual, retornada pela função millis (). Lembre-se que esta função retorna o tempo desde que o cartão Arduino foi ligado ou ligado pela última vez. Para saber esse tempo, que é fornecido ou retornado em milissegundos, usamos a seguinte linha de código:

unsigned long currentMillis = millis();

   Em seguida, verificamos, se o tempo real, retornado pela função millis ()e armazenado na variável currentMillis é maior ou igual (> =) o valor quando mudou o estado do LED pela última vez e é armazenado na variávelpreviousMillis . Assim, o valor da variável previousMillis é subtraído de currentMillis. Se o resultado for maior ou igual ao atribuído ao valor constante intervalo, que é de 1000 milissegundos, em seguida, a declaração: if (currentMillis - previousMillis> = intervalo) para ou é verdadeiro e o código armazenado entre seus {}, é executada Esta verificação para ver desta vez, sem usar a função delay (), fazemos isso com a seguinte linha de código:

if (currentMillis - previousMillis> = interval) {

Então, atualizamos o valor do tempo na variável previousMillis, porque o próximo passo é mudar o estado do LED. Atualizamos esse tempo com a seguinte linha de código:

previousMillis = currentMillis;

Agora é hora de mudar o estado do LED. Para isso, verificamos o estado atual do LED. Se for baixo (LOW), então a mudamos para alto (HIGH). Fazemos isso com as seguintes linhas de código:

    if (ledState == LOW) {

      ledState = HIGH

    } mais {

      ledState = LOW;

    }

   Em seguida, alteramos o estado no pino atribuído ao LED. Aqui, é necessário usar a função digitalWrite (), que é responsável por colocar o estado de um pino parao nível alto ou baixo, como indicado no segundo parâmetro. O primeiro parâmetro é o pino onde o estado será colocado. Fazemos isso com a seguinte linha de código:

digitalWrite (ledPin, ledState);

Assim, podemos ver que o LED piscará (blink) a cada segundo. Você pode alterar o valor na constante interval, para testar o programa. Faça isso na linha do programa:

const long interval = 1000;           // interval at which to blink (milliseconds)

A vantagem desse tipo de código, mostrado neste exemplo, é poder executar outras tarefas de código, como sensores de leitura, sem interromper o programa. Por exemplo, muitas impressoras 3D, trabalham com placas Arduino, e é necessário estar velicando as chaves limitadoras, constantemente, para parar os motores de passo. Isso não pode ser feito se a função delay () for usada, com tempos muito longos. Podemos dar outros exemplos como Drones, que também trabalham com técnicas e códigos baseados no Arduino, e é necessário estar lendo sensores, para verificar se um comando chega no rádio, etc. Para isso, é necessário usar alguma forma de usar a função millis (), para fazer atrasos e horários.

 

 

LEITURA DO VALOR DO TEMPO DA FUNÇÃO millis () E ENVIANDO PARA O MONITOR DE SERIAL

 

   Esta prática e código de exemplo, o valor de tempo é lido, desde que a placa Arduino e este valor é enviado pela porta serial. Assim, é possível abrir o monitor serial e observar o valor. Para abrir o monitor serial, consulte a Figura 10, que indica o menu.

 


 

 

 

   Este programa nos permite ver como funciona a função millis (). O seguinte é o código de exemplo:

 

 

unsigned long time;

 

void setup() {

Serial.begin(9600);

}

 

void loop() {

Serial.print("Time:  ");

time = millis();

//prints time since program started.

Serial.println(time);

// wait a second so as not to send massive amounts of datas.

  delay(1000);

}

 

   Este programa inicia declarando uma variável chamada time, para armazenar o valor do tempo retornado pela função milli (). Fazemos isso com a seguinte linha de código. Observe que ele é declarado como não assinado por muito tempo.

unsigned long time;

   Então encontramos a função setup (). Nele, executamos uma função para configurar a porta serial a uma velocidade de transmissão e recepção de 9600 bauds ou bits por segundo. Nós usaremos essa porta para enviar dados para o computador, especificamente para o monitor serial. Fazemos isso com a linha de código:

Serial.begin (9600);

   Então a função loop () é chamada, que começa chamando a função:

Serial.print ("Time:");

   Com a função anterior, enviamos o texto "Time:" para o computador. Então, lemos o tempo real e o armazenamos na variável de tempo. Fazemos isso com a seguinte linha de código:

time = milis ();

   Em seguida, enviamos o valor retornado pela função millis () e armazenamos na variável time, pela porta serial. Então, podemos observá-lo no monitor serial. Fazemos isso com a seguinte linha de código:

Serial.println (time);

   Finalmente, fazemos um atraso, para não enviar muitos dados para o computador. Fazemos isso com a seguinte linha de código:

delay (1000);

Como podemos ver, este programa é mais didático. É entender como funciona a função millis (). E usamos a função delay (), com um atraso de 1000 milissegundos ou 1 segundo, para poder ver o resultado no computador. Mas, para aplicações reais e mais complexas, é necessário fazer os atrasos com a função millis ().

 

 

EVITANDO O RUÍDO DOS PULSADORES OU INTERRUPTORES

 

    Para realizar essa prática é necessário montar um circuito como o mostrado na Figura 11.

 

 Legenda: 1 - Interruptor de pressão / 2 - Resistor
Legenda: 1 - Interruptor de pressão / 2 - Resistor

 

    Os interruptores e pulsadores, quando pressionados e liberados, produzem um repique mecânico, que envia muitos pulsos para os circuitos aos quais estão conectados. Veja a Figura 12.

 

 Legenda: 1 - Salta ao pressionar / 2 - Salta ao soltar / 3 - Botão / 4 - Interruptor
Legenda: 1 - Salta ao pressionar / 2 - Salta ao soltar / 3 - Botão / 4 - Interruptor

 

 

    Em alguns casos, isso não é um problema, mas em outros, isso pode ser um problema. Tudo depende da aplicação em que esses interruptores e botões estão instalados. Para evitar isso, podemos usar um programa como o mostrado aqui. O código de exemplo pode ser encontrado no menu: . Archivo->Ejemplos->02.Digital->Debounce. Veja a Figura 13.

 


 

 

O seguinte é o código de exemplo:

// constants won't change. They're used here to set pin numbers:

const int buttonPin = 2;    // the number of the pushbutton pin

const int ledPin = 13;      // the number of the LED pin

 

// Variables will change:

int ledState = HIGH;         // the current state of the output pin

int buttonState;             // the current reading from the input pin

int lastButtonState = LOW;   // the previous reading from the input pin

 

// the following variables are unsigned longs because the time, measured in

// milliseconds, will quickly become a bigger number than can be stored in an int.

unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled

unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

 

void setup() {

 pinMode(buttonPin, INPUT);

 pinMode(ledPin, OUTPUT);

 

 // set initial LED state

 digitalWrite(ledPin, ledState);

}

 

void loop() {

 // read the state of the switch into a local variable:

 int reading = digitalRead(buttonPin);

 

 // check to see if you just pressed the button

 // (i.e. the input went from LOW to HIGH), and you've waited long enough

 // since the last press to ignore any noise:

 

 // If the switch changed, due to noise or pressing:

 if (reading != lastButtonState) {

   // reset the debouncing timer

   lastDebounceTime = millis();

 }

 

 if ((millis() - lastDebounceTime) > debounceDelay) {

   // whatever the reading is at, it's been there for longer than the debounce

   // delay, so take it as the actual current state:

 

   // if the button state has changed:

   if (reading != buttonState) {

     buttonState = reading;

 

     // only toggle the LED if the new button state is HIGH

     if (buttonState == HIGH) {

       ledState = !ledState;

     }

   }

 }

 

 // set the LED:

 digitalWrite(ledPin, ledState);

 

 // save the reading. Next time through the loop, it'll be the lastButtonState:

 lastButtonState = reading;

}

 

O programa começa declarando 2 constantes. Uma constante para o pino onde o botão está conectado. Isso é feito com a linha do programa:

const int buttonPin = 2; // o número do pino de pressão

   A outra constante é para indicar ao programa em qual pino o LED está conectado. Fazemos isso com a linha do programa:

const int ledPin = 13; // o número do pino do LED

   Depois, as variáveis ​​que serão usadas no programa são declaradas. A primeira variável é ledState, que armazenará o estado do LED. Note que esta variável é inicializada com um valor alto (HIGH). Isso é feito com a seguinte linha de programa:

int ledState = HIGH;   // o estado atual do pino de saída

   Em seguida, declaramos a variável buttonState. Isso é usado para armazenar o estado atual da leitura do botão. Note que esta variável é do tipo int. A seguinte linha de código faz isso:

int buttonState; // a leitura atual do pino de entrada

   Em seguida, declaramos a variável lastButtonState. Isso é usado para armazenar o valor do estado anterior do botão. A seguinte linha de programa faz isto:

int lastButtonState = LOW; // a leitura anterior do pino de entrada

   Em seguida, declaramos a variável lastDebounceTime. Isso é usado para armazenar o último momento em que o pino do LED é alterado (alternado). Fazemos isso com a seguinte linha de programa:

unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled

   Em seguida, declaramos a variável debounceDelay. Isso usamos para dar um atraso de leituras no pulsador e assim, ter uma leitura estável, evitando o anti revoto ou ruído. Esta variável é declarada com a seguinte linha de programa:

unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

   Então, entramos na função setup (), que é executada somente na inicialização, quando conectamos a placa Arduino, à fonte de tensão ou após uma reinicialização. Por conseguinte, esta função é onde o microcontrolador configurações, de tal modo que os pinos são entradas ou saídas, se a porta serial, baud alguns segundos, trabalhará usado, etc. Assim, com a seguinte linha de código, configuramos o pin buttonPin como entrada.

pinMode (buttonPin, INPUT);

   Então, configuramos o pino ledPin, como saída, pois é nesse pino, onde está o LED que vem com a placa Arduino Uno, feito com a seguinte linha de código:

pinMode (ledPin, OUTPUT);

   Em seguida, colocamos a saída do LED, para o valor armazenado na variável ledState. Como essa variável foi inicializada com o valor HIGH, ou seja, 1, essa saída será colocada em um nível alto. Fazemos isso com a seguinte linha de código:

digitalWrite (ledPin, ledState);

   Então, lemos o estado do botão em uma variável local. As variáveis ​​locais são declaradas dentro de uma rotina ou função e só podem ser usadas dentro dessa função. Essas variáveis ​​locais são úteis para armazenar valores que são muito temporários, isto é, precisamos deles apenas por alguns instantes. A seguinte linha de código faz isso:

int reading = digitalRead(buttonPin);

   Em seguida, verificamos se o estado do botão recentemente lido é diferente do último estado em que o botão foi alterado. Isso é feito com a seguinte linha de código:

 if (reading != lastButtonState) {

   Se a condição for atendida, atualizamos o temporizador que usamos para evitar o ruído do botão. Fazemos isso com a seguinte linha de código:

lastDebounceTime = millis ();

   Em seguida, subtrair o tempo atual retornado das millis (função), o valor do tempo da última vez que a mudança de estado botão armazenado na variável lastDebounceTime e verificar para ver se este valor for maior que o valor armazenado na variável debounceDelay, que foi programado para 50 milissegundos. Fazemos isso com a seguinte linha de código:

if ((millis () - lastDebounceTime)> debounceDelay) {

   Se o tempo for superior a 50 milissegundos, o microcontrolador executará o código entre os parênteses da instrução if. A primeira ação é verificar se o status do botão é alterado. Fazemos isso com a seguinte linha de código:

if (reading != buttonState) {

Se o estado do botão de mudou, armazenamos esse valor na variável buttonState. Fazemos isso com a seguinte linha de código:

buttonState = reading;

   Em seguida, verificamos se a alteração foi para o nível alto (HIGH). Fazemos isso com a seguinte linha de código:

if (buttonState == HIGH) {

   Se a mudança foi para alto, então é necessário alterar o estado do LED (alternar - toggle). Fazemos isso com a seguinte linha de código:

digitalWrite (ledPin, ledState);

   Em seguida, salvamos ou memorizamos o status do botão. Fazemos isso com a seguinte linha de código:

lastButtonState = reading;

   Assim, na próxima vez que o loop for repetido, ele verificará se o status do botão é alterado.

   Esta técnica é amplamente utilizada para evitar o repique de chaves limitadoras em máquinas operatrizes. A vantagem deste exemplo é permitir que mais tarefas sejam executadas sem usar a função delay ().

 

 

CONCLUSÃO

 

Como podemos ver, é muito fácil fazer atrasos com a placa Arduino. Simplesmente use a função delay (). Mas como não é aconselhável usar esta função, se os atrasos forem muito grandes, então podemos fazer atrasos usando a função millis (). Bastante, apenas de alguma forma armazenar em alguma variável a última vez que um evento aconteceu e, em seguida, subtrair o valor atual do tempo do microcontrolador, o tempo armazenado nesta variável. Tenha em mente que os valores de tempo retornados pela função millis () são do tipo longo não assinado, que no compilador do Arduino são de 32 bits. Existem bibliotecas que automatizam este processo de criação de atrasos e temporizadores, tornando muito fácil escrever código. Embora neste artigo, eu tenha descrito os exemplos linha por linha, é muito importante entender claramente como os atrasos funcionam no Arduino, para fazer projetos mais complexos. Para um erro muito comum na programação, é armazenar o valor retornado pela função millis (), que é do tipo unsigend long, que é de 32 bits, em uma variável do tipo unsigned int ou type int, ambos os quais são 16 bits. Então, quando testamos para ver se a hora que queremos tempo e termo (decorrido), com uma linha de código como o seguinte:

if ((millis () – lastDebounceTime)> debounceDelay) {

Os resultados não serão os esperados e o programa falhará. Infelizmente, os compiladores não detectam isso, pois é normal, em alguns casos, querer armazenar grandes valores em valores menores. Mas para o teste de aritmética de tempo usado na instrução: if ((millis () - lastDebounceTime)> debounceDelay), é necessário que todos os seus valores sejam de 32 bits, ou seja unsigned long.

 

 

NO YOUTUBE


NOSSO PODCAST