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:
5 Comentários
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?
ResponderExcluirObrigado Fernando!
ResponderExcluirTinha pedido justamente isso em um dos seus vídeos passados em que comentou sobre o assunto!
Abs, Paulo.
Boa noite Fernando. Sou seu fã.
ResponderExcluirGostei 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?
Olá Fernando.
ResponderExcluirQueria saber se este circuito é aplicável a uma tensão de 220 Vca e 380 Vca? como ficariaos valores dos resistores de entrada do circuio com 220 Vca e 380 Vca?
No circuito mostra capacitores de 100nF, mas não mostra a tensão. Seriam de 100nF e de quantos Volts?
ResponderExcluir