Introdução
Este artigo apresentará os conceitos básicos da Modulação por largura de Pulso, PWM (Pulse Width Modulation) sendo a sua sigla em inglês, e como utilizar e manipular os comandos GPIO da linguagem de programação Python no Raspberry Pi 3.
Ao final da leitura e aplicando os conceitos teóricos e práticos apresentados sobre o PWM na Raspberry, o leitor será capaz de realizar as seus próprios projetos e aplicações.
Este artigo é continuidade aos dois artigos sobre entrada e saída de dados no Raspberry publicado pelo Cleiton Bueno.
O que é PWM?
A Modulação por largura de Pulso ou Pulse Width Modulation, é uma maneira de se manipular uma forma de onda quadrada mantendo a frequência constante e se variando intervalo de tempo em que se permanece em nível lógico alto durante o período de frequência.
Existem inúmeras aplicações como, controle de velocidade rotação ou torque em motores DC, controle de luminosidade, controle de atuadores e etc.
A razão entre o tempo em estado lógico alto pelo período da frequência é chamado de duty cycle. A equação 1, apresenta essa definição:
Vamos analisar a situação apresentado na figura 01 para melhor entendermos o conceito de PWM e o duty cycle. A frequência do sinal neste exemplo é 500 Hz e foram fornecidos 5 valores diferentes de duty cycle, 0%, 25%, 50%, 75% e 100%, lembrando que o valores podem variar entre 0% e 100%. Vamos realizar os cálculos utilizando a equação 01 e iremos encontrar o valor do tempo em nível lógico alto.
Antes de tudo, deve-se calcular o valor do período da frequência desejada que é dado pela equação 02.
Para um sinal com frequência de 500 Hz, temos um período de 2 ms como calculado abaixo:
Agora então vamos realizar o cálculo do tempo em nível lógico alto para as cinco situações.
Para duty cycle de 0%:
Pode-se ver que quando o duty cycle é de 0%, o tempo em nível lógico alto é de 0s e comprovando o que é apresentado na Figura 01 no intervalo de tempo anterior a 0 s.
Para duty cycle de 25%:
Pode-se ver que quando o duty cycle é de 25%, o tempo em nível lógico alto é de 500 us e comprovando o que é apresentado na Figura 01 no intervalo de tempo entre 0 e 2 ms .
Para duty cycle de 50%:
Pode-se ver que quando o duty cycle é de 50%, o tempo em nível lógico alto é de 1 ms e comprovando o que é apresentado na Figura 01 no intervalo de tempo entre 2 e 4 ms.
Para duty cycle de 75%:
Pode-se ver que quando o duty cycle é de 75%, o tempo em nível lógico alto é de 1,5 ms e comprovando o que é apresentado na Figura 01 no intervalo de tempo entre 4 e 6 ms.
Para duty cycle de 100%:
Pode-se se ver que quando o duty cycle é de 100%, o tempo em nível lógico alto é de 2 ms, que é o mesmo tempo do período da freqüência, e comprovando o que é apresentado no intervalo de tempo entre 6 e 8 ms.
Comandos Python para PWM na Raspberry Pi
Os comandos Python utilizados para realizar a manipulação PWM da forma de onda quadrada fazem parte da biblioteca RPi.GPIO e devemos usar o comando import para poder utilizar esses comandos nos nossos códigos.
Há seguir serão apresentados as funções que nos ajudaram na manipulação PWM da forma de onda:
- pwm =GPIO.PWM(canal, frequência):
Nesta função se cria um objeto chamado “pwm”, mas poderia ser dado qualquer outro nome a este objeto, como poderemos ver no exemplo 01.O argumento “canal” é o pino em que será utilizado como saída PWM e o argumento “frequência” define a frequência do sinal aplicada na saída do pino definido no argumento “canal”.
- pwm.start(DCInicio):
Esta função inicializa o sinal PWM com um valor do duty cycle, deevendeo estar entre 0 a 100, respectivamente representando 0% a 100% .
- pwm.ChangeDutyCycle(DC):
Esta função é utilizada durante a execução do código para variar o valor do duty cycle entre 0% e 100%. Nos exemplos apresentados mais abaixo, entenderemos melhor o seu uso.
Exemplos:
Para ilustrar tudo que foi apresentada até o momento, vamos apresentar dois códigos simples desenvolvidos que se utilizam dos conceitos e definições da PWM e como as funções da biblioteca RPi.GPIO do Python são aplicadas no decorrer do código. Vamos então a eles:
Exemplo 01
Neste exemplo é realizada a variação da luminosidade de dois leds, um vermelho e outro azul, conectados na saídas dos terminais do Raspberry Pi 3. Vamos então analisar o código passo-a -passo para melhor entendimento do que está sendo realizando no código Python.
Circuito
O circuito acima apresenta as conexões a serem realizadas em um protoboard para que o circuito definido no exemplo 02 funcione corretamente. Os dois resistores de 1 kΏ em das suas extremidades conectadas respectivamente ao pino 38 e 40 da Raspberry Pi 3. Nas duas extremidades cada uma está conectada ao anodo do led. Os catodos dos led estão conectados ao pino 6 de GND Raspberry Pi.
Código Python
#Define Libraries
import RPi.GPIO as gpio
import time
#Configuring don’t show warnings
gpio.setwarnings(False)
#Configuring GPIO
pio.setmode(gpio.BOARD)
gpio.setup(38,gpio.OUT)
gpio.setup(40,gpio.OUT)
#Configure the pwm objects and initialize its value
pwmBlue = gpio.PWM(38,100)
pwmBlue.start(0)
pwmRed = gpio.PWM(40,100)
pwmRed.start(100)
#Create the dutycycle variables
dcBlue = 0
dcRed = 100
#Loop infinite
while True:
#increment gradually the luminosity
pwmBlue.ChangeDutyCycle(dcBlue)
time.sleep(0.05)
dcBlue = dcBlue + 1
if dcBlue == 100:
dcBlue = 0
#decrement gradually the luminosity
pwmRed.ChangeDutyCycle(dcRed)
time.sleep(0.05)
dcRed = dcRed - 1
if dcRed == 0:
dcRed = 100
#End code
gpio.cleanup()
exit()
As linhas 2 e 3, importam para o código as bibliotecas que permitem o uso das funções manipulação das GPIOs e de tempo.
A linha 6, faz que não se mostre os warnings no shell do Python.
As linhas 9, 10 e 11 definem respectivamente que configuração dos pinos se dará pelo números destes e que os pinos 38 e 40 serão saídas.
As linhas 14 e 17 criam dois objetos chamados pwmBlue e pwmRed, define que eles irão trabalhar na frequência de 100 Hz e respectivamente definem osn seus canais sendo os pinos 38 e 40.
As linhas 15 e 18 definem os valores iniciais do duty cycle dos objetos pwmBlue como 0% e pwmRed como 100%.
As linhas 21 e 2 definem as variáveis dcBlue e dcRed recebendo respectivamente os valores 0% e 100%.
Alinha 25 defini o loop infinito.
Entre as linhas 28 e 32 são executados os comandos que realizam ativam e incrementam o duty cycle do pino 38, e quando se alcança o valor máximo este é retornado a 0%. Isso faz com que o led azul aumente a sua luminosidade gradualmente.
Entre as linhas 35 e 39 são executados os comandos que realizam ativam e decrementam o duty cycle do pino 40, e quando se alcança o valor mínimo este é retornado a 100%. Isso faz com que o led vermelho diminua a sua luminosidade gradualmente.
As linhas 43 e 44 finalizam o código.
Exemplo 02
Neste exemplo, o controle do duty cycle é realizado por duas chaves, uma para incrementar e outra decrementar, e este representado por led que tem a sua luminosidade alterada de acordo com o seu valor. Vamos então analisar o código passo-a -passo para melhor entendimento do que está sendo realizando no código Python.
Circuito
O circuito acima apresenta as conexões a serem realizadas em um protoboard para que o circuito definido no exemplo 02 funcione corretamente. As duas chaves push-button tem um dos seus terminais conectados ao pino 1 que fornece a tensão de 3,3 V e o outro terminal de cada uma deve ser conectados respectivamente nos pinos 11 e 12. No pino 40 é conectado um dos terminais do resistor de 1 kΏ e no outro terminal deve ser conectado ao terminal do anodo do led. O terminal cátodo do led deve ser conectado ao terminal do pino 6 que é o GND da Raspberry.
Código Python
#Define Libraries
import RPi.GPIO as gpio
import time
#Configuring GPIO
gpio.setwarnings(False)
gpio.setmode(gpio.BOARD)
gpio.setup(11,gpio.IN, pull_up_down = gpio.PUD_DOWN)
gpio.setup(12,gpio.IN, pull_up_down = gpio.PUD_DOWN)
gpio.setup(40,gpio.OUT)
#Configuring GPIO as PWM
pwm = gpio.PWM(40,100)
#Initializing PWM
pwm.start(50)
dc = 50
print("Duty Cycle:",dc)
pwm.ChangeDutyCycle(dc)
#Defining the detection in rising edge
gpio.add_event_detect(11,gpio.RISING,bouncetime = 300)
gpio.add_event_detect(12,gpio.RISING,bouncetime = 300)
while True:
# Increasing the duty cycle of the PWM waveform
if gpio.event_detected(11):
dc = dc + 10
if dc == 110:
dc = 0
print("Duty Cycle:",dc)
pwm.ChangeDutyCycle(dc)
# Decreasing the duty cycle of the PWM waveform
elif gpio.event_detected(12):
dc = dc - 10
if dc == -10:
dc = 100
print("Duty Cycle:",dc)
pwm.ChangeDutyCycle(dc)
time.sleep(0.1)
gpio.cleanup()
exit()
As linhas 2 e 3 importam para o código as bibliotecas que permitem o uso das funções manipulação das GPIOs e de tempo.
Entre as linhas 6 e 10 são definidos que os pinos 11 e 12 serão entradas e utilizam um resistor de pull-down interno e que o pino 40 é uma saída.
A linha 13 é definido o objeto “pwm” e também que o seu canal será o pino 40 e a frequência será de 100 Hz.
Na linha 16 define que duty cycle iniciará em 50%.
Entre as linhas 17 e 19, é criada uma variável chamada “dc” que recebe o valor 50 representando o valor de duty cycle de 50% e esse valor é mostrada na tela do shell do Python. E este valor é aplicado na pino 40 onde está conectado o led.
Entre as linhas 22 e 23 definem que os pinos 11 e 12 interpretem como nível lógico alto uma borda de subida e é aplicado um debounce de 300 ms.
A linha 25 implementa o loop infinito.
Entre as linhas 28 e 33 é interpretado se o evento da borda de subida no pino 11 aconteceu, sendo verdadeiro, a variável “dc” é incrementada em 10 unidades causando um aumento no duty cycle de 10%, também é mostrado no shell essa alteração e consequentemente a luminosidade do led aumenta. Caso o valor do variável “dc” ultrapasse o valor 100, ela é recebe ao valor 0.
Entre as linhas 36 e 41 é interpretado se o evento da borda de subida no pino 12 aconteceu, sendo verdadeiro, a variável “dc” é decrementada em 10 unidades causando um diminuição no duty cycle de 10%, também é mostrado no shell essa alteração e consequentemente a luminosidade do led aumenta. Caso o valor do variável “dc” seja menor o valor 0, ela é recebe ao valor 100.
A linha 43 causa um atraso de 100 ms segundo na execução do próxima iteração do loop infinito.
As linhas 45 e 46 finalizam o código.
Conclusão
Pode-se observar que a PWM é uma aplicação que é utilizada para inúmeras aplicações e que as funções contidas na biblioteca Python para o Raspberry Pi 3 são simples de serem manipuladas e aplicadas, o que pode ser observado pelos exemplos de códigos apresentados neste artigo.
Referências
Raspberry PI-GPIO – output com Python – https://embarcados.com.br/raspberry-pi-gpio-output-com-python/
Raspberry PI–GPIO input com Python – https://embarcados.com.br/raspberry-pi-gpio-input-com-python/
PWM na Raspberry Pi com Python – https://embarcados.com.br/pwm-raspberry-pi-python/
Figura 01 – https://www.hho4free.com/pulse_width_modulator__pwm.html

















Boa tarde! Não consigo encontrar esta informação em outro lugar, por favor qual a quantidade de canais PWM que o Raspberry possui e quais são esses canais nos GPIOs? Desde já, obrigado!
Que sucesso! Excelente artigo! Que venham outros! Recomendo a leitura ?