PWM, do inglês Pulse Width Modulation, é uma técnica utilizada por sistemas digitais para variação do valor médio de uma forma de onda periódica. A técnica consiste em manter a frequência de uma onda quadrada fixa e variar o tempo que o sinal fica em nível lógico alto. Esse tempo é chamado de duty cycle, ou seja, o ciclo ativo da forma de onda.
O PWM é usado em diversas aplicações que necessitam controlar a potência, por exemplo: velocidade de motor DC, brilho da lâmpada, temperatura de resistência e muitas outras aplicações. Quase todas as GPIOs da Franzininho WiFi possuem suporte para gerar sinais PWM, apenas a GPIO 0 (Boot) e GPIO 46 não possuem esse recurso.
Nesse artigo aprenderemos usar o PWM na Franzininho WiFi com a API do Arduino. A partir desse exemplo você poderá aplicar a técnica PWM em diversos projetos.
API Analog do Arduino
Nesta sessão apresentaremos as funções usadas para configurar e gerar os sinais PWM.
analogWrite
Função para gerar um sinal PWM no pino desejado.
void analogWrite(uint8_t pin, int value);
- pin : pino selecionado
- value: configura o valor do Duty Cycle do sinal PWM, o valor está numa faixa de 0 (sempre desligado) a 255 (sempre ligado).
analogWriteResolution
Função usada para configurar a resolução em bits para todos os canais com PWM
void analogWriterResolution(uint8_t bits);
- bits : quantidade de bits para configurar o PWM ( 1 – 13)
analogWriteFrequency
Função usada para configurar a frequência em todos os canais com PWM
void analogWriterFrequency(uint32_t freq);
- freq : valor da frequência do PWM ( 1 Hz – 40 MHz)
Ao configurar as GPIOs com suporte ao PWM é necessário que se leve em consideração a aplicação desejada pelo projetista, sabendo balancear a relação entre a resolução e a frequência. De acordo com a documentação da Espressif, para frequências de 5 kHz pode ter o máximo de resolução (13 bits), em aplicações que envolvem processamento de imagem é possível utilizar na frequência máxima de 40 MHz com um 1 bit de resolução (50% de Duty Cycle).
Materiais necessários
Os materiais utilizados nesse artigo foram:
- Placa Franzininho WiFi
- Potenciômetro
- Jumpers
- Arduino IDE
Circuito Exemplo para PWM na Franzininho WiFi
O circuito proposto para esse artigo envolve apenas um componente externo, potenciômetro, um LED da placa Franzininho WiFi, mas caso deseje utilizar um LED externo para aplicação conecte a GPIO 33 e terá acesso à saída do sinal PWM gerado.
Código
O projeto proposto é controlar a intensidade do LED a partir da rotação do eixo potenciômetro. Como mencionado anteriormente, vamos alterar Duty Cycle do sinal PWM mapeando as leituras analógicas do canal ADC, utilizando a função nativa do Arduino , map().
/*
Autor : Equipe Embarcados
*/
#define MAX_ADC_VALUE 4096
#define MIN_ADC_VALUE 0
#define MAX_DUTY_CYCLE 255
#define MIN_DUTY_CYCLE 0
#define MAX_RESOLUTION 13
int adc_signal;
int duty_cycle;
const int potentiometer = 4;
const int led_yelllow = 33;
void setup()
{
/*Configura a resolução do sinal PWM */
analogWriteResolution(MAX_RESOLUTION);
/*Configura o led como saída digital*/
pinMode(led_yelllow, OUTPUT);
}
void loop()
{
/* Pega a leitura do canal ADC*/
adc_signal = analogRead(potentiometer);
/*Mapea as leituras ADC para valores entre MIN_DUTY_CYCLE - MAX_DUTY_CYCLE */
duty_cycle = map(adc_signal,MIN_ADC_VALUE,MAX_ADC_VALUE,MIN_DUTY_CYCLE,MAX_DUTY_CYCLE);
/*Gera o sinal PWM com o duty_cycle*/
analogWrite(led_yelllow, duty_cycle);
}
Simule esse projeto no Wokwi: https://wokwi.com/projects/363007792774465537
Explicação do Código
Nesta seção vamos abordar cada trecho do código a fim de esclarecer o uso das funções.
Define os máximos e mínimos do canal ADC e do Duty Cycle do PWM, além disso adicionou uma definição de resolução máxima.
#define MAX_ADC_VALUE 4096
#define MIN_ADC_VALUE 0
#define MAX_DUTY_CYCLE 255
#define MIN_DUTY_CYCLE 0
#define MAX_RESOLUTION 13Variáveis para armazenar os valores ADC (adc_signal) e para armazenar os valores mapeados do Duty Cycle (duty_cycle).
int adc_signal;
int duty_cycle;Declarando as cosntantes para mapeamento dos pinos físicos.
const int potentiometer = 4;
const int led_yelllow = 33;No void setup() , configura a resolução do sinal PWM e o LED Azul on board como OUTPUT.
void setup()
{
/*Configura a resolução do sinal PWM */
analogWriteResolution(MAX_RESOLUTION);
/*Configura o led como saída digital*/
pinMode(led_yelllow , OUTPUT);
}
No void loop(), utilizamos a função map() para realizar um reajuste de escala de valores compatíveis para o duty cycle, visto que seu intervalo é de 0 – 255 e do canal ADC é 0 – 4096. Ao realizar a leitura do potenciômetro e mapear o valor, vamos gerar o sinal PWM de acordo com o valor da variável duty_cycle.
void loop()
{
/* Pega a leitura do canal ADC*/
adc_signal = analogRead(potentiometer);
/*Mapea as leituras ADC para valores entre MIN_DUTY_CYCLE - MAX_DUTY_CYCLE */
duty_cycle = map(adc_signal,MIN_ADC_VALUE,MAX_ADC_VALUE,MIN_DUTY_CYCLE,MAX_DUTY_CYCLE);
/*Gera o sinal PWM com o duty_cycle*/
analogWrite(led_yelllow, duty_cycle);
}
Conclusão
Nesse artigo abordamos sobre uma técnica de modulação por largura de pulso (PWM), configuramos os canais e escrevemos na saída da GPIO o sinal PWM. Para realizar o controle de outros componentes que exigem uma potência maior, deve-se utilizar um circuito adicional de potência para garantir a entrega de corrente e tensão adequada. No exemplo de projeto apresentamos uma forma de abstrair uma aplicação bem comum em ambientes residenciais, o dimmer.
Para assegurar a compreensão do tema, recomendamos fortemente que faça a acionamento de motores DC e LEDs, LEDs RGB, etc.
Saiba mais
Franzininho WiFi: A placa versátil para iniciantes e desenvolvedores experientes






