Como usar sinais analógicos no NodeMCU com o LM358 16

Nos últimos anos vimos uma grande expansão no leque de opções relacionadas a placas de desenvolvimento e prototipagem. O ambiente maker que era dominado pelos Arduinos mais tradicionais (Placa Uno e Nano) passou a ser inundado por novas ferramentas. Dentre elas podemos citar os pequenos módulos ESP8266 e suas variações, como a famosa NodeMCU. Neste post, vamos mostrar como você pode usar sinais analógicos no NodeMCU ESP8266, mas é um princípio que pode ser usado nos outros módulos e placas da linha ESP8266, e até mesmo servir como base para outros projetos eletrônicos, já que uma das dúvidas comuns entre os makers é sobre como condicionar o sinal de sensores analógicos para adequá-lo às limitações destas novas plataformas.

Este artigo irá abordar algumas técnicas possíveis de serem utilizadas no condicionamento de sinais analógicos. Essas técnicas são adaptáveis a qualquer outra plataforma, mas neste artigo iremos focar nas características/limitações da popular NodeMCU e outros microcontroladores alimentados em 3,3V.

Principais materiais utilizados

Sinais analógicos no NodeMCU ESP8266

A placa NodeMCU se popularizou bastante após o surgimento dos módulos ESP8266, em especial por permitir a comunicação WiFi, conferindo mobilidade aos projetos. Como características relevantes podemos citar a circuitaria básica para seu funcionamento, além da quantidade de pinos, principalmente quando comparada com um módulo mais simples como a ESP8266 ESP-01.

Apesar do módulo ESP8266 estar no mercado a um bom tempo, o mesmo ainda carece de certas informações técnicas (seu datasheet é por demais resumido). Em especial com relação ao seu ADC faltam informações úteis aos projetos, mas sabemos que sua resolução é de 10bit, com tensão máxima de 1V. Ou seja, utilizar a entrada analógica pode ser um pequeno desafio.

Para facilitar as coisas a NodeMCU já conta com um atenuador de sinais através de um divisor resistivo, que condiciona tensões entre 0 e 3,3V ao nível do ADC de 0 a 1,0V. Segundo o esquemático da mesma, os resistores tem valor 220kΩ e 100kΩ respectivamente, conforme pode ser visto a seguir. O esquemático da placa pode ser encontrado neste link.

Sinais analogicos no NodeMCU ESP8266

Mesmo o limite de 3,3V da NodeMCU costuma dificultar um pouco as coisas na hora de interfacear os sensores analógicos mais tradicionais, preparados para trabalhar com 5V e com saídas analógica também de 0 a 5V. Como exemplo podemos citar desde uma simples medição de tensão de uma bateria ou fonte, até sensores como o ACS712 para medição da corrente consumida por algum dispositivo.

Métodos para condicionar os sinais

Existem diversos métodos de se condicionar sinais analógicos mantendo sua integridade e características. Partirei do mais básico visto que podemos ir incrementando o método de acordo com as necessidades e possibilidades.

Caberá a você escolher qual das técnicas se encaixa melhor, levando em consideração complexidade, custo e desempenho.

O divisor resistivo

O primeiro método, e base para os próximos, é um simples divisor resistivo. Um divisor resistivo é formado pela associação de pelo menos dois resistores em série, onde de acordo com a relação entre suas resistências é possível se obter um sinal de saída menor e proporcional ao sinal analógico original.

Divisor de tensãoComo principal característica deste método podemos citar seu custo, afinal, você precisa de basicamente 2 resistores, podendo utilizar também um resistor variável para ajudar manualmente o divisor. Outra característica importante é que este método de condicionamento de sinais tende a não interferir nas características do sinal analógico, não adicionando ruído e não distorcendo a forma da onda (caso for um sinal AC).

A partir dos valores de R1, R2 e Vin podemos calcular qual a tensão na saída, conforme mostra a fórmula a seguir. Além disso, definindo um valor para Vin, Vout e para um dos dois resistores é possível se obter o valor do outro.

Fórmula divisor de tensãoComo ferramenta útil para facilitar seu desenvolvimento, indico a utilização da calculadora disponível neste link. Ela permite verificar o valor de Vout em função dos resistores ou mesmo calcular os resistores a partir das tensões de entrada, saída e da definição de um dos resistores.

Uma dica prática, evite que a soma dos resistores tenha valor inferior a 10kΩ, visto que isto elevaria o consumo e dissipação térmica. Um ponto bastante importante em dispositivos móveis ou alimentados por baterias.

Apesar das características positivas citadas anteriormente, este método possui suas limitações, em especial com relação a impedância de saída do sensor e de entrada do ADC.

Imagine a seguinte situação, você precisa atenuar o sinal de um Sensor X que possui elevada impedância de saída. Para conseguir captar totalmente seu sinal será necessário que o divisor resistivo tenha um valor muito maior que o da impedância do sensor. Neste ponto podemos pensar “ok, podemos resolver isso utilizando R1 e R2 com valores bastante elevados…”, correto!? Mais ou menos… Isso amenizará o efeito de carga sobre o sensor, mas poderá criar um problema para a entrada do conversor ADC, visto que nem sempre sua impedância será elevada o suficiente a ponto de compensar a etapa anterior.

Imagine um sensor com tensão máxima de 5V e com resistência de saída de 1kΩ. Precisamos adequar o sinal para os 3,3V da NodeMCU. Para isso utilizaremos o circuito a seguir com R1 e R2 valendo 220kΩ e 390kΩ, respectivamente. Antes de conectar a entrada analógica a tensão estará nos níveis esperados, mas ao conectarmos a tensão cairá devido a interação entre os circuitos e ao efeito de carga do segundo divisor de tensão. Você pode testar uma simulação aqui.

Efeito de cargaPara corrigir essa deficiência iremos adicionar um componente ativo bastante versátil e importante no mundo analógico, o Amplificador Operacional, ou AmpOp como irei chamar.

Atenuador de sinal ativo com AmpOp

Como nosso objetivo é a parte mais prática da coisa, deixarei de lado a história dos AmpOp’s bem como a dedução das fórmulas relacionadas às configurações mais tradicionais. Caso tiver interesse de se aprofundar um pouco mais, indico a leitura desta série que escrevi para o portal Embarcados.

Como principais características para nossa solução devo citar a elevada impedância de entrada do AmpOp, em alguns casos chegando a casa dos Tera Ohms (isso mesmo, você não leu errado), e também sua baixa impedância de saída. Desta maneira mostra-se como um elemento perfeito para o casamento de impedâncias entre duas etapas de um circuito.

Para esta aplicação, uma das configurações mais tradicionais é a de Buffer. Nesta configuração o amplificador terá ganho unitário, servido apenas para casar as impedâncias e “isolar” os circuitos. O esquema de um buffer pode ser visto a seguir.

Buffer amplificador operacional

Uma das limitações dos AmpOps é que nem todos os modelos funcionam bem sem alimentação simétrica (positiva e negativa). Ao mesmo tempo essa é uma limitação da maioria dos projetos envolvendo microcontroladores em geral já que utilizamos apenas alimentações positiva (5V, 3,3V). Neste ponto já descarto o uso do tradicional modelo 741, que apesar de ser um clássico vendido até hoje, não se comporta bem com fonte simples.

Indico o AmpOp LM358, um modelo bastante interessante e que funciona bem com alimentação simples, mesmo em baixas tensões. Vale lembrar que a tensão de saída no LM358 será entre 1,3V e 1,5V menor que o limite máximo de alimentação devido a suas limitações construtivas, e este valor pode variar de acordo com a corrente da carga.

Amplificador Operacional LM358Lembra-se do efeito de carga causado pela impedância do divisor nativo da NodeMCU? Iremos anular este efeito utilizando um buffer entre a saída do divisor resistivo e a entrada analógica da placa.

Circuito AmpOpVeja a diferença, sem o buffer o sinal na entrada do ADC é atenuado INDEVIDAMENTE (efeito de carga). Com a introdução do buffer a entrada analógica passará a receber toda a tensão disponível na saída do divisor resistivo externo. Você pode testar uma simulação aqui.

Adicionando proteções

O circuito anterior é totalmente funcional, mas dependendo das circunstância pode ser interessante proteger as entradas do AmpOp e também sua saída (entrada analógica da placa).

Uma maneira bastante eficiente e comum de realizar esta proteção é utilizar diodos formando um limitador de tensão que irá seifar o excesso de tensão após a polarização do diodo.

Um circuito completo é apresentado a seguir:

circuito_compLembre-se que a tensão sobre dois elementos em paralelo é a mesma. o diodo D1 terá como função limitar tensões que excedam “VDD + Vd”. De maneira análoga o diodo D2 evitará que tensões reversas danifiquem a entrada do AmpOp, limitando seu valor a “-Vd”. O Diodo D3 protege ao mesmo tempo a saída do AmpOp, além de evitar que a tensão na entrada analógica ultrapasse a tensão de “VDD + Vd”. Para o circuito apresentado, mesmo um problema no AmpOp que elevasse sua saída a 5V, resultaria em 3,97V na entrada analógica e 1,24V na entrada do ADC. Um valor que não irá prejudicar a mesma, em especial pela limitação de corrente causada pelos resistores R9 e R11.

Neste link é possível simular o comportamento do circuito proposto (facilitando modificações para outras plataformas).

Tanto a proteção da entrada como saída são opcionais, mas indico utilizar pelo menos os diodos na entrada e evitar que algum distúrbio externo danifique o AmpOp.

Exemplo – Monitorando a tensão no conector USB

Imagine que você necessita monitorar a tensão fornecida através do conector USB que alimenta sua NodeMCU, a mesma tensão presente no pino VU (Entre o pino G e o pino S3).

Iremos modificar um pouco o projeto. Iremos aumentar a tensão de entrada para 5,1V dando um pouco mais de margem dinâmica. Com isso iremos recalcular os resistores. Como o valor de 390kΩ é menos usual, iremos utilizar o valor 470kΩ para R2 e através da calculadora online obtemos R1 como 256kΩ, um valor não comum. Iremos substituí-lo por dois resistores com 47kΩ e 220kΩ em série, resultando em um resistor equivalente de 267kΩ, valor próximo do calculado. O restante do circuito será o mesmo, conforme pode ser visto a seguir.

circuito_comp_nodemcu

O circuito montado no protoboard virtual do Fritzing para leitura de sinais analógicos no NodeMCU pode ser visto a seguir e o arquivo pode ser baixado no meu github.

Circuito Sinais Analógicos no NodeMCUIrei utilizar a IDE Arduino para uma programação rápida, verificando o valor convertido através da comunicação serial. Você pode incrementar mais o projeto de acordo com sua necessidade, criando por exemplo uma página que possa ser acessada via Wifi pelo browser.

A seguir é apresentado o código para leitura de sinais analógicos no NodeMCU desenvolvido dentro da IDE Arduino. O resultado da conversão será apresentado via terminal serial. Note que os valores de R1 e R2 que adotei não são os valores teóricos, mas sim os que medi com um multímetro. Mas porque fazer isso!? Para minimizar erros na medição. Devido a tolerância dos resistores, talvez ocorra algum desvio. Mas caso você não tiver um multímetro em mãos, sem problemas, utilize os valores teóricos mesmo.

/* Programa: Sinais analogicos no NodeMCU ESP8266
 * Conditioning analog signal to NodeMCU
 * - Conditioning an analog signal bigger than 3.3v
 * using an active circuit with OpAmp LM358
 * the article about this code is available in:
 * https://www.makerhero.com/author/haroldo-amaral/
 * -------------------------------------------------
 * condicionando sinal analógico para NodeMCU
 * - condicionando um sinal analógico maior que 3.3v
 * utilizando um circuito ativo com o AmpOp LM358
 * o artigo sobre este código esta disponível em:
 * https://www.makerhero.com/author/haroldo-amaral/
 * 
 * developed by: Haroldo Amaral - agaelema@gmail.com
 * 2017/05/24 - v 1.0
 */
 
// some constants - algumas constantes
const unsigned int analogInPin = A0;    // Analog input - pino analógico
const float analogLimit = 3.3;          // Limit of Analog In. - Limite da entrada analogica
const float R1 = 46700 + 217000;        // Valores medidos - teóricos de 47k + 220k
const float R2 = 450000;                // valor medido - teórico de 470k
 
// used variables - variáveis utilizadas
unsigned int RAWanalogInput = 0;        // save the RAW value of A0 - armazena o valor RAW de A0
float analogInputVoltage = 0;           // save the converted A0 voltage - armazena a tensão convertida de A0
float Vusb = 0;                         // save the Vusb voltage - armazena a tensão Vusb
 
void setup()
{
  // setup the serial communication - configura a comunicacao serial
  Serial.begin(115200);
}
 
void loop()
{
  // read the analog input - le a entrada analogica
  RAWanalogInput = analogRead(analogInPin);
 
  // print RAW value - imprime o valor RAW
  Serial.print("RAW value: "); Serial.println(RAWanalogInput);
 
  // convert RAW value in voltage - converte o valor RAW em tensao
  analogInputVoltage = (float)RAWanalogInput * (analogLimit/1024);
  // print A0 voltage - imprime a tensao em A0
  Serial.print("ADC voltage: "); Serial.println(analogInputVoltage);
 
  // calculate the Vusb voltage - calcula a tensao Vusb
  Vusb = analogInputVoltage * (R1 + R2) / R2;
  // print Vusb voltage - imprime a tensao Vusb
  Serial.print("Vusb voltage: "); Serial.println(Vusb);
  
  delay(500);
}

A imagem a seguir apresenta o valor no terminal dos sinais analógicos no NodeMCU junto com a medição realizada pelo multímetro. Veja que os resultados são bastante próximos e coerentes.Comparação de leituraOs arquivos deste projeto (sketches e esquemático do Fritzing) podem ser baixados no meu repositório GitHub.

Gostou do artigo Como Usar Sinais Analógicos no NodeMCU ESP8266? Deixe seu comentário logo abaixo. 

Faça seu comentário

Acesse sua conta e participe

16 Comentários

  1. Não seria melhor, simplesmente, adicionar um resistor de 180k na entrada do adc? Daria 1v na leitura.

  2. Me corrija se estiver errado, mas acredito que haja um problema nessa montagem final. Se o sensor possuir uma variação de 0 à 5V e deseja-se traduzir essa variação em uma de 0 à 3.3V, ocorerá problemas no limite inferior desse intervalo, pois o CI LM358 não é um amplificador operacional Rail to Rail, logo se for alimentado com uma tensão de 0V (GND) no terminal de alimentação negativo, o mesmo não conseguirá fornecer uma tensão de 0V na saída do circuito pois ele irá saturar antes disso. O correto então seria a alimentação com uma tensão negativa no terminal de alimentação negativo.

  3. Olá, poderia me dizer como posso fazer para deslocar um sinal para cima, por exemplo, um sensor emite ondas que variam entre 0 volts, queria saber como deixar este sinal apenas no ciclo positivo, seria com um capacitor ou algo assim?

    1. A ideia é adicionar um nível DC ao sinal original, eliminando a tensão negativa do sinal original.

      Se for um sinal AC é menos complicado, você pode ter algumas ideias lendo este artigo meu no Embarcados (https://www.embarcados.com.br/amp-op-fonte-de-alimentacao-simples/).

      Para sinal DC é um pouco mais complicado fazer o acoplamento. Uma possibilidade é usar um divisor resistivo para criar o nível DC, mas você não pode conectar o sinal direto no ponto central do divisor, você precisar colocar um resistor adicional entre a fonte de sinal e o ponto central do divisor. O problema dessa abordagem é que isso afeta o divisor de tensão original além de formar um divisor de tensão indireto no sinal (será atenuado). Você pode compensar isso com ganho, mas o ganho também será aplicado ao nível DC, ou seja, é um bom desafio escolher valores interessantes ao projeto.

      Boa sorte :p

    2. Adrian,

      Você teria que usar uma ponte retificadora para deixar o sinal apenas no positivo, e então um capacitor para diminuir o ripple. Dê uma olhada no que é uma ponte retificadora: https://www.mundodaeletrica.com.br/diodo-retificador-o-que-e-pra-que-serve/

      Abraços!
      Diogo – Equipe MakerHero

  4. show de bola haroldo, muito bom o post..

  5. é possível ler um sinal de um sensor industrial de 4-20ma com esp32?

    1. Olá,

      Acredito que para medir corrente a abordagem teria que ser diferente.

      Abraço!
      Rosana – Equipe MakerHero

  6. Então para poder utilizar o segundo método, irei utilizar apenas um divisor de tensão e um buffer de tensão, irei utilizar um resistor de 220k e um de 390 e em seguida o buffer correto? A entrada analógica ficará na saída do AmpOp correto?

  7. Cara muito bom seu post!!!

  8. Boa noite,

    como ficaria caso eu quisesse usar as duas entras a A e B?
    Posso?

    Pelo esquema me parece que elas são independente, mas tentei ligar e não consegui fazer a leitura de duas ao mesmo tempo.

    Note que estou usando o ESP32, pois o ESP8266 não tem portas analógicas suficiente.

    Desde já obrigada.
    Att,

    1. Boa noite.

      Sim, o LM358 é um dual Opamp, ou seja, possui dois OpAmps independentes, eles compartilham apenas a alimentação.

      Para utiliza-los você deve reproduzir o mesmo circuito no segundo OpAmp (B), ou montar o circuito desejado.

      Att,

  9. Muito bom principalmente para quem não é especialista em eletrônica

    1. Que bom que gostou e achou útil

  10. Excelente artigo.
    Já que estamos partindo do básico, qual seria o problema se fizermos uso das propriedades dos diodos, e ligarmos 6 em serie para chegarmos em algo em torno de 0.8v para um aplicação simples como detectar o sinal de saída alto ou baixo de um sensor 5v qualquer?

    1. Não sei se consegui entender sua ideia de utilização do diodo. Você fala em colocar os 6 em série com um sinal de um sensor com saída de 0 a 5v? O problema é que com menos que 4,2V idealmente os diodos não conduziriam nada e a partir de 4,2V você teria uma variação útil de apenas 0,8V.

      Se a ideia é apenas indicar existência de tensão é melhor utilizar um comparador com OpAmp ou mesmo um comparador dedicado.