Início
/
Projetos Arduino
/
Projetos Squids
/
Básico
/
Projeto106 - Suavizando as leituras de um sensor luz com Arduino - Filtro de Média Móvel
Projeto106 - Suavizando as leituras de um sensor luz com Arduino - Filtro de Média Móvel
Angelo Luis Ferreira | 24/10/2022
Acessos: 3.127
Básico - Projeto 106
Usando a média móvel para suavizar as leituras do sensor BH1750
Objetivo
O objetivo deste projeto é mostrar como podemos utilizar um filtro digital para estabilizar as leituras de intensidade luminosa que incide sobre um sensor de luz BH1750. Para a leitura da iluminação, utilizaremos o módulo GY-302 ou o módulo GY-30 (ambos possuem o sensor de luz BH1750FVI e geram o mesmo resultado). Utilizaremos também a biblioteca BH1750 para facilitar a determinação dos valores resultantes e como filtro digital, usaremos o método Filtro de Média Móvel.
Definições
Obs.: Geralmente os módulos GY-30 e GY-302 não são fornecidos com os pinos soldados.
Módulos GY-30 e o GY-302:
1. Como possuem o sensor de luminosidade BH1750FVI (datasheet) como base, estes módulos são capazes de determinar o nível de iluminação (iluminância) que incide sobre o sensor, medido em lux (lx). Portanto, os módulos GY-30 e GY-302 são utilizados para medir a quantidade de luz dentro do ambiente onde está localizado o sensor.
2. O circuito integrado BH1750FVI é capaz de medir a intensidade da luz em lux na faixa de 1 a 65535 lx, sendo ideal para aplicação em sistemas de controle de iluminação automática.
3. Os módulos possuem interface I2C de comunicação, facilitando a montagem e a conexão com o Arduino.
4. Os módulos possuem conversor AD de 16 bits (para transformar sinal analógico em sinal digital) e funcionam com tensões entre 3 e 5Vcc (corrente contínua) .
5. módulos GY-30 e GY-302 são similares e retornam valores de iluminância com a mesma precisão. Se diferem apenas pelas suas dimensões e disposição dos seus pinos de conexão.
Conceitos importantes
Filtro Digital: O filtro digital é um filtro que processa sinais digitais usando um processador ou microcontrolador para executar cálculos necessários para fazer a filtragem, multiplicando os valores da entrada por constantes e somando os produtos resultantes, além de utilizar técnicas matemáticas, como Transformadas de Fourier e Hilbert em valores amostrados do sinal de entrada. O processador pode ser um computador ou um DSP. Em um processo de filtragem digital, o sinal analógico deve ser primeiramente digitalizado usando um ADC (Conversor analógico-digital). Filtros digitais são um elemento essencial para os atuais equipamentos eletrônicos, como rádios, celulares e dispositivos multimídia em geral. Filtro Digital - Wikipédia
Porque usar um filtro digital?
É muito comum em eletrônica a presença de ruído em um sinal digital, principalmente quando se trabalha com sinais provenientes de um Conversor Analógico-Digital (ADC).
O ruído é um sinal aleatório parasita que gera alterações nas leituras de sensores, principalmente quando ocorre a conversão de um sinal analógico para um sinal digital. Em sistemas eletrônicos, como projetos que utilizam o Arduino, por exemplo, esses ruídos podem ser causados por uma fonte de alimentação, capacitância parasita ou por indução magnética nos fios, entre outros.
Portanto, ao fazermos leituras de sensores com Arduino, precisamos muitas vezes realizar uma filtragem para eliminar ou reduzir algum ruído indesejável no sistema. Essa filtragem na pratica é geralmente realizada por intermédio da programação com o uso de filtros digitais. O problema é que a teoria sobre filtros digitais é muito complexa, e faz com o programador a evite. Entretanto, pode-se utilizar um filtro digital bem simples chamado de média móvel, que pode resolver de forma bastante razoável o problema do ruído em leituras de sensores na maioria dos casos.
Neste tutorial, portanto, vamos mostrar como podemos utilizar o método Filtro de Média Móvel na programação para realizarmos leituras de um sensor de luz BH1750.
Filtro de Média Móvel: O filtro de média móvel utilizado é obtido calculando-se a média de um conjunto de valores, sempre se adicionando um novo valor ao conjunto e se descartando o mais velho. Não é apenas uma média de um conjunto isolado de valores.
O Filtro de Média Móvel (MM) é portanto, um filtro finito (FIR), onde resulta em uma resposta finita em relação a um impulso, descartando o valor mais antigo. É um tipo de filtro fácil de ser implementado, rápido e que gera resultados razoavelmente estáveis.
O ponto negativo em utilizar sensores tipo FIR é o consumo de memória RAM do microcontrolador e algum atraso no sinal de resposta calculada pelo filtro digital em relação ao sinal lido diretamente no sensor. Portanto, essas considerações deverão ser avaliadas em uma aplicação com sensores. O atraso em relação aos valores é bem aparente quando há uma mudança brusca no sinal recebido pelo sensor. Veja o exemplo a seguir:
Como o nosso objetivo neste tutorial é uma abordagem prática, não aprofundaremos na teoria sobre filtros digitais e portanto, apresentamos abaixo um código prático de filtro de média móvel para ser utilizado neste projeto ou em qualquer outro projeto com sensores:
// FUNÇÃO FILTRO - MÉTODO MÉDIA MÓVEL (MM)
float mediaMovel(float xis) {
static float media = 0.0;
static int indice = 1;
if (indice == 0 || indice == 33) {
indice = 1;
media = 0.0;
}
media = media + (xis - media) / indice++;
return media;
}
void setup() {
}
void loop() {
float sample = 5.0 * analogRead(0) * 100.0 / 1024.0;
Serial.print(mediaMovel(sample));
}
Observações:
a) Variáveis declaradas como static são criadas e inicializadas apenas a primeira vez que uma função é chamada.
b) A variável índice determina na quantidade de valores (amostras) que se realiza a média. Lembrando-se que sempre será descartado o valor mais antigo a cada nova leitura do sensor.
c) O valor da variável sample é um exemplo de leitura de uma entrada analógica na porta A0 do Arduino, que pode ser um sensor ou um potenciômetro, por exemplo.
d) Quanto maior o número de amostras, ou seja, quanto maior o valor da variável índice, mais suave será a curva. Entretanto, maior será o consumo de memória RAM do microcontrolador e maior será o atraso entre os sinais lido e os sinal calculado pelo filtro.
d) No cálculo de média móvel, utilizamos a função abaixo, onde M é o índice utilizado:
Referências
Projeto103 - Como usar o sensor BH1750 com Arduino sem auxílio de biblioteca específica
Projeto104 - Como medir a iluminação ambiente com o sensor BH1750 e Arduino
Projeto 48 - Como controlar um display LCD com o módulo I2C
Projeto 38 - Controlando um display LCD (instalação e comandos básicos) (Caso não possua um módulo I2C e queria adaptar o projeto para usar o display LCD)
Aplicação
Para fins didáticos e em sistemas de controle de iluminação automático ou apenas circuitos para medição da luz ambiente nos mais diversos tipos de projetos robóticos ou de automação residencial. É muito utilizado em sistemas que detectam a luminosidade para um ajuste de eficaz da iluminação, por exemplo.
Componentes necessários
Referência
|
Componente
|
Quantidade
|
Imagem
|
Observação
|
Protoboard |
Protoboard 830 pontos |
1 |
|
No mínimo utilizar protoboard com 830 pontos
|
Jumpers |
Kit cabos ligação macho / macho |
1 |
|
|
Módulo Sensor de Luminisidade |
Módulo Sensor de Luz GY-30 ou GY-0302
|
1 |
|
Especificações:
Módulo sensor de luminosidade GY-302 ou GY-30
CI BH1750FVI (datasheet)
Tensão de operação 3 a 5V DC Faixa de medição 1 à 65.535 Lux Interface I2C Conversor AD 16 bits Dimensões 18,5 x 13,9mm
|
Display LCD
|
Display LCD 16X2 (com pinos soldados) |
1 |
|
LCD que utilize o controlador HD44780 (veja na descrição ou datasheet do componente)
O display poderá ser de qualquer cor (fundo verde, azul ou vermelho)
|
Módulo I2C para display LCD
|
Módulo I2C com CI PCF8574 |
1 |
|
O módulo I2C poderá vir separado ou já soldado no display LCD
(datasheet)
Se você não possui um módulo I2C para display LCD, poderá adaptar o projeto para o display LCD sem o adaptador.
|
Arduino UNO R3 |
Arduino UNO |
1 |
|
Você poderá utilizar uma placa Arduino UNO original ou similar
|
Montagem do Circuito
Conecte os componentes no Protoboard como mostra a figura abaixo. Verifique cuidadosamente os cabos de ligação antes de ligar seu Arduino. Lembre-se que o Arduino deve estar totalmente desconectado da força enquanto você monta o circuito.
Observação: O módulo BH1750 poderá ser conectado no Arduino nas fontes de energia 3.3V ou 5V (Vcc), pois de acordo com o seu datasheet, o módulo funciona perfeitamente em ambas tensões. É importante lembrar também que o display LCD opera somente na tensão de 5V.
Atenção
1. Veja na imagem abaixo a "pinagem" do módulo GY-302 (à esquerda) e o módulo GY-30, que funcionam com a interface I2C.
2. Observe nas imagens que os módulos GY-302 e Gy-30 possuem os pinos de alimentação Vcc e GND e os pinos de interface I2C: SCL (Clock), SDA (Data) e ADDR (Address).
2.1. Pino Vcc: Deve ser conectado com o pino 3,3V ou 5V do Arduino. O sensor possui tensão de operação de 3 a 5Vcc.
2.2. Pino GND: Deve ser conectado no GND do Arduino.
2.3. Para a interface I2C, vamos usar os pinos SCL, SDA. Faça a conexão dos pinos SCL e SDA com o Arduino da seguinte forma:
Obs.: No nosso exemplo usamos o Arduino Uno.
Arduino Uno |
A5 |
A4 |
Arduino Nano |
A5 |
A4 |
Arduino Mega |
21 |
20 |
Leonardo/Micro |
3 |
2 |
2.4. O pino ADDR pode ser usado, por exemplo, para ligar dois sensores no mesmo microcontrolador ou quando o módulo é utilizado sem uma biblioteca específica. Quando usamos o pino ADDR em nível alto, o endereço de conexão I2C opera no endereço 0x5C, e com o pino em nível baixo, 0x23. Leia o Projeto103 - Como usar o sensor BH1750 com Arduino sem auxílio de biblioteca específica
Obs.: Quando adicionamos uma biblioteca pronta para calcular o resultado obtido pelo leitura de um único sensor BH1750, a utilização do pino ADDR pode ser opcional. Portanto, vamos optar por não utilizar o pino ADDR nesse projeto, entretanto, se o pino ADDR estiver conectado no Vcc ou no GND do Arduino, o resultado será o mesmo.
3. No projeto, podemos utilizar também um display LCD 16x2 com controlador HD44780, que se adapta aos mais diversos projetos com vários modelos de placas e microcontroladores. Este display possui 16 colunas por 2 linhas com backlight (luz de fundo) verde, azul ou vermelha e tem 16 pinos para a conexão.
3.1. A utilização do display LCD é opcional neste projeto, pois o objetivo principal dele é a exibição dos valores lidos no sensor e os valores calculados pelo filtro digital no Plotter Serial do Arduino.
4. Para a montagem do display com adaptador, entenda a estrutura do módulo I2C para display LCD 16x2 / 20X4:
4.1. Na lateral do adaptador encontramos 4 pinos, sendo: 2 pinos para alimentação (Vcc e GND) e 2 pinos para conexão com a interface I2C (SDA e SCL) que deverão estar conectados nos pinos analógicos A4 (SDA) e A5 (SCL) do Arduino Uno ou nos pinos A20 (SDA) e A21 (SCL) do Arduino Mega 2560. Veja a tabela abaixo com onde temos as principais placas Arduino e suas conexões com o I2C.
4.2. Para controlar o contraste do display, utilize o potenciômetro de ajuste de contraste. O jumper lateral, quando utilizado, permite que a luz do fundo (backlight) seja controlada pelo programa ou permaneça apagada.
4.3. A seleção de endereço do adaptador I2C para display LCD, na maioria dos módulos fornecidos no mercado já vêm configurados com o com o endereço 0x27. Se você não sabe qual endereço que o seu módulo I2C e/ou módulo RTC DS3231 está configurado, baixe o seguinte "sketch":
DOWNLOAD - I2C_scanner.ino
2.3.1 Após instalar e rodar o sketch acima, abra o monitor serial que mostrará qual é o endereço que o seu módulo I2C está configurado:
4.3.2 Nos casos em que módulo I2C estiver configurado com uma faixa de endereços diferente do endereço 0X27 altere a alinha de programação -> LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7,3, POSITIVE); com o endereço correto.
4.4. Para saber mais sobre a montagem e utilização de display LCD com módulo I2C leia: Projeto 48 - Como controlar um display LCD com o módulo I2C.
5. A montagem do nosso exemplo foi realizada em um protoboard com 400 pontos e com um display LCD com comunicação via protocolo I2C. Verifique sempre se o seu protoboard possui linhas de alimentação contínuas ou separadas.
Incluindo a biblioteca BH1750
Para utilizarmos o módulo BH1750 incluiremos a biblioteca BH1750, que obtém a leitura da intensidade luminosa do ambiente de forma facilitada, sem precisamos conhecer mais profundamente alguns detalhes do sensor.
Instalação da biblioteca
1. No IDE do Arduino, acesse a aba Sketch, selecione [Incluir Biblioteca] e depois [Gerenciar Bibliotecas...].
2. No campo de pesquisa digite BH1750. Localizada a biblioteca BH1750 (by Christopher Laws) clique no botão [Instalar].
Para saber detalhes desta biblioteca clique aqui.
3. Após a instalação, observe que aparecerá a informação que a biblioteca foi instalada.
Incluindo a biblioteca LiquidCrystal_I2C
Atenção: Caso você opte pela utilização do display de LCD sem o módulo I2C, siga os procedimentos do Projeto 38 - Controlando um display LCD (instalação e comandos básicos) e não instale a biblioteca abaixo.
1. Para que o módulo I2C funcione corretamente é necessário adicionarmos a biblioteca LiquidCrystal_I2C no IDE do Arduino. Uma das grandes vantagens das placas Arduino é a diversidade de bibliotecas disponíveis que podem ser utilizadas em seus programas. Estas bibliotecas podem ser criadas para a linguagem "C" ou especificamente para o Arduino, reduzindo drasticamente o tempo gasto com programação. Veja a tabela Coletânea de bibliotecas para módulos.
Download dos arquivos da biblioteca LiquidCrystal_I2C
DOWNLOAD - NewliquidCrystal_1.3.4.zip
Para saber detalhes desta biblioteca clique aqui.
2. Após fazer o download do arquivo NewliquidCrystal_1.3.4.zip com todos os arquivos da biblioteca compactados no formato zip, abra o IDE do Arduino e siga o tutorial: Como incluir uma biblioteca no IDE do Arduino.
Biblioteca Wire
1. Para realizar a comunicação via protocolo I2C (comunicação com 2 fios: clock (SCL) e dado (SDA) podemos utilizar a biblioteca Wire.h que já vem instalada por padrão no IDE do Arduino.
2. A biblioteca Wire.h é responsável por conter as funções necessárias para gerenciar a comunicação entre os dispositivos através do protocolo I2C.
3. Muitas bibliotecas específicas para módulos e sensores com comunicação I2C já tem incluído a biblioteca Wire no seu escopo. Entretanto, é recomendável utilizar sempre essa biblioteca quando utilizarmos a comunicação via protocolo I2C, afim de evitarmos possíveis erros de comunicação.
Código do Projeto (Sketch)
1. Faça o download e abra o arquivo projeto106.ino no IDE do Arduino: DOWNLOAD - projeto106.ino
Obs. 1: Nos casos em que módulo I2C estiver configurado com um endereço diferente do endereço 0X27, altere a alinha de programação -> LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7,3, POSITIVE); com o endereço correto. - Veja o tutorial Projeto 48 - Como controlar um display LCD com o módulo I2C
Obs. 2: Se estiver utilizando um display de LCD 20 X 4, altere o comando de inicialização para lcd.begin (20,4);
Obs.3: Se não possuir o módulo I2C utilize apenas o display LCD conforme Projeto 38 - Controlando um display LCD (instalação e comandos básicos) .
2. Se preferir, copie e cole o código abaixo no IDE do Arduino:
/*******************************************************************************
*
* 106 - Métodos de filtros digitais - Média móvel
* Autor: Angelo Luis Ferreira
* 20/11/2022
* http://squids.com.br/arduino
*
*******************************************************************************/
#include <Wire.h> // biblioteca para comunicação I2C
#include <BH1750.h> // biblioteca para sensor BH1750
#include <LiquidCrystal_I2C.h> // biblioteca para o display LCD I2C
// variáveis globais
float lux; // variável para a leitura real do sensor
unsigned long anterior = 0; // variável para o temporizador
// criar instâncias (bibliotecas)
BH1750 sensor; // cria a instancia sensor
LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7,3, POSITIVE); // cria a instância lcd
void setup() {
// inicializações
Serial.begin(9600); // inicializa a comunicação serial
sensor.begin(); // incializa o sensor BH1750
lcd.begin(16,2); // inicializa o lcd 16X2 com I2C
}
void loop() {
// le os valores do sensor de lux
lux = sensor.readLightLevel(); // faz a leitura direta do sensor analógico para digital
float luxFiltered = filterMediaMovel(lux); // filtra valor lido pelo método filtro média móvel (função)
showLux(luxFiltered); // exibe valor filtrado no lcd (função)
showReadsFilters(luxFiltered); // exibe valores no plotter serial (função)
delay(100); // delay 100ms
}
void showLux(float luxMedia) {
// verifica o tempo atual (temporizador)
unsigned long atual = millis();
// mostra as informacoes no LCD a cada 200ms
if(atual - anterior > 200) {
lcd.setCursor(0, 0);
lcd.print(" Ilum. Ambiente");
lcd.setCursor(0, 1);
lcd.print("Lumin.: lux");
lcd.setCursor(8, 1);
lcd.print(luxMedia,1); //imprime valor filtrado no lcd com uma casa decimal
anterior = atual; // atualiza temporizador
}
}
void showReadsFilters(float luxMedia) {
// Mostra o valor real
Serial.print(lux,1); // imprime valor real com uma casa decimal
Serial.print(" ");
// Mostra valor filtro média móvel
Serial.print(luxMedia,1); // imprime valor médio (filrado) com uma casa decimal - média móvel
Serial.println(" ");
}
// FUNÇÃO FILTRO - MÉTODO MÉDIA MÓVEL
float filterMediaMovel(float xis) {
static float media = 0.0;
static int indice = 1;
if (indice == 0 || indice == 100) {
indice = 1;
media = 0.0;
}
media = media + (xis - media) / indice++;
return media;
}
Vídeo
Como o projeto deve funcionar
1. Ao rodar o programa, caso tenha incluído o display no projeto, poderá visualizar no display LCD a quantidade de luz (iluminância) medida em um ponto ambiente, no caso no local onde se encontra o sensor BH750.
1.2. Caso não tenha utilizado o display, você poderá visualizar os valores abrindo o Monitor Serial do Arduino.
2. Para analisarmos e compararmos as leituras diretas do sensor com o valor calculado pelo método de médias móveis, abra o Plotter Serial.
Atenção: Para poder abrir o Plotter Serial é necessário e obrigatório que o Monitor Serial esteja fechado.
3. Agora podemos visualizar e comparar as curvas de leitura direta pelo sensor e calculada. Na imagem abaixo, temos a curva em azul com os valores lidos no sensor e convertidos digitalmente pelo Arduino e a curva em vermelho com os valores calculados através do método de Média Móvel (MM).
3.1 Dica : para visualizar os valores lidos no Plotter Digital, utilize o comando Serial.print(" "); ou Serial.println(" "); no final de cada valor que se deseja visualizar no gráfico.
4. Se você incluiu o display LCD no projeto, poderá visualizar o valor da intensidade luminosa "filtrado" pelo método de média móvel no display. Veja o vídeo abaixo:
Desafios
Com base neste projeto, resolva o seguinte desafio: Desafio 96
O anúncio abaixo ajuda a manter o Squids Arduino funcionando
Comentários