Existem diversas técnicas, já usei muitas.
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.
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
SL VL ML ===== === ==== 16383 251 0 16634 253 1039 15848 251 990 15109 254 944 14419 253 901 13771 251 860 13162 256 822 12596 255 787 12064 253 754 11563 257 722 11098 253 693 10658 254 666 10246 253 640 9859 252 616 9495 257 593 9159 251 572 8838 251 552 8537 255 533 8259 257 516 8000 257 500 7757 253 484 7526 258 470 7314 252 457 7109 255 444 6920 253 432 6741 256 421 6576 255 411 6420 257 401 6276 255 392 6139 251 383 6007 254 375 5886 251 367 5770 251 360 5661 251 353 5559 257 347 5469 256 341 5384 251 336 5299 256 331 5224 251 326 5149 253 321 5081 256 317 5020 254 313 4961 254 310 4905 253 306 4852 253 303 4802 256 300 4758 251 297 4712 254 294 4672 258 292 4638 258 289 4607 254 287 4574 255 285 4544 257 284 4517 255 282 4490 256 280 4466 255 279 4442 258 277 4423 256 276 4403 251 275 4379 251 273 4357 254 272 4339 258 271 4326 258 270 4314 252 269 4297 252 268 4281 251 267 4265 255 266 4254 251 265 4240 258 265 4233 256 264 4225 253 264 4214 256 263 4207 258 262 4203 252 262 4193 254 262 4185 251 261 4175 251 260 4166 251 260 4157 253 259 4151 254 259 4146 256 259 4143 253 258 4138 252 258 4132 255 258 4129 253 258 4124 252 257 4119 253 257 4115 256 257 4114 254 257 4111 256 256 4111 255 256 4110 256 256 4110 254 256 4108 251 256 4103 256 256 4103 251 256 4098 258 256 4100 256 256 4100 254 256 4098 252 256 4094 253 255 4092 257 255 4094 258 255 4097 251 256 4092 258 255 4095 258 255 4098 257 256 4099 257 256 |
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.