Archive for April 2014

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