banner

Ir para o Forum

Medindo tensão AC True-RMS



Hoje vamos usar o STM32 Maple Mini para fazer uma leitura de AC, ou seja, pegar o valor RMS da rede elétrica. Isso é bastante útil para aqueles que querem monitorar a rede elétrica para a Internet das Coisas. Vamos, então, criar uma aplicação aproveitando a poder computacional do Maple Mini, aplicar um circuito eletrônico capaz de permitir a aquisição de um sinal 127Vac, bem como aplicar o cálculo da raiz do valor quadrático médio (RMS) sobre as amostras.



Demonstração

Na nossa montagem de hoje, nós temos o STM32, além do nosso circuito analógico para fazer a entrada do 110. Para evitar choques, isolamos o resistor que está entrando por 110.
O circuito é bastante sensível. Estou entrando com 110, mas reduzo 168 vezes usando o divisor de tensão e jogo para dentro do amplificador operacional, o qual tem várias funções.
Temos ainda alguns capacitores opcionais para filtragem da fonte. Caso sua fonte seja de boa qualidade, não precisa utilizá-los.
A entrada do AD é calculada através do osciloscópio, no qual você vê uma senóide, que não é a 110, mas é bem formada. Outra coisa é que a tensão na nossa rede elétrica não é 110, mas 127 volts. Mas, como estamos passando por um estabilizador, ele ajustará para 115V.
O valor exibido no monitor serial é o calculado em RMS, ou seja, o identificado pelo multímetro Fluke.




Recursos usados

·         jumpers
·         Um Maple Mini
·         Protoboard
·         Um amplificador LM386
·         Uma fonte simétrica (+5V e -5V)
·         Um trimpot multivoltas 10k (ou potenciômetro)
·         Quatro capacitores de 100nF poliester
·         3 resistores 10k
·         4 resistores470k
·         1 resistor 5k6
·         1 Diodo zener 1n4728A




Diagrama de blocos





Esquema

Este é um circuito que desenvolvi baseado nas especificações que acredito serem mais interessantes para esta medida, mas há vários outros exemplos na internet.




LM386 – Pinagem

O LM386 possui dois amplificadores para condicionamento ou amplificação de sinal.




AmpOp – Diferencial (subtrator)



 AmpOp – Somador Inversor




Maple Mini – Pinagem

Pinos marcados em:
Vermelho >> Tolerantes a 3V3
Verde   >> Tolerantes a 5V




Maple Mini – Pinagem – A/D utilizado na captura

Destaco aqui que o pino que eu utilizei é o D11 que, na nomenclatura da STMicroelectronics é o PA0.




Montagem

Para o nosso circuito, você precisará de uma fonte simétrica, como a que criamos para este projeto, ou, então, de duas fontes.




Gráfico com os dados obtidos




Cálculo do valor rms




Código-fonte – Definições e constantes

De início, definimos o pino de leitura como D11 e as várias constantes utilizadas nos cálculos.

#define leituraTensao D11 //AD CH0 no pino PA0

//valor teórico divisor de tensão  = 168.85714285714285714286
const float fatorDivisor = 168.40166345742404792461;

//valor teórico do ganho de amplificação = 1.0
const float fatorAmplificador = 1.0;

//Valor usado na multiplicação da leitura
const float fatorMultiplicacao = fatorDivisor * fatorAmplificador;

//Valor teórico da Tensão de alimentação Vcc = 3.3V
const float Vcc = 3.3;

//valor teórico do offset do amplificador = Vcc / 2.0;
const float offSet = 1.66;

//fator teórico da conversão do AD = 3.3 / 4095.0
const float fatorAD = Vcc / 4095.0;

const int amostras = 71429; //resulta em 1,027 segundos para cada atualização
//const int amostras = 35715; //resulta em 0,514 segundos para cada atualização



Código-fonte – Variáveis globais

Agora, definimos algumas variáveis globais.

float Vrms = 0.0; //armazena o valor rms da tensão
float Vmax = 0.0; //armazena o valor máximo detectado
float Vmin = 10000.0; //armazena o valor mínimo detectado
float Vmed = 0.0; //armazena o valor médio entre Vmáx e Vmín



Código-fonte – Setup()

Inicio a porta serial em 1Mbps. Ajustamos a porta do AD como entrada e aguardamos 5 segundos antes de iniciar a coleta de dados. O tempo de espera é opcional.

void setup() {
  Serial.begin(1000000); //inicia a porta serial em 1Mbps
  pinMode(leituraTensao, INPUT); //ajusta a porta do AD como entrada
  delay(5000); //aguarda 5s antes de iniciar a coleta. (opcional)
}


Código-fonte – Loop() – Inicia as variáveis  de coleta de dados

No Loop, temos a variável para iteração. Ainda aqui, armazenamos as leituras do AD em 0.0 e reiniciamos a variável Vrms também em 0.0.

void loop() {
  int i = 0; //variável para iteração
  float leitura = 0.0; //armazena as leituras do AD
  Vrms = 0.0; //reinicia a variável Vrms



Código-fonte – Captura e executa os cálculos individuais de cada amostra

Nesta fase, se i for menor que a amostra, iniciamos um ciclo de amostragem até que o i alcance o número de amostras. Executamos analogRead para leitura da porta analógica e calculamos a soma dos quadrados das tensões lidas. Por fim, incrementamos o iterador.

while (i < amostras) { //inicia um ciclo de amostragem até que i alcance o número de amostras
    leitura = analogRead(leituraTensao); //lê a porta analógica
    //Serial.println(leitura); //Descomente se quiser ver o sinal bruto do AD
    Vrms = Vrms + pow(((leitura * fatorAD) - offSet), 2.0); //calcula a soma dos quadrados das tensões lidas
    i++; //incrementa o iterador
  }


Código-fonte – Cálculos gerais das amostras e identificação de máximo, mínimo e média

Aplicamos o fator de multiplicação para determina o valor real das tensões. Detectamos se o valor é máximo ou mínimo e calculamos a média dos valores máximo e mínimo atuais.

 //Aplicando fator de multiplicação para determinar o valor real das tensões
  Vrms = (sqrt(Vrms / amostras)) * fatorMultiplicacao;

  //detecta se é um valor é máximo
  if (Vrms > Vmax) {
    Vmax = Vrms;
  }
  //detecta se é um valor mínimo
  if (Vrms < Vmin) {
    Vmin = Vrms;
  }
  //calcula a média dos valores máximo e mínimo atuais
  Vmed = (Vmax + Vmin) / 2.0;
  


Código-fonte – Opções de saída

Temos três opções para “plottar” o valor de saída.  Temos a saída formatada para plotter serial IDE Arduino, como CSV ou como Jason.

 //saída formatada para plotter serial IDE Arduino
  Serial.print(Vrms, 3);
  Serial.print(",");
  Serial.print(Vmax, 3);
  Serial.print(",");
  Serial.print(Vmin, 3);
  Serial.print(",");
  Serial.println(Vmed, 3);

  /*
    //saída formatada como json
    Serial.print("{\"instante(ms)\":");
    Serial.print(millis());
    Serial.print(",");
    Serial.print("\"Vrms(V)\":");
    Serial.print(Vrms, 3);
    Serial.print(",");
    Serial.print("\"Vmax(V)\":");
    Serial.print(Vmax, 3);
    Serial.print(",");
    Serial.print("\"Vmin(V)\":");
    Serial.print(Vmin, 3);
    Serial.print(",");
    Serial.print("\"Vmed(V)\":");
    Serial.print(Vmed, 3);
    Serial.println("}");
  */

  /*
    //saída formatada como CSV
    Serial.print(millis());
    Serial.print(",");
    Serial.print(Vrms, 3);
    Serial.print(",");
    Serial.print(Vmax, 3);
    Serial.print(",");
    Serial.print(Vmin, 3);
    Serial.print(",");
    Serial.println(Vmed, 3);
  */
}



Faça o download dos arquivos:




3 comentários:

  1. Boa noite Fernando, desculpe está perguntando aqui, mas estou com uma dúvida com a placa protoneer cnc. Como eu faço para os motores ficarem alimentados, mantendo a cnc travada no lugar quando não estiver usinando, tem algum jump a ser colocado como na cnc shild do arduíno?

    ResponderExcluir
  2. Obrigado Fernando!

    Tinha pedido justamente isso em um dos seus vídeos passados em que comentou sobre o assunto!

    Abs, Paulo.

    ResponderExcluir
  3. Boa noite Fernando. Sou seu fã.
    Gostei muito desse circuito, se me permite, segue uma sugestão.
    Acho que daria para fazer um retificador de onda completa sem filtro (só os 4 diodos nos 127vca) com o objetivo de não precisar da fonte simétrica e nem ajustar o offset.
    Dessa forma, só teríamos tensão positiva e sem alterar o valor RMS em relação a senoide original, exceto pela ddp de 2 diodos (1,4v) que poderia ser compensado pelo software. O que você acha? Será que dá certo?

    ResponderExcluir

Tecnologia do Blogger.