Skip to Content

Piscar LEDs com Frequências Diferentes

Piscar LEDs com Frequências Diferentes

Neste tutorial, vais aprender a piscar vários LEDs em simultâneo, mas com frequências, atrasos e ciclos de trabalho diferentes, usando um Arduino ou ESP32.

Piscar um único LED é fácil e um dos primeiros exemplos que aprendes ao começar a programar Arduino. No entanto, piscar vários LEDs independentemente com frequências diferentes pode ser complicado. Neste tutorial, vamos usar a biblioteca ezOutput para simplificar isso. Também te vou mostrar como converter frequências e ciclos de trabalho em tempos de atraso.

Mas antes disso, vamos ver as peças necessárias.

Overview

Peças Necessárias

Segue a lista das peças necessárias. Usei um Arduino Uno para este projeto, mas qualquer outra placa Arduino, ou placa ESP8266/ESP32 também funciona bem. E claro, se já tens LEDs e resistores adequados (220Ω), não precisas de os comprar.

Arduino

Arduino Uno

USB Data Sync cable Arduino

Cabo USB para Arduino UNO

Dupont wire set

Conjunto de fios Dupont

Half_breadboard56a

Breadboard

Kit de resistores e LEDs

Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.

O que é Frequência

Antes de montarmos o circuito e escrevermos o código, vamos falar rapidamente sobre o que é Frequência. Isso vai simplificar as coisas mais tarde. Acho que a definição mais simples de Frequência é a seguinte:

Frequência é o número de vezes que um padrão ou evento se repete dentro de um segundo.

Por exemplo, se um LED liga e desliga quatro vezes dentro de um segundo, ele pisca com uma frequência de 4 Hertz (Hz). Vê a imagem abaixo, onde ilustramos o sinal de comutação para um LED.

LED blinking with 4Hz Frequency
Piscar de LED com frequência de 4Hz

O evento de ligar o LED ocorre 4 vezes em 1 segundo. Portanto, a frequência é 4 Hz. Se ligássemos e desligássemos o LED 10 vezes por segundo, ele piscaria a 10Hz.

Normalmente, a fórmula para frequência f é dada por 1 dividido pelo tempo T que leva para completar um ciclo (evento de comutação):

Formula to calculate the Frequency f
Fórmula para calcular a Frequência f

É a mesma coisa, só ao contrário ; ) Por exemplo, se ligarmos o LED quatro vezes num segundo (=4Hz), significa que leva T =1/4 = 0,25 segundos para um evento de comutação. Vamos colocar isso na fórmula acima: 1/T = 1/0,25s = 4Hz.

Frequência de uma onda senoidal

Note que a frequência não se limita a pulsos retangulares ou eventos de comutação. Podemos calcular a frequência para qualquer tipo de padrão ou evento repetitivo. Um caso comum é uma onda senoidal, que poderíamos usar para pulsar (diminuir e aumentar) o brilho de um LED.

O exemplo abaixo mostra uma onda senoidal ao longo de dois períodos. Suponhamos que um período dura 0,1 segundos. A onda senoidal teria então uma frequência de 10Hz.

Sine wave with a Frequency of 10Hz
Onda senoidal com frequência de 10Hz

Função tone() do Arduino

Note que a linguagem Arduino tem uma função incorporada chamada tone() que permite criar um sinal de onda quadrada com frequência entre 16Hz e 4MHz (usando um Arduino Uno). No entanto, para a maioria das aplicações onde queres piscar LEDs, mesmo a frequência mais baixa de 16Hz é normalmente demasiado rápida. Muitas vezes queremos piscar mais devagar e, por isso, não podemos usar tone() .

Além disso, tone() só pode gerar ondas quadradas com ciclo de trabalho de 50%. Vamos falar rapidamente sobre ciclos de trabalho e porque isso é uma limitação quando queremos piscar LEDs.

O que é Ciclo de Trabalho

Suponhamos que queres ligar e desligar um LED a cada segundo. Agora sabemos que isso seria uma frequência de 1Hz. Mas durante quanto tempo desse segundo o LED deve estar ligado e quanto tempo desligado? Se quisermos que esteja ligado 50% desse segundo (=0,5), isso seria um ciclo de trabalho de 50%. A definição de ciclo de trabalho é a seguinte:

Ciclo de trabalho é a percentagem do tempo em que um sinal está alto comparado com o tempo total de um período.

Portanto, se ligarmos o LED apenas por 0,1 segundos durante esse segundo, e o deixarmos desligado pelos restantes 0,9 segundos, isso seria um ciclo de trabalho de 10%. A imagem abaixo ilustra três ondas quadradas com diferentes ciclos de trabalho.

Different Duty Cycles
Diferentes ciclos de trabalho

Poderias pensar que podes usar o sinal PWM gerado por analogWrite() para piscar LEDs com diferentes ciclos de trabalho. No entanto, novamente, a frequência do sinal PWM é demasiado alta ( 490Hz / 980Hz ) para piscar LEDs, embora possas alterar um pouco a frequência. Mas é um pouco complexo e ainda não nos dá as frequências que normalmente queremos para piscar LEDs.

Piscar um único LED

Piscar um único LED com uma frequência e ciclo de trabalho dados é fácil. Digamos que pegamos no exemplo anterior e queremos piscar um LED com frequência de 1Hz e ciclo de trabalho de 50%. Isso significa que temos de ligar o LED por 0,5s = 500ms, desligar por mais 0,5s e repetir o ciclo. Isso é essencialmente o conhecido exemplo Blink:

void loop() {
  digitalWrite(ledPin, HIGH);
  delay(500); 
  digitalWrite(ledPin, LOW);
  delay(500); 
}

Podemos fazer isso de forma um pouco mais elegante e flexível implementando uma função blink() para piscar um LED com uma frequência dada f e um ciclo de trabalho dc :

void blink(int ledPin, float f, float dc) {
  digitalWrite(ledPin, HIGH);
  delay(1000 * dc / f);
  digitalWrite(ledPin, LOW);
  delay(1000 * (1 - dc) / f);
}

Isto é essencialmente o mesmo que antes, mas calculamos o delay() com base na frequência e no ciclo de trabalho. O atraso para a fase ligada do LED é 1000 * dc / f baseado na fórmula da frequência discutida acima. O cálculo para a fase desligada é o mesmo, mas com a percentagem restante do ciclo de trabalho 1 – dc em vez de dc.

Uma implementação completa para um LED ligado ao pino 9 que pisca com frequência de 1Hz e ciclo de trabalho de 50% seria assim:

int ledPin = 9;

void setup() {
  pinMode(ledPin, OUTPUT);
}

void blink(int ledPin, float f, float dc) {
  digitalWrite(ledPin, HIGH);
  delay(1000 * dc / f);
  digitalWrite(ledPin, LOW);
  delay(1000 * (1 - dc) / f);
}

void loop() {
  // 1 Hz, 50% duty cycle
  blink(ledPin, 1, 0.5);
}

Isto funciona bem para um único LED, mas não para vários LEDs com frequências diferentes! Experimenta. Por exemplo, não podes piscar dois LEDs, um com frequência de 1Hz e outro com frequência de 2Hz, usando o código seguinte.

// This doesn't work!
void loop() {
  // 1 Hz, 50% duty cycle
  blink(ledPin1, 1, 0.5);
  // 2 Hz, 50% duty cycle
  blink(ledPi2, 2, 0.5);
}

A razão é que os atrasos (piscares) não são executados independentemente (em paralelo), mas em sequência.

Se quiseres piscar vários LEDs com diferentes frequências e ciclos de trabalho, as coisas ficam muito mais complexas. Temos um tutorial sobre isso: Control Multiple LEDs With Different Delays with Arduino . E se precisares de mais informações sobre como piscar LEDs, dá uma vista de olhos em How To Blink An LED Using Arduino (4 Different Ways ).

No entanto, neste tutorial vamos usar a biblioteca ezOutput ezOutput para controlar vários LEDs a piscar. Isso vai simplificar muito a nossa tarefa.

Usar a biblioteca ezOutput para piscar LEDs

Primeiro, precisas de instalar a ezOutput library através do Library Manager antes de a poderes usar.

Installing exOutput Library via Library Manager
Instalar a biblioteca ezOutput via Library Manager

Funções principais da biblioteca ezOutput

A biblioteca ezOutput tem várias funções, mas vamos precisar apenas de três.

A função ezOutput() recebe um pino como entrada e cria um objeto ezOutput à sua volta. Ela fornece as funções especiais para pinos que vamos discutir a seguir.

ezOutput(int pin)

Com a função blink() podes desligar ( low ) e ligar ( high ) um pino por intervalos de tempo dados ( lowTime , highTime ). Os intervalos de tempo estão em milissegundos.

void blink(unsigned long lowTime, unsigned long highTime)

Poderias fazer isso com a função delay() também, como vimos no exemplo acima. Mas a função blink() tem a vantagem de poder ser chamada independentemente para diferentes pinos com diferentes atrasos.

Para isso acontecer, precisas de chamar a função loop() do ezObject() dentro do loop principal do Arduino.

void loop(void)

Parece complicado? Na verdade é muito fácil. Vamos ver um exemplo.

Piscar três LEDs com diferentes tempos de atraso

No código de exemplo abaixo, vamos piscar três LEDs ligados aos pinos 11, 10 e 9 com três frequências e ciclos de trabalho diferentes.

#include "ezOutput.h"

ezOutput led1(11);
ezOutput led2(10);
ezOutput led3(9);

void setup() {
  led1.blink(500, 500);  // 1Hz,  dc=50%
  led2.blink(250, 250);  // 2Hz,  dc=50%
  led3.blink(10, 90);    // 10Hz, dc=90%
}

void loop() {
  led1.loop();
  led2.loop();
  led3.loop();
}

Bibliotecas e Objetos

Começamos por incluir a biblioteca “ezOutput.h”. Depois criamos três instâncias da classe ezOutput chamadas led1, led2 e led3, cada uma correspondendo a um LED diferente ligado aos pinos 11, 10 e 9 respetivamente.

#include "ezOutput.h"

ezOutput led1(11);
ezOutput led2(10);
ezOutput led3(9);

Função Setup

Na função setup() configuramos cada LED para piscar a uma frequência e ciclo de trabalho específicos usando o método blink() da biblioteca ezOutput . Os parâmetros de intervalo de tempo passados ao método blink() são escolhidos de forma a representar a frequência e ciclo de trabalho indicados nos comentários.

led1.blink(500, 500);  // 1Hz, 50% duty cycle
led2.blink(250, 250);  // 2Hz, 50% duty cycle
led3.blink(10, 90);    // 10Hz, 90% duty cycle

Por exemplo, para led1 : se queremos uma frequência de piscar de 1Hz e ciclo de trabalho de 50%, temos de ligar o LED por 500 ms e desligar por mais 500 ms. Portanto, passamos um tempo desligado de 500 ms e um tempo ligado de 500 ms para a função blink para conseguir isso.

Se cortarmos os tempos de atraso ao meio (250 ms), o LED pisca duas vezes mais rápido, o que nos dá uma frequência de 2Hz para led2 .

E se quisermos mudar o ciclo de trabalho, precisamos de alterar a proporção entre os tempos ligado e desligado. Assim, para led3 o tempo ligado é 90 ms e o tempo desligado é 10 ms, o que nos dá um ciclo de trabalho de 90% e uma frequência de 10Hz.

Função Loop

Na função loop() chamamos continuamente o método loop() para cada objeto LED. Isso garante que cada LED pisca independentemente e de acordo com os parâmetros de piscar definidos na função setup() .

void loop() {
  led1.loop();
  led2.loop();
  led3.loop();
}

Este código funciona bem, mas tens de converter frequências de piscar e ciclos de trabalho em tempos ligados e desligados para a função blink. Podemos tornar isso mais conveniente encapsulando esta parte numa função personalizada.

Piscar três LEDs com diferentes frequências

No exemplo de código seguinte fazemos exatamente o mesmo que no exemplo acima. Três LEDs nos pinos 11, 10 e 9 vão piscar com frequências 1Hz, 2Hz, 10Hz e ciclos de trabalho 50%, 50%, 90%, respetivamente.

#include "ezOutput.h"

ezOutput led1(11);  
ezOutput led2(10); 
ezOutput led3(9);

void setFrequency(ezOutput &led, float f, float dc=0.5) {
  led.blink(1000*(1-dc)/f, 1000*dc/f); 
}

void setup() {
  setFrequency(led1, 1, 0.5);
  setFrequency(led2, 2, 0.5);
  setFrequency(led3, 10, 0.9);
}

void loop() {
  led1.loop(); 
  led2.loop(); 
  led3.loop(); 
}

No entanto, adicionámos a nossa própria função setFrequency() que recebe uma frequência f e um ciclo de trabalho dc e converte para os parâmetros lowTime e highTime necessários para a função blink() .

void setFrequency(ezOutput &led, float f, float dc=0.5) {
  led.blink(1000*(1-dc)/f, 1000*dc/f); 
}

Em vez de blink() podemos agora chamar setFrequency() na função setup() diretamente com frequências e ciclos de trabalho.

void setup() {
  setFrequency(led1, 1, 0.5);
  setFrequency(led2, 2, 0.5);
  setFrequency(led3, 10, 0.9);
}

Note que fornecemos os ciclos de trabalho como uma razão (0,9) e não como percentagem (90%). Se quiseres, basta dividir o parâmetro dc por 100 dentro da função.

Com a função setFrequency() podes agora trabalhar com frequências e ciclos de trabalho, em vez de tempos ligados e desligados, se for mais conveniente.

Este código funciona também para ESP32 e ESP8266. Basta selecionar a placa correta e alterar as constantes dos pinos em conformidade. Por exemplo, estou a usar os seguintes pinos na minha placa WEMOS Lolin ESP32 lite:

ezOutput led1(GPIO_NUM_22);  
ezOutput led2(GPIO_NUM_19); 
ezOutput led3(GPIO_NUM_23);

A seguir, vamos montar o circuito com os três LEDs que queremos piscar.

Circuito de piscar com três LEDs

A imagem seguinte mostra o circuito de piscar com os seus três LEDs e resistores limitadores de corrente.

Blink circuit with three LEDs
Circuito de piscar com três LEDs

Montar é fácil. Primeiro liga o terra (GND) do Arduino à linha de terra da breadboard (fio azul). Depois coloca os três LEDs. Certifica-te que os pinos curtos dos LEDs (cátodo) estão ligados à linha de terra.

Cada um dos pinos longos dos LEDs está ligado a um resistor limitador de corrente de 220Ω. Os resistores estão ligados aos pinos GPIO 11, 10 e 9 do Arduino. E é tudo. Aqui está o teu circuito de piscar.

O pequeno vídeo seguinte mostra o código e o circuito em ação. Os LEDs piscam com frequências de 1Hz, 2Hz, 10Hz e ciclos de trabalho de 50%, 50%, 90%, respetivamente.

Divirte-te a experimentar diferentes frequências, ciclos de trabalho e mais LEDs.

Conclusões

Em conclusão, aprendemos com sucesso como piscar vários LEDs em simultâneo com diferentes frequências, atrasos e ciclos de trabalho usando um Arduino ou ESP32. Ao compreender os conceitos de frequência e ciclo de trabalho, conseguimos criar um circuito para controlar os LEDs e escrever o código necessário para obter os padrões de piscar desejados.

A biblioteca ezOutput tornou isto muito simples e viste que é fácil adicionar as tuas próprias funções personalizadas para tornar tudo ainda mais conveniente.

Se tiveres alguma dúvida, consulta as FAQ ou escreve um comentário.

Divirte-te ; )

Perguntas Frequentes

P: Posso usar diferentes tipos de LEDs com frequências variadas no mesmo circuito?

R: Sim, podes usar diferentes tipos de LEDs com frequências variadas no mesmo circuito. Basta ajustar os tempos de atraso no teu código para cada LED para obter a frequência de piscar desejada.

P: É possível sincronizar o piscar de vários LEDs com frequências diferentes?

R: Embora possa ser difícil sincronizar o piscar de vários LEDs com frequências muito diferentes, podes experimentar ajustar os tempos de atraso para conseguir um padrão visualmente apelativo. Considera usar arrays ou funções para gerir o tempo de cada sequência de piscar dos LEDs.

P: Posso controlar o brilho de cada LED juntamente com a sua frequência?

R: Sim, podes usar um sinal PWM durante o tempo ligado do LED para conseguir esse efeito. No entanto, a biblioteca ezOutput não suporta isso diretamente. Terás de alterar e expandir o código.

P: Como posso adicionar mais LEDs ao circuito e controlá-los individualmente?

R: Para adicionar mais LEDs ao circuito e controlá-los individualmente, podes ligar cada LED a um pino digital separado no Arduino ou ESP32. Depois, no teu código, define variáveis para o tempo de atraso e ciclo de trabalho de cada LED para os controlar independentemente.

P: Qual é o número máximo de LEDs que posso piscar simultaneamente com frequências diferentes?

R: O número máximo de LEDs que podes piscar simultaneamente com frequências diferentes depende do poder de processamento e da memória do teu microcontrolador. Normalmente, podes controlar vários LEDs com frequências variadas desde que tenhas pinos digitais e memória suficientes para o código.

P: Posso usar componentes externos como transistores ou shift registers para expandir o número de LEDs controláveis?

R: Sim, podes usar componentes externos como transistores ou shift registers para expandir o número de LEDs controláveis. Usando esses componentes, podes aumentar efetivamente o número de LEDs que controlas com o teu Arduino ou ESP32, permitindo padrões de iluminação mais complexos. Para mais detalhes, vê o nosso tutorial: More Arduino Outputs With 74HC595 Shift Register .

P: Como calculo o tempo de atraso para uma frequência específica de piscar?

R: Para calcular o tempo de atraso para uma frequência específica de piscar, podes usar a fórmula: tempo de atraso = 1 / (2 * frequência). Por exemplo, se quiseres que um LED pisque a 2 Hz (com ciclo de trabalho de 50%), o tempo de atraso será 250 milissegundos.

P: Como posso criar padrões de LED mais complexos, como efeitos de desvanecimento ou pulsação?

R: Para criar padrões de LED mais complexos como desvanecimento ou pulsação, podes incorporar lógica adicional no teu código usando técnicas como interpolação linear para efeitos de desvanecimento ou funções sinusoidais para efeitos de pulsação. Manipulando os níveis de brilho ao longo do tempo, podes obter padrões de iluminação dinâmicos.

P: É possível sincronizar o piscar dos LEDs com eventos externos ou sensores?

R: Sim, é possível sincronizar o piscar dos LEDs com eventos externos ou sensores incorporando leituras de sensores ou gatilhos de eventos no teu código. Por exemplo, podes ajustar a frequência de piscar dos LEDs com base em entradas de sensores como intensidade de luz, temperatura ou deteção de movimento.

P: Posso implementar diferentes padrões de piscar, como sequências alternadas ou aleatórias, para vários LEDs?

R: Sim, podes implementar diferentes padrões de piscar como sequências alternadas ou aleatórias para vários LEDs definindo padrões ou sequências únicas para cada LED no teu código. No entanto, para esses efeitos, usar um shift register é frequentemente mais fácil. Para mais detalhes, vê o nosso tutorial: More Arduino Outputs With 74HC595 Shift Register

P: Como posso fazer os LEDs piscarem num padrão específico, como batimento cardíaco ou onda?

R: Para fazer os LEDs piscarem em padrões específicos como batimento cardíaco ou onda, podes definir sequências personalizadas de estados ligados e desligados para cada LED no teu código. Programando o tempo e as transições entre esses estados, podes criar padrões únicos que imitam vários efeitos.

P: Posso incorporar som ou música para sincronizar o piscar dos LEDs com sinais áudio?

R: Sim, podes sincronizar o piscar dos LEDs com som ou música analisando sinais áudio ou integrando bibliotecas de som no teu código. Ao detetar batidas ou frequências na entrada áudio, podes coordenar os padrões de piscar dos LEDs para combinar com o ritmo ou intensidade do som, melhorando a experiência audiovisual.

P: Como posso tornar os padrões de LED interativos, respondendo a entradas do utilizador ou comandos externos?

R: Para tornar os padrões de LED interativos e responsivos a entradas do utilizador ou comandos externos, podes implementar protocolos de comunicação como Bluetooth ou Wi-Fi para receber comandos de um smartphone ou computador. Interpretando essas entradas no teu código, podes ajustar dinamicamente os padrões de LED com base nas interações do utilizador ou gatilhos externos.