DESENVOLVIMENTO
TREINAMENTO
CONSULTORIA
REFERÊNCIA
EMBARC NOTÍCIAS
blog.embarc.com.br
BUSCA NO SITE
Separador.gif
Login
 
VISUALIZAÇÃO DE POST
 
topoBlog.jpg
Filtrando quase sem querer

Antes de seguir com nossa série sobre aritmética de ponto fixo, vamos aprender uma estrutura básica de processamento digital de sinais.

Ok, muito tempo se passou desde o último post, mas vamos tentar engrenar a partir de agora.

Passei muito tempo pensando em como abordar o uso do ponto fixo de forma prática e simples o suficiente para que todos pudessem compreender o conteúdo do post.

A idéia aqui é que todos os conceitos possam ser imediatamente aplicados pelos leitores, logo temos que usar conceitos muito práticos. Não queria fazer outro post puramente matemático para não intimidar os leitores.
Muitas abordagens acabavam usando alguns conceitos de processamento de sinais que não seriam imediatamente claros para todos e então acabava desistindo. Mas então pensei, se estes conceitos são tão recorrentes, por que não tentar apresenta-los logo? Acho que será interessante abrir as portas para o processamento digital de sinais, principalmente porque com estes conceitos poderemos evoluir mais rapidamente e fazer coisas muito mais interessantes.

Então, mãos à obra.

Vamos começar nosso post tentando realizar uma tarefa simples: calcular a média de um sinal. Digamos que estamos capturando um sinal com o conversor A/D de 8 bits do nosso processador e queremos mostrar o valor amostrado em um display. O problema é que o sinal é ruidoso e a cada amostra o valor apresenta uma pequena variação, que faz com que o display fique variando rapidamente e com isso não conseguimos ler o que está escrito.

Claro, podemos simplesmente mudar a taxa de atualização do display para que apenas um dos valores do conversor A/D seja mostrado a cada segundo, mas como nossa intenção aqui é usar processamento digital de sinais, temos a idéia de que se tirarmos a média das últimas 4 amostras teremos valores mais estáveis para mostrar no display.

Então o que queremos fazer é calcular a média das 5 últimas amostras. Para fazer isso, temos sempre que ter guardadas na memória do processador quais foram as últimas 5 amostras, somá-las e dividir o resultado por 4 para obtermos a média.

        amostra1 + amostra2 + amostra3 + amostra4 + amostra5
media = ----------------------------------------------------
                                  5

considerando que a amostra1 é a amostra mais antiga e a amostra5 é a amostra atual. O que acontece quando chega a amostra6?

Bem, temos que descartar a amostra mais antiga e passar a contabilizar a nova amostra. Dessa forma temos a seguinte conta:

        amostra2 + amostra3 + amostra4 + amostra5 + amostra6
média = ----------------------------------------------------
                                 5



Para facilitar a leitura e tornar a fórmula mais genérica, vamos considerar que o instante atual é chamado de (n). Se N é o instante atual, a amostra atual será chamada amostra(n). Vamos chamar o instante anterior de instante (n-1), ou seja, o instante atual menos 1. Com isso a amostra anterior se chamará amostra(n-1). O instante anterior a este se chamará isntante (n-2) e a amostra correspondente se chamará amostra(n-2) e assim por diante. Com isso podemos mudar nossa fórmula para:

       amostra(n-4)+amostra(n-3)+amostra(n-2)+amostra(n-1)+amostra(n)
med(n)=--------------------------------------------------------------
                                         5

A média das últimas 5 amostras em qualquer instante (n) poderá ser calculado com a fórmula acima.

Para facilitar o passo seguinte vamos aplicar a propriedade distributiva da divisão e reescrever a formula da seguinte maneira:

        amostra(n-4)  amostra(n-3)  amostra(n-2)  amostra(n-1)  amostra(n)
med(n)= ----------- + ----------- + ----------- + ----------- + ----------
              5            5             5             5            5

Quem leu o post anterior, deve se lembrar que computacionalmente, fazer uma divisão no processador e mais complicado que fazer uma multiplicação, então vamos mudar um pouco a formula acima para usar multiplicações ao invés de divisões (dividir por quatro equivale a multiplicar por 0,2):

med(n) = (amostra(n-4) * 0,2) +
         (amostra(n-3) * 0,2) +
         (amostra(n-2) * 0,2) +
         (amostra(n-1) * 0,2) +
         (amostra(n) * 0,2)

Em linguagem C, poderíamos criar uma função para calcular a média da seguinte forma:

// funcao calculaMedia que recebe a amostra atual e retorna a
// media das 4 ultimas amostras
signed8 calculaMedia(signed8 amostraAtual)
{
   // declara um vetor memoria para guardar as amostras.
   // memoria[4] é a amostra mais antiga e memória[0] é a amostra atual
   // o vetor é declarado com static para que os valores guardados
   // se mantenham a cada chamada da função
   static signed8 memoria[5] = {0,0,0,0,0};
   signed8 media;
  
   // descarta a amostra mais antiga e coloca a amostra atual na memoria
   memoria[4] = memoria[3];
   memoria[3] = memoria[2];
   memoria[2] = memoria[1];
   memoria[1] = memoria[0];
   memoria[0] = amostraAtual;
  
   media = (memoria[4] * 0,2) +
           (memoria[3] * 0,2) +
           (memoria[2] * 0,2) +
           (memoria[1] * 0,2) +
           (memoria[0] * 0,2);

   return (media);
}

Olhando para o código acima, primeiramente temos que esclarecer que estamos usando o tipo fictício signed8 para declarar variáveis de 8 bits com sinal. Observe também que a função acima ainda está fazendo uso das bibliotecas de ponto flutuante do compilador e não estamos usando os nossos conhecimentos de ponto fixo ainda. Isso fica para o próximo post.

A função funciona bem, mas, e se quiséssemos dar pesos diferentes para cada uma das amostras? Se por acaso eu achasse importante que as amostras mais recente tivessem maior peso, como faria?

A primeira função dá um peso igual a todas as amostras(0,2), de forma que poderíamos representar a nossa função de cálculo de média da seguinte forma:

A partir da figura acima, fica fácil ver como poderíamos mudar a função para dar pesos diferentes para cada amostra:

o calculo da media da função em linguagem C ficaria da seguinte forma:

   media = (memoria[4] * 0,1) +
           (memoria[3] * 0,1) +
           (memoria[2] * 0,1) +
           (memoria[1] * 0,3) +
           (memoria[0] * 0,4);

E com isso, quase que sem querer, acabamos chegando na implementação genérica de um filtro muito utilizado em processamento digital de sinais chamado filtro FIR(finite impulse response). Em processamento digital de sinais, representamos este filtro da seguinte maneira:

A estrutura é muito semelhante àquela que utilizamos originalmente para representar o nosso cálculo de média. A diferença está na representação de linha de retardo, onde utilizamos um bloco com um "Z-1" dentro. Esta notação vem de um processo matemático chamado "transformada z", mas por enquanto, só precisamos saber que em processamento digital de sinais, usamos o "z-1" para representar o atraso de 1 amostra.

Se a amostraN entra em um bloco "z-1", na saída temos a amostra(n-1). Se a amostra(n-3) entra em um bloco "z-1", na saída temos a amostra(n-4).

O vetor que chamamos em nossa função de "memória" é conhecido como "linha de retardo"( ou "delay line", para quem gosta de inglês).

Os pesos que usamos para multiplicar as amostras são chamados de coeficientes do filtro.

Mudando os coeficientes e o tamanho da linha de retardo, podemos criar filtros que só deixam passar algumas frequências e outras não.

Para facilitar a nossa comunicação daqui para frente vamos dar nomes a alguns filtro comuns:
- passa-baixa - só deixa passar frequências que estão abaixo de determinado valor.
- passa-alta - só deixa passar frequências acima de determinado valor
- passa-banda - só deixam passar frequências entre dois valores determinados
- rejeita-banda - não deixam passar frequencias entre dois valores determinados

Agora sim, temos algum conhecimento básico da estrutura de um filtro digital e no próximo post vamos aprofundar mais nossos conhecimentos de aritmética em ponto fixo, re-escrever este mesmo filtro usando estes conhecimentos e comparar o tamanho do código e a velocidade da nossa função de cálculo de média.

Até lá!



0 comentário(s) | Comente

Embedded Architects Tecnologia                         | +55 (61) 3202-0409
SRT/S 701 bl. K sala 326, Ed. Embassy Tower | CEP 70324-908