Filtro para leitura de ADC

screenshot.73
Durante muitos anos eu desenvolvo técnicas de filtros passa baixo por software em leitura de ADCs, para obter um sinal médio mais estável e mais funcional.

Existem diversas técnicas, já usei muitas.

Ao final das contas, ultimamente estou optando por uma técnica muito rápida e que ocupa pouco software, mesmo que ela faz uma média de 16 leituras.    Essa técnica, que vou chamar aqui de “MDM” (média das médias), vai ocupar o mesmo espaço em variáveis e praticamente a mesma quantidade de código para memorizar 1, 2, 4, 8, 16, 32 ou 64 leituras.

Para facilitar o software é interessante sempre optar por uma quantidade de amostragens que seja equivalente a 2^n, a fim de facilitar a divisão, que será feita usando só a instrução “shift-right”.

Uma técnica que eu vinha usando por anos era a do “buffer rotativo”, ou seja, eram alocados 32 bytes na memória, para 16 leituras (2 bytes cada), e um ponteiro que ficava rodando nesse buffer a cada nova leitura, substituindo a leitura mais antiga pela mais nova, então todos os 2×16 bytes eram somados e o total era dividido por 16, a fim de obter a média das ultimas mais recentes 16 leituras.

A técnica que apresentarei aqui hoje, a “MDM”, não é a média de 2^n leituras, mas é a média das médias infinitas, o que apresenta uma estabilidade muito maior, e na prática quase que independe de acumular 4, 8, ou 64 leituras, a média das médias será praticamente a mesma, o que mudará com mais ou menos leituras é a resolução do ultimo bit do valor a mostrar.

A idéia é diluir a medida atual num balde de “n” medidas anteriores, de forma a obter a média simples das leituras, mas sempre manter a média de “n” leituras anteriores.

Atenção ao detalhe, estarei mantendo A MÉDIA de “n” leituras anteriores, e não as “n” leituras anteriores.

No caso de um microcontrolador que possui um ADC de 10 bits, precisarei de dois bytes para armazenar o valor lido (VL) e a média das leituras (ML) , e também precisarei de outra variável que caiba a soma de “n” leituras (SL) de valor máximo do ADC, no caso de 10 bits, é 1024.

Portanto, precisarei de duas variável de 16 bits, e uma terceira de também 16 bits, para conter o valor máximo somado de 16 x 1024 = 16384.

Inicialmente carrego SL com a metade do valor máximo de 16 leituras, que é 8191 (0x1FFF). Pode ser qualquer valor, até 1 ou 16383, só não pode ser 0×0000 ou 0×8000, senão dá problemas na rotina.

Em seguida leio o ADC em VL, digamos que foi lido 0x13A.  Subtraio ML de SL e somo VL.

Portanto, a variavelzona SL terá :   0x1FFF – 0×0000 + 0x013A = SL = 0×2139.
Agora copio SL para ML e faço quatro shifts right em ML, obtendo o valor 0×213.
Nesse instante, o valor médio ML  será 0×213.

Leio novamente o ADC em VL, digamos que pela instabilidade foi lido 0x13D, subtraio ML de SL e adiciono VL, copio VL para ML, faço quatro shifts para a direita em ML, o que o divide por 16.
Vejamos, SL era 0×2139, subtrai 0×213 e somei 0x13D, agora SL = 0×2063, copio para ML e faço 4 shifts para a direita, resultando no novo valor médio ML de 0×0206.

Aproximadamente após 100 leituras e rodadas acima, o valor ML será a média simples das leituras do ADC, com grande estabilidade.

Uma centena de leituras parece muito, mas se a fizer a cada 5ms, significa 500ms para estabilizar a leitura.  A partir dai, as mudanças no sinal lido serão menores e poucas rodadas estabilizam.

Note que essa técnica funciona melhor quando o ADC roda continuamente, alimentando a rotina das médias.  A qualquer instante, para saber o valor da média das leituras, basta ler o valor de ML.

A teoria da rotina é que ao retirar a média das médias do valor de 16x médias, essa soma passa a ser 15x medias, e então soma-se o valor lido do ADC, e divide-se por 16, que seria o mesmo que subtrair 1/16 da média obtida e somar 1/16 do valor lido.  O problema é que fazendo dessa maneira, perde-se-ia quatro bits de baixa ordem do valor lido, e na prática seria como se eliminando os 4 bits de baixa ordem, obtendo estabilidade na marra com 6 bits do ADC.

Com a técnica acima, obtem-se a mesma estabilidade dos 6 bits da alta ordem nos 10 bits do ADC, o que é muito interessante.

Na tabela abaixo, feita no Excel, temos SL (que inicia com 0x1FFF), VL (um valor randomico entre 251 e 258) e ML (a média das médias).  Note que após aproximadamente 80 rodadas, ML já está estabilizando em torno de 256/255.


O gráfico abaixo da “perseguição” de “ML” com base em “VL”, mostra a aproximação sucessiva e a centralização em 254/255.

screenshot.76

Leave a Reply

Your email address will not be published. Required fields are marked *