Controle de potência via PWM - ESP32

Controle de potência via PWM - ESP32 

A modulação por largura de pulso (PWM) é uma técnica amplamente utilizada em diversos meios, principalmente para controle de potência e velocidade. Neste tutorial, você aprenderá a configurar o PWM no ESP32 através do recurso LED PWM e fazer um LED "respirar" (fade) ou acender com metade do brilho.

[toc]

Pulse Width Modulation

Controle de potência via PWM - ESP32

Com o PWM, podemos controlar a tensão média em um componente, e por consequência a potência, como um LED, a velocidade de um motor DC ou até converter o sinal PWM criado (onda quadrada) para uma onda senoidal com a adição de alguns poucos itens.

As imagens (GIF) abaixo mostram o duty cycle variando, que altera a tensão média entregue ao componente. Em alguns casos como motores, também é preciso configurar corretamente a frequência de chaveamento e ter atenção ao nível de pico máximo aceito na alimentação, entretanto isso ficará de "lição de casa" para pesquisarem.

Controle de potência via PWM - ESP32
Brilho de LED com a variação do duty cycle
Controle de potência via PWM - ESP32
Tensão média com a variação do duty cycle

 


Mãos a obra - Variando o brilho do LED

Componentes necessários

Código do projeto

void setup()
{
	pinMode(2, OUTPUT);//Definimos o pino 2 (LED) como saída.

	ledcAttachPin(2, 0);//Atribuimos o pino 2 ao canal 0.
	ledcSetup(0, 1000, 10);//Atribuimos ao canal 0 a frequencia de 1000Hz com resolucao de 10bits.
	
}

void loop()
{
	for (int i = 0; i < 1024; i++)
	{
		ledcWrite(0, i);//Escrevemos no canal 0, o duty cycle "i".
		delay(2);
	}

	for (int i = 1023; i > 0; i--)
	{
		ledcWrite(0, i);
		delay(2);
	}
}

Colocando para funcionar

O código fará um "fade" no LED, dando a sensação de "respiração", aumentando e diminuindo o brilho gradativamente.


Entendendo a fundo

Software

-Função ledcAttachPin()

ledcAttachPin(PINO, CANAL);

Esta função apenas atribui um pino a um canal. Podemos escolher qualquer pino a qualquer canal, este vai de 0 a 15, totalizando 16 canais.

Cada canal é independente do outro, mas você também pode atribuir vários pinos a um mesmo canal.

Pino: Qualquer.

Canal: 0 - 15.

-Função ledcSetup()

ledcSetup(CANAL, FREQUENCIA, RESOLUCAO);

Esta função configura um canal para trabalhar a uma determinada frequência e resolução.

Canal: 0 - 15.

Frequência: 1 - 40MHz.

Resolução: 1 - 16 bits.

-Função ledcWrite()

ledcWrite(CANAL, DUTY CYCLE);

Esta função "escreve" o duty cycle ao canal. Lembramos que o valor colocado no parâmetro duty cycle não é em porcentagem e sim em decimal.

Exemplo: para um duty cycle de 50% com 10bits (2^10 = 1024) de resolução, devemos escrever 512.

Canal: 0 - 15.

Duty cycle: 0 - 100% (em decimal).


Indo além com PWM 

Tensão média

Podemos calcular a tensão média (V) entregue ao componente através de uma simples conta que relaciona o sinal HIGH com o duty cycle.

Sinal HIGH do ESP32 (Vcc): ~3.3V.

Duty cycle: 32%.

Ao efetuar a conta de 3.3*0.32, chegamos a conclusão que a tensão média (Vm) entregue será de 1.056V!

Vamos testar este código e verificar as tensões com um multímetro.

void setup()
{
	pinMode(23, OUTPUT);//Definimos o pino 23 como saída.
	pinMode(22, OUTPUT);//Definimos o pino 22 como saída.
	pinMode(21, OUTPUT);//Definimos o pino 21 como saída.
	pinMode(19, OUTPUT);//Definimos o pino 19 como saída.

	ledcAttachPin(23, 0);//Atribuimos o pino 23 ao canal 0.
	ledcSetup(0, 1000, 10);//Atribuimos ao canal 0 a frequencia de 1000Hz com resolucao de 10bits.
	ledcWrite(0, 256);//Escrevemos um duty cycle de 25% no canal 0.

	ledcAttachPin(22, 1);//Atribuimos o pino 22 ao canal 1.
	ledcSetup(1, 1000, 10);//Atribuimos ao canal 1 a frequencia de 1000Hz com resolucao de 10bits.
	ledcWrite(1, 512);//Escrevemos um duty cycle de 50% no canal 1.

	ledcAttachPin(21, 2);//Atribuimos o pino 21 ao canal 2.
	ledcSetup(2, 1000, 10);//Atribuimos ao canal 2 a frequencia de 1000Hz com resolucao de 10bits.
	ledcWrite(2, 768);//Escrevemos um duty cycle de 75% no canal 2.

	ledcAttachPin(19, 3);//Atribuimos o pino 19 ao canal 3.
	ledcSetup(3, 1000, 10);//Atribuimos ao canal 3 a frequencia de 1000Hz com resolucao de 10bits.
	ledcWrite(3, 1023);//Escrevemos um duty cycle de 100% no canal 3.
}

void loop()
{

}

Testando este código e verificando o pino respectivo com um multímetro, podemos perceber que as contas são iguais ou próximas. Lembrando que o próprio multímetro tem sua faixa de precisão (erro), que neste caso é (+-0.5% + 3D com 1mV de resolução).

Todos os testes a seguir tem Vcc teórico de 3.3V, as imagens são as leituras do nosso multímetro.

Caso 1, 25% = 0.825V

25%

Caso 2, 50% = 1.65V

50%

Caso 3, 75% = 2.475V

75%

Caso 4, 100% = 3.3V

100%

Todos os valores lidos, mesmo estando próximos aos teóricos, há o erro do multímetro. Aplicando a formula de erro ao valor lido, todos os valores obtidos estão dentro da faixa tolerável de erro, ou seja, estão corretos!

Frequência X resolução

Um problema recorrente com alguns componentes é a frequência necessária de funcionamento. Motores por exemplo, é bastante usado entre 20kHz e 200kHz.

O recurso "LED PWM" do ESP32 é baseado em um clock de 80MHz, logo podemos fazer algumas contas básicas para se chegar a frequência máxima com a resolução escolhida.

Nos exemplos acima, foi usado uma frequência de 1kHz com 10bits de resolução, entretanto pode ser necessário o uso de uma frequência muito maior e a resolução é uma das barreiras para isso. Vamos fazer essa conta com os dados citados para chegar na frequência máxima (Fm).

A resolução deve ser em decimal e não "bits".

80MHz / 10bits

80000000 / 1024 = 78125Hz

A frequência máxima que conseguimos chegar com uma resolução de 10bits no ESP32 é de ~78kHz. Vamos testar!

Caso 1, 32kHz com 10bits

Caso 1

Caso 1.1, 80kHz com 10bits

Caso 1.1

Como feito nas contas, a frequência máxima realmente foi de ~78kHz para 10bits, mesmo atribuindo 80kHz no código. Agora vamos brincar com frequências mais altas deixando a resolução em 3bits e ver a frequência máxima.

80MHz / 3bits = Fm

80000000 / 8 = 10MHz

Caso 2, 2MHz com 3bits

Caso 2

Caso 2.1: 11MHz com 3bits

Caso 2.1

Novamente, as contas mostraram um máximo de 10MHz e mesmo atribuindo 11MHz, ficou limitado a 10MHz.


Considerações finais

O PWM é extremamente útil em diversos projetos, permitindo o controle de potência, velocidade, brilho e até inversores (DC-AC) através da modulação da tensão. Apesar de parecer simples apenas "inverter o estado do pino", com frequências um pouco mais altas, não é qualquer microcontrolador que aguenta se manter com uma frequência estável ou se quer chegar em frequências acima de 10MHz. O ESP32 com 1bit de resolução nos permite chegar a 40MHz, dando uma vasta gama de possibilidades em aplicações.


Software Timer - ESP8266

Software Timer - ESP8266

Software Timer

Em várias situações, é necessário de certa forma, a manipulação do tempo em micro controladores. O jeito mais fácil é pelas funções básicas (delay e derivados), porém, normalmente, estas funções travam o micro controlador, e com isto, você é incapaz de ler botões ou algo do tipo enquanto o delay não acabar. Isto além de gerar terríveis problemas nos mais variados projetos, não é uma pratica saudável. Neste tutorial, vamos aprender sobre o OS_TIMER do ESP8266, este timer é baseado no software do ESP8266 e o limite inferior é 1mS e máximo de ~2 horas. Este software timer não é aconselhado para projetos em que o tempo é crítico. Apesar de nossos testes darem certa confiança, por ele ser baseado em software, alguns fatores podem atrasa-lo em alguns mS, tome cuidado.

 

Demonstrando a diferença

Neste exemplo apenas para comparação do Software Timer, usaremos um exemplo que acende 3 LEDs a cada 1 segundo e enquanto isso, ficaremos  enviando dados na Serial para mostrar o funcionamento do código. Antes de ir para o software timer, testem este código abaixo no ESP8266 e veja no Serial Monitor como é o recebimento de informações.

Neste código, estamos usando Delay para fazer o acionamento simples dos LEDs. Você perceberá que só irá aparecer mensagens a cada 4 Segundos.

long x;//Variavel para mostrar o desenvolvimento do codigo no Serial Monitor.

void setup()
{
   pinMode(D1, OUTPUT);//Define D1 como Saida.
   pinMode(D2, OUTPUT);//Define D2 como Saida.
   pinMode(D3, OUTPUT);//Define D3 como Saida.

   Serial.begin(9600);//Inicia a comunicaçao Serial para provar que o codigo nao trava.
}

void loop()
{
   led();//Sub rotina para acender os LED`s.

   Serial.println(x++);//Mostra no serial monitor o desenvolvimento do codigo.
}

void led()//Sub rotina para acender os LED`s.
{
   digitalWrite(D1, 1);//Acende o led 1.
   delay(1000);//Aguarda 1 segundo.
   digitalWrite(D2, 1);//Acende o led 2.
   delay(1000);//Aguarda 1 segundo.
   digitalWrite(D3, 1);//Acende o led 3.
   delay(1000);//Aguarda 1 segundo.
   digitalWrite(D1, 0);//-
   digitalWrite(D2, 0);//-
   digitalWrite(D3, 0);//-Apaga os 3 leds.
   delay(1000);//Aguarda 1 segundo.
}

Após ver que o ESP só pula para a linha debaixo da função led() a cada 4 segundos, percebe-se que o ESP fica travado durante 4 segundos apenas para acender os LEDs, inutilizando totalmente o seu uso para outras coisas.

Agora chega de papo e vamos ao Software Timer.

 

 

Normalmente, na maioria dos casos, as funções de delay travam o código até que o delay se acabe. Ao usar delay(60000), o micro controlador ficará travado por 1 Minuto nesta linha até que o tempo acabe e não fara mais nada. Se desejarmos acender um LED a cada 30 segundos, isto irá gerar muitos problemas usando delay, então, usaremos os Timer’s. O Timer gera uma interrupção no sistema a cada intervalo de tempo e voltara a fazer a sua rotina padrão após terminar suas instruções.

Lembre-se, A rotina de um timer (Interrupção) não pode conter comandos de Delay, Serial e vários outros. A rotina do ISR deve ser a mais breve possível e normalmente usamos flag’s armazenadas na RAM para agilizar o processo e evitar erros internos.

 

Mãos à obra

Componentes necessários

Montando o projeto

 

Veja como ficou nossa montagem:

 

 

Código do projeto

#include <user_interface.h>;//Biblioteca necessaria para acessar os Timer`s.

os_timer_t tmr0;//Cria o Timer. Maximo de 7 Timer's.

volatile byte status;//Variavel armazenada na RAM para Status do LED.
long x;//Variavel para mostrar o funcionamento do Codigo.

void setup()
{
   os_timer_setfn(&tmr0, led, NULL); //Indica ao Timer qual sera sua Sub rotina.
   os_timer_arm(&tmr0, 1000, true);  //Inidica ao Timer seu Tempo em mS e se sera repetido ou apenas uma vez (loop = true)
                                     //Neste caso, queremos que o processo seja repetido, entao usaremos TRUE.

   pinMode(D1, OUTPUT);//Define D1 como Saida.
   pinMode(D2, OUTPUT);//Define D2 como Saida.
   pinMode(D3, OUTPUT);//Define D3 como Saida.

   Serial.begin(9600);//Inicia a comunicaçao Serial.
}

void loop()
{
   leitura();//Sub rotina para processar os LED`s.

   //O codigo irá funcionar normalmente sem que haja delays e acendendo os LED`s no intervalo definido.
   //Para demonstraçao, abra o Serial monitor e voce vera que o codigo continua normalmente.

   Serial.println(x++);//Print para provar que o codigo nao trava. Abra o Serial monitor e veja
                       //que o codigo continua rodando enquanto os LED`s piscam a cada 1 Segundo.
}

void leitura()//Sub rotina para processar os LED`s.
{
   switch (status)
   {
   case(1)://Caso status seja 1, acenda o led 1.
      digitalWrite(D1, 1);
   break;

   case(2)://Caso status seja 2, acenda o led 2.
      digitalWrite(D2, 1);
   break;

   case(3)://Caso status seja 3, acenda o led 3.
      digitalWrite(D3, 1);
   break;

   case(4)://Caso status seja 4, Apague os 3 LED`s.
      digitalWrite(D1, 0);
      digitalWrite(D2, 0);
      digitalWrite(D3, 0);
   break;
   }
}

void led(void*z)//Sub rotina ISR do Timer sera acessada a cada 1 Segundo e mudara o status do LED.
{
   if (status == 4)//Verifica se o maximo foi alcançado para resetar a contagem.
   {
      status = 0;
   }

   status++;
}

 


Entendendo a fundo

Hardware

As ligações são simples, apenas sendo necessário ligar o pino de cada LED em sua correspondente porta, não esquecendo o uso de resistores para limitar a corrente/tensão e também não queimar o LED. O outro pino do LED no GND. Este é o básico para um LED funcionar.

Software

 

-Função os_timer_setfn()

os_timer_setfn(&tmr0, led, NULL);

Esta função atribui uma função sua à rotina do Timer. Neste caso, definimos a nossa função led() ao timer tmr0, que criamos anteriormente.

 

-Função os_timer_arm()

os_timer_arm(&tmr0, 1000, true);

Com esta outra, é definido o tempo do timer e também se irá se repetir (loop). Neste caso, definimos ao timer tmr0, que entre na função anteriormente atribuída, a cada 1000mS. Se você não precisa que isso seja repetido, troque true por false, desativando o loop.

 

Finalizando

Comparando os dois códigos, podemos perceber claramente a diferença entre fazer tarefas com um Timer ou Delay. Enquanto o primeiro código só mostra a mensagem a cada 4 Segundos, o segundo mostra a mensagem diversas vezes ao mesmo tempo que gerencia os LEDs. Você pode usar isso em vários projetos em que é preciso fazer tarefas em tempos definidos, sem travar o resto do sistema com Delay. Dúvidas? Sugestões? Críticas? Comente abaixo!


conhecendo a família esp

O que é ESP8266 - A Família ESP e o NodeMCU

O que é ESP8266 - A Família ESP e o NodeMCU 

Que tal conectar seu projeto à imensidão da internet de forma simples e barata? Essa é a proposta do ESP8266 que têm sido cada vez mais usado em projetos de automação e robótica para conectar as mais diversas ideais à internet. Neste tutorial você irá conhecer a família de microcontroladores ESP8266 que é tendência no mundo dos Makers e nos mais diversos exemplos de Internet das Coisas (IoT), e também aprenderá como funciona a sua programação e dar o primeiro upload. Entre eles: ESP-01 A, ESP-7, ESP-12E e NodeMcu 

[toc]

O que é ESP8266?

É possível que você já tenha ouvido falar sobre o ESP8266, ele tem se tornado cada vez mais popular entre projetos de Internet das Coisas!

Os ESP8266's são microcontroladores que já possuem tudo que é necessário para se conectar a Internet. Ou seja, eles são como um Arduino com integração Wi-Fi.

Outro ponto importante é que eles são pequenos e isso viabiliza projetos pequenos.

Fig 1: ESP-01 A ESP8266
Fig 1: ESP-01 A

Um exemplo é o ESP8266-01, esta minúscula placa, também chamado de "Módulo" por alguns, tem um potencial muito maior do que o aparenta, veja algumas especificações:

  • CPU: 32bit RISC Tensilica Xtensa LX106 rodando à 80/160 MHz.
  • RAM: 64 kB.
  • FLASH: QSPI Externo - de 512 kB até 4 MB.
  • WiFi: IEEE 802.11 - b/g/n.

Comparando diretamente com o Arduino, o ESP8266 tem um poder de processamento maior, porem há poucas GPIO's para usar nesta versão. Esta versão, conta apenas com 4 GPIO's para uso, sendo que dois são para comunicação Serial.

Para resolver esse problema de pinos insuficientes, existem versões mais robustas do ESP8266, como por exemplo, este ESP8266-12:

Fig 2: ESP8266 ESP-12
Fig 2: ESP-12

Este, é exatamente o mesmo que o anterior, mas conta com mais GPIO's disponíveis para uso geral.

 

APLICAÇÕES DO ESP8266

 

 

O uso para esse Micro controlador beira ao "Infinito", já que conta com poder de processamento e WiFi embutido. Com ele, também é possível ser usado como um "Módulo" com outros Micro controladores, isto pode ser feito através de comandos AT. Além disso, as versões menores, como o 01 ou 09, são muito usados como uma "Ponte Serial-WiFi", já que contam com poucos pinos; sendo assim, é possível receber dados por um aplicativo/WEB e enviar estes dados para um Arduino e acender uma lampada por exemplo! O oposto também é possível, enviar dados do Arduino para um aplicativo ou página WEB.

 

Algumas aplicações interessantes:

  • Automação residencial.
  • Rede de sensores.
  • Robótica.
  • Comunicação Wireless entre MCU's (Micro controller Unit).
  • Aplicativos e Paginas WEB para controle geral.
  • Monitoramento de Informações remotamente.
  • E muito mais.

 

 

A Família ESP8266

Apresentaremos as principais características dos dois principais mais vendidos, que são: ESP8266-01 e o ESP8266-12 na versão NodeMCU.

ESP-01

Este pequeno ESP8266-01, conta com poucos pinos para uso geral, porém é muito usado por conta do seu tamanho como a "Ponte Serial-WiFi", segue a explicação dos pinos:

GND: Terra-GND.

Vcc: Alimentação de 3,3V.

RESET: Reset ativo quando em LOW.

CH_PD: Chip enable, deve estar em HIGH para funcionamento do MCU.

RXD: Receive data, usado para receber dados da comunicação de outros MCU's.

TXD: Tansmit data, usado para transmitir dados a outros MCU's.

GPIO0: GPIO (General Purpose Input/Output), este pino é para uso geral, tanto como Entrada/Saída e até Digital/PWM. Deve estar conectado ao GND para novos Upload's (Veja na Fig 4, Boot Modes).

GPIO2: GPIO para uso geral.

 

Para dar um novo upload à este carinha, você precisa de um conversor Serial (FTDI) para transmitir os dados até ele. As ligações são estas:

Lembrando que a alimentação deve ser feita com 3,3V, inclusive o Rx. Com isto, voce já sera capaz de dar upload de seus códigos.

 

NodeMCU

 

NodeMcu esp8266 ESP-32
NodeMcu
Pinagem NodeMcu
Pinagem NodeMcu

Esta versão do ESP8266-12 vem numa placa de desenvolvimento, chama-se de NodeMCU. Esta belezinha conta com conversor Serial e regulador de tensão próprio, não sendo necessário ambos como nas outras versões fora da placa. Também há pinos próprios para I2C, SPI, Analógico e outros.

 

GPIO's ESP8266:

Esta imagem, mostra todas definições de GPIO's do ESP8266, inclusive durante o boot, em que alguns pinos são mantidos em certos estados.


Mãos à obra

Este projeto é  o "Hello world" no mundo de Microcontroladores. Você irá ensinar a dar o primeiro upload para piscar o LED_BUILTIN (LED OnBoard) do ESP8266-01 usando um FTDI externo. Pegue a pipoca e vamos la!

 

Componentes necessários

As ligações ficarão parecidas com esta:

 

Estas são ligaçoes básicas, porém, para cada novo upload, é necessário colocar o GPIO0 em GND, como foi mostrado no esquema, GPIO0 já esta em GND. Não se esqueça dele sempre que for fazer um novo Upload!

 

Preparando a IDE Arduino

Usaremos a Arduino IDE, mas você pode programa-lo com LUA, ou até a propria SDK.

1-) Vá em Arquivos>Preferencias, e adicione este link em "URLs Adicionais...": http://arduino.esp8266.com/stable/package_esp8266com_index.json

2-) Vá em Ferramentas>Placa>Gerenciador de placas.

3-) Procure pelo ESP8266 e instale-o.

4-) Após instalar as placas do ESP8266, selecione-a em Ferramentas>Placa>Generic ESP8266 Module. (Estou usando o ESP8266-01, caso voce use por exemplo o NodeMCU, selecione NodeMCU...).

5-) Agora, é só configurar a placa, aconselho a usarem igual ao da foto. Testem primeiramente com o upload a 115200@bps, caso nao funcione, teste com outras velocidades! Não se esqueça de selecionar a porta que estiver seu FTDI.

Sua IDE esta pronta para funcionar com o ESP8266! Vamos ao código!

 

Código do projeto

void setup()
{
   pinMode(LED_BUILTIN, OUTPUT);//Habilita o LED interno como Saida.
}

void loop()
{
   digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));//Inverte o estado do LED de acordo com a leitura.
   delay(250);
}

 


Entendendo a fundo

Software

-Função pinMode()

pinMode(LED_BUILTIN, OUTPUT);//Habilita o LED interno como Saida.

Esta função define um pino, como saída ou entrada. Neste caso, definimos o  pino do LED_BUILTIN como saída.

 

-Função digitalWrite() e digitalRead()

digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));//Inverte o estado do LED de acordo com a leitura.

Aqui, estamos escrevendo um sinal lógico ao LED_BUILTIN. Neste caso, usamos a função digitalRead() que retorna o valor atual de um pino (1 para HIGH e 0 para LOW).

Usamos tambem um Inversor (NOT) "!" para inverter o estado de leitura, ou seja, caso o LED esteja ligado (1), invertemos para (0) e escrevemos isso à porta, assim, desligando-a.

 

-Função delay()

delay(250);

A função delay(), gera um atraso no código, fazendo com que o micro controlador trave naquela linha e fique até acabar o tempo. O tempo deve ser em mS, sendo que 1 Segundo = 1000mS.


 

De upload do codigo, e veja que o LED OnBoard (Azul) irá piscar a cada 250mS. Não se esqueça que para dar um novo upload, é necessário que o ESP8266 seja reiniciado com o GPIO0 em GND novamente.

 

Fechamento

Você aprendeu o que é este incrível microcontrolador e também como dar o primeiro upload à ele. Sinta-se à vontade para dar sugestões, críticas ou elogios. Lembre-se de deixar suas dúvidas nos comentários abaixo.

Você vai gostar de Conhecer o ESP32