Embedded C Moving Average




Embedded C Moving AverageComo outros ja mencionaram, voce deve considerar um filtro IIR (resposta de impulso infinito) em vez do filtro FIR (resposta de impulso finito) que voce esta usando agora. Ha mais, mas a primeira vista os filtros FIR sao implementados como convolucoes explicitas e filtros IIR com equacoes. O filtro IIR especial que eu uso muito em microcontroladores e um filtro de passa-baixa de polo unico. Este e o equivalente digital de um simples filtro analogico R-C. Para a maioria das aplicacoes, elas terao melhores caracteristicas do que o filtro de caixa que voce esta usando. A maioria dos usos de um filtro de caixa que eu encontrei sao o resultado de alguem nao prestar atencao na classe de processamento de sinal digital, e nao como resultado de precisar de suas caracteristicas particulares. Se voce so quer atenuar as altas frequencias que voce sabe que sao ruido, um unico polo filtro passa-baixo e melhor. A melhor maneira de implementar um digitalmente em um microcontrolador e geralmente: FILT lt - FILT FF (NEW - FILT) FILT e um pedaco de estado persistente. Esta e a unica variavel persistente que voce precisa para calcular este filtro. NEW e o novo valor que o filtro esta sendo atualizado com esta iteracao. FF e a fraccao do filtro. Que ajusta o peso do filtro. Olhe para este algoritmo e veja que para FF 0 o filtro e infinitamente pesado desde que a saida nunca muda. Para FF 1, seu realmente nenhum filtro em tudo desde que a saida apenas segue a entrada. Os valores uteis estao no meio. Em sistemas pequenos voce escolhe FF para ser 1/2 N de modo que a multiplicacao por FF possa ser realizada como um deslocamento para a direita por N bits. Por exemplo, FF pode ser 1/16 e multiplicar por FF, portanto, um deslocamento para a direita de 4 bits. Caso contrario, este filtro precisa apenas de uma subtracao e uma adicao, embora os numeros geralmente precisam ser mais largos do que o valor de entrada (mais na precisao numerica em uma secao separada abaixo). Eu costumo tomar leituras A / D significativamente mais rapido do que eles sao necessarios e aplicar dois desses filtros em cascata. Este e o equivalente digital de dois filtros R-C em serie, e atenua por 12 dB / oitava acima da frequencia de rolloff. No entanto, para as leituras A / D e geralmente mais relevante olhar para o filtro no dominio do tempo, considerando sua resposta passo. Isso indica a rapidez com que seu sistema vera uma alteracao quando a coisa que voce esta medindo muda. Para facilitar a concepcao destes filtros (que significa apenas escolher FF e decidir quantos deles para cascatear), eu uso o meu programa FILTBITS. Voce especifica o numero de bits de deslocamento para cada FF na serie de filtros em cascata e calcula a resposta da etapa e outros valores. Na verdade eu costumo correr isso atraves do meu script wrapper PLOTFILT. Isso executa FILTBITS, que faz um arquivo CSV, e depois traca o arquivo CSV. Por exemplo, aqui esta o resultado de PLOTFILT 4 4: Os dois parametros para PLOTFILT significa que havera dois filtros em cascata do tipo descrito acima. Os valores de 4 indicam o numero de bits de mudanca para realizar a multiplicacao por FF. Os dois valores FF sao, portanto, 1/16 neste caso. O traco vermelho e a resposta da etapa da unidade, e e a coisa principal a olhar. Por exemplo, isto diz-lhe que se a entrada muda instantaneamente, a saida do filtro combinado estabelecera a 90 do novo valor em 60 iteracoes. Se voce se preocupa com 95 settling tempo, entao voce tem que esperar cerca de 73 iteracoes, e por 50 tempo de resolucao apenas 26 iteracoes. O traco verde mostra a saida de um unico pico de amplitude total. Isto da-lhe alguma ideia da supressao aleatoria do ruido. Parece que nenhuma amostra ira causar mais do que uma alteracao de 2,5 na saida. O traco azul e dar uma sensacao subjetiva do que este filtro faz com o ruido branco. Este nao e um teste rigoroso, uma vez que nao ha garantia o que exatamente o conteudo foi dos numeros aleatorios escolhidos como a entrada de ruido branco para esta execucao de PLOTFILT. Seu somente para dar-lhe uma sensacao aspera de quanto sera squashed e de como liso e. PLOTFILT, talvez FILTBITS, e muitas outras coisas uteis, especialmente para o desenvolvimento de firmware PIC esta disponivel no software PIC Development Tools release na minha pagina de downloads de Software. Adicionado sobre precisao numerica eu vejo dos comentarios e agora uma nova resposta que ha interesse em discutir o numero de bits necessarios para implementar este filtro. Observe que a multiplicacao por FF criara Log 2 (FF) novos bits abaixo do ponto binario. Em sistemas pequenos, FF e geralmente escolhido para ser 1/2 N para que este multiplicar e realmente realizado por um deslocamento a direita de N bits. FILT e geralmente um inteiro de ponto fixo. Observe que isso nao altera nenhuma das matematicas do ponto de vista dos processadores. Por exemplo, se voce estiver filtrando leituras A / D de 10 bits e N 4 (FF 1/16), entao voce precisara de 4 bits de fracao abaixo das leituras A / D inteiras de 10 bits. Um processadores mais, youd estar fazendo operacoes de 16 bits inteiro devido as leituras de 10 bit A / D. Neste caso, voce ainda pode fazer exatamente as mesmas operacoes de 16 bits inteiros, mas comece com as leituras A / D esquerda deslocada por 4 bits. O processador nao sabe a diferenca e nao precisa. Fazer a matematica em inteiros inteiros de 16 bits funciona se voce os considera 12,4 pontos fixos ou inteiros verdadeiros de 16 bits (16,0 ponto fixo). Em geral, voce precisa adicionar N bits cada polo de filtro se voce nao quiser adicionar ruido devido a representacao numerica. No exemplo acima, o segundo filtro de dois teria 1044 18 bits para nao perder informacoes. Na pratica em uma maquina de 8 bits que significa youd usar valores de 24 bits. Tecnicamente apenas o segundo polo de dois precisaria do valor mais amplo, mas para a simplicidade do firmware eu costumo usar a mesma representacao, e, portanto, o mesmo codigo, para todos os polos de um filtro. Normalmente eu escrevo uma sub-rotina ou macro para executar uma operacao de polo de filtro, em seguida, aplicar isso a cada polo. Se uma subrotina ou macro depende se os ciclos ou a memoria do programa sao mais importantes nesse projeto especifico. De qualquer maneira, eu uso algum estado zero para passar NOVO para a subrotina / macro, que atualiza FILT, mas tambem carrega isso para o mesmo estado zero NOVO foi dentro Isso torna mais facil para aplicar varios polos desde o FILT atualizado de um polo e O NOVO do proximo. Quando uma sub-rotina, e util ter um ponteiro apontar para FILT no caminho, que e atualizado para logo apos FILT na saida. Dessa forma, a sub-rotina opera automaticamente em filtros consecutivos na memoria se for chamada varias vezes. Com uma macro voce nao precisa de um ponteiro desde que voce passa no endereco para operar em cada iteracao. Exemplos de codigo Aqui esta um exemplo de uma macro como descrito acima para um PIC 18: E aqui esta uma macro semelhante para um PIC 24 ou dsPIC 30 ou 33: Ambos estes exemplos sao implementados como macros usando o meu pre-processador de assembler PIC. Que e mais capaz do que qualquer um das instalacoes macro incorporadas. Clabacchio: Outra questao que eu deveria ter mencionado e a implementacao de firmware. Voce pode escrever uma sub-rotina de filtro passa-baixa de um unico polo uma vez, depois aplica-la varias vezes. Na verdade eu costumo escrever tal sub-rotina para ter um ponteiro na memoria para o estado do filtro, em seguida, te-lo avancar o ponteiro para que ele pode ser chamado em sucessao facilmente para realizar filtros multi-polo. Ndash Olin Lathrop Apr 20 12 at 15:03 1. muito obrigado por suas respostas - todas elas. Eu decidi usar este filtro IIR, mas este filtro nao e usado como um filtro LowPass padrao, uma vez que eu preciso para a media de valores de contador e compara-los para detectar alteracoes em um determinado intervalo. Uma vez que estes Valores van ser de dimensoes muito diferentes, dependendo de hardware que eu queria tomar uma media, a fim de ser capaz de reagir a estas alteracoes Hardware especificas automaticamente. Ndash sensslen May 21 12 at 12:06 Se voce pode viver com a restricao de um poder de dois numeros de itens para a media (ou seja, 2,4,8,16,32 etc), entao a divisao pode ser feita de forma facil e eficiente em um Micro de baixo desempenho sem divisao dedicada, pois pode ser feito como um deslocamento bit. Cada turno e um poder de dois, por exemplo: O OP pensou que ele tinha dois problemas, dividindo em um PIC16 e memoria para seu buffer de anel. Esta resposta mostra que a divisao nao e dificil. E verdade que ele nao trata o problema da memoria, mas o sistema SE permite respostas parciais, e os usuarios podem tirar algo de cada resposta por si mesmos, ou mesmo editar e combinar outras respostas. Uma vez que algumas das outras respostas exigem uma operacao de divisao, elas sao igualmente incompletas, uma vez que nao mostram como efetivamente conseguir isso em um PIC16. Ndash Martin Apr 20 12 at 13:01 Ha uma resposta para um verdadeiro filtro de media movel (aka boxcar filtro) com menos requisitos de memoria, se voce nao mente downsampling. E chamado um filtro integrador-pente em cascata (CIC). A ideia e que voce tem um integrador que voce toma as diferencas de um periodo de tempo, eo dispositivo de economia de memoria chave e que por downsampling, voce nao tem que armazenar cada valor do integrador. Ele pode ser implementado usando o seguinte pseudocodigo: Seu comprimento medio movel efetivo e decimationFactorstatesize, mas voce so precisa manter em torno de amostras statesize. Obviamente, voce pode obter um melhor desempenho se o seu statesize e decimationFactor sao poderes de 2, de modo que a divisao e os operadores restantes sao substituidos por turnos e mascara-ands. Postscript: Eu concordo com Olin que voce deve sempre considerar filtros IIR simples antes de um filtro de media movel. Se voce nao precisa de frequencia-nulos de um filtro de vagao, um filtro de passa-baixa de 1 polo ou de 2 polos provavelmente funcionara bem. Por outro lado, se voce estiver filtrando para fins de decimacao (tomando uma alta taxa de amostragem de entrada e de media para o seu uso por um processo de baixa taxa), em seguida, um CIC filtro pode ser exatamente o que voce esta procurando. (Especialmente se voce pode usar statesize1 e evitar o ringbuffer completamente com apenas um valor unico integrador anterior) Theres alguma analise em profundidade da matematica por tras usando o filtro IIR de primeira ordem que Olin Lathrop ja descreveu mais sobre a troca de pilha Digital Signal Processing (Inclui muitas imagens bonitas.) A equacao para este filtro IIR e: Isso pode ser implementado usando apenas inteiros e nenhuma divisao usando o codigo a seguir (pode precisar de alguma depuracao como eu estava digitando na memoria.) Este filtro aproxima uma media movel de Os ultimos K amostras, definindo o valor de alfa para 1 / K. Faca isso no codigo anterior, definindo BITS para LOG2 (K), ou seja, para K 16 set BITS para 4, para K 4 set BITS para 2, etc (eu verificar o codigo listado aqui logo que eu recebo uma alteracao e Editar esta resposta, se necessario.) Responder Jun 23 12 at 4:04 Heres um filtro passa-baixo de um unico polo (media movel, com frequencia de corte CutoffFrequency). Muito simples, muito rapido, funciona muito bem, e quase nenhuma sobrecarga de memoria. Nota: Todas as variaveis ??tem escopo alem da funcao de filtro, exceto o passado em newInput Nota: Este e um filtro de etapa unica. Varias etapas podem ser conectadas em cascata para aumentar a nitidez do filtro. Se voce usar mais de uma etapa, voce tera que ajustar DecayFactor (como se relaciona com a Cutoff-Frequency) para compensar. E, obviamente, tudo o que voce precisa e dessas duas linhas colocadas em qualquer lugar, eles nao precisam de sua propria funcao. Este filtro tem um tempo de aceleracao antes que a media movel represente a do sinal de entrada. Se voce precisar ignorar esse tempo de aceleracao, basta inicializar MovingAverage para o primeiro valor de newInput em vez de 0 e esperar que o primeiro newInput nao seja um outlier. (CutoffFrequency / SampleRate) tem um intervalo entre 0 e 0,5. DecayFactor e um valor entre 0 e 1, geralmente perto de 1. Flutuadores de precisao unica sao bons o suficiente para a maioria das coisas, eu so prefiro dobra. Se voce precisa ficar com numeros inteiros, voce pode converter DecayFactor e Amplitude Factor em inteiros fracionarios, em que o numerador e armazenado como o inteiro, eo denominador e uma potencia inteira de 2 (assim voce pode bit-shift para a direita como o Denominador em vez de ter que dividir durante o loop de filtro). Por exemplo, se voce usar DecayFactor 0,99, e voce quiser usar numeros inteiros, voce pode definir DecayFactor 0,99 65536 64881. E entao, sempre que voce multiplicar por DecayFactor em seu loop de filtro, basta deslocar o resultado 16. Para obter mais informacoes sobre isso, um excelente livro thats Online, capitulo 19 sobre filtros recursivos: dspguide / ch19.htm PS Para o paradigma da media movel, uma abordagem diferente para definir DecayFactor e AmplitudeFactor que pode ser mais relevante para suas necessidades, vamos dizer que voce quer o anterior, cerca de 6 itens media juntos, faze-lo discretamente, youd adicionar 6 itens e dividir por 6, entao Voce pode definir o AmplitudeFactor para 1/6 e DecayFactor para (1.0 - AmplitudeFactor). Respondeu May 14 12 at 22:55 Todo mundo tem comentado completamente sobre a utilidade de IIR vs FIR, e na divisao de poder-de-dois. Id gostaria de dar alguns detalhes de implementacao. O abaixo funciona bem em pequenos microcontroladores sem FPU. Nao ha multiplicacao, e se voce manter N um poder de dois, toda a divisao e de ciclo unico bit-shifting. Tampao de toque FIR basico: mantem um buffer de execucao dos ultimos N valores e uma Soma em execucao de todos os valores no buffer. Cada vez que uma nova amostra entra, subtraia o valor mais antigo no buffer de SUM, substitua-o pela nova amostra, adicione a nova amostra a SUM e a saida SUM / N. Tampao de anel IIR modificado: mantenha uma SUM corrente dos ultimos N valores. Cada vez que uma nova amostra chega, SUM - SUM / N, adicione a nova amostra e a saida SUM / N. Se I39m lendo voce direito, voce esta descrevendo um filtro IIR de primeira ordem, o valor que voce esta subtraindo isn39t o valor mais antigo que esta caindo, mas e, em vez disso, a media dos valores anteriores. Os filtros IIR de primeira ordem podem certamente ser uteis, mas nao tenho certeza do que voce quer dizer quando sugere que a saida e a mesma para todos os sinais periodicos. A uma taxa de amostragem de 10KHz, a alimentacao de uma onda quadrada de 100Hz em um filtro de caixa de 20 estagios produzira um sinal que sobe uniformemente para 20 amostras, senta alto para 30, cai uniformemente para 20 amostras e senta baixo para 30. Uma primeira ordem IIR. Ndash supercat Aug 28 13 as 15:31 vai produzir uma onda que comeca bruscamente a subir e gradualmente nivela perto (mas nao no) maximo de entrada, entao comeca bruscamente a cair e nivela gradualmente perto (mas nao) o minimo de entrada. Comportamento muito diferente. Uma questao e que uma media movel simples pode ou nao ser util. Com um filtro IIR, voce pode obter um bom filtro com relativamente poucos calcs. O FIR que voce descreve so pode lhe dar um retangulo no tempo - um sinc em freq - e voce nao pode gerenciar os lobos laterais. Pode valer a pena jogar algumas multiplicacoes inteiras para torna-la uma simpatica e simetrica sintonia FIR se voce pode poupar os carrapatos do relogio. Ndash Scott Seidman Aug 29 13 as 13:50 ScottSeidman: Nao ha necessidade de multiplicar se um simplesmente tem cada estagio do FIR ou saida a media da entrada para esse estagio e seu valor armazenado anterior, e depois armazenar a entrada (se tiver O intervalo numerico, pode-se usar a soma em vez da media). Se isso e melhor do que um filtro de caixa depende da aplicacao (a resposta de passo de um filtro de caixa com um atraso total de 1ms, por exemplo, tera um pico d2 / dt desagradavel quando a mudanca de entrada e novamente 1ms mais tarde, mas tera O minimo possivel d / dt para um filtro com um atraso total de 1 ms). Como disse mikeselectricstuff, se voce realmente precisa reduzir suas necessidades de memoria, e voce nao se importa sua resposta ao impulso e uma exponencial (em vez de um pulso retangular), eu iria para um filtro de media movel exponencial . Eu uso-os extensivamente. Com esse tipo de filtro, voce nao precisa de nenhum buffer. Voce nao tem que armazenar N amostras passadas. Apenas um. Assim, seus requisitos de memoria sao cortados por um fator de N. Alem disso, voce nao precisa de qualquer divisao para isso. Somente multiplicacoes. Se voce tiver acesso a aritmetica de ponto flutuante, use multiplicacoes de ponto flutuante. Caso contrario, faca multiplicacoes inteiras e desloque para a direita. No entanto, estamos em 2012, e eu recomendo que voce use compiladores (e MCUs) que permitem que voce trabalhe com numeros de ponto flutuante. Alem de ser mais memoria eficiente e mais rapido (voce nao tem que atualizar itens em qualquer buffer circular), eu diria que e tambem mais natural. Porque uma resposta de impulso exponencial corresponde melhor a maneira como a natureza se comporta, na maioria dos casos. Um problema com o filtro IIR como quase tocado por olin e supercat mas aparentemente desconsiderado por outros e que o arredondamento para baixo introduz alguma imprecisao (e potencialmente vies / truncamento). Assumindo que N e uma potencia de dois, e apenas aritmetica inteira e usada, o deslocamento direto sistematicamente elimina os LSBs da nova amostra. Isso significa que quanto tempo a serie poderia ser, a media nunca vai levar esses em conta. Por exemplo, suponha uma serie lentamente decrescente (8,8,8,8,7,7,7,7,6,6), e suponha que a media e realmente 8 no inicio. A amostra do punho 7 trara a media para 7, independentemente da intensidade do filtro. Apenas para uma amostra. Mesma historia para 6, etc. Agora pense no oposto. A serie sobe. A media ficara em 7 para sempre, ate que a amostra seja grande o suficiente para fazer a mudanca. Claro, voce pode corrigir o vies adicionando 1 / 2N / 2, mas isso nao vai realmente resolver o problema de precisao. Nesse caso a serie decrescente permanecera para sempre em 8 ate que a amostra seja 8-1 / 2 (N / 2). Para N4, por exemplo, qualquer amostra acima de zero mantera a media inalterada. Acredito que uma solucao para isso implicaria manter um acumulador dos LSBs perdidos. Mas eu nao fui longe o suficiente para ter o codigo pronto, e nao tenho certeza que nao iria prejudicar o poder IIR em alguns outros casos de serie (por exemplo, se 7,9,7,9 seria media para 8 entao). Olin, sua cascata de dois estagios tambem precisaria de alguma explicacao. Voce quer dizer segurando dois valores medios com o resultado do primeiro alimentado para o segundo em cada iteracao. O que e o beneficio deste Embedded C Software Engineer Empregos A tabela a seguir e para comparacao com o acima e fornece estatisticas para toda a categoria de titulos de emprego em trabalhos permanentes anunciados em todo o Reino Unido. A maioria das vagas de emprego incluem um titulo de trabalho discernivel. Como tal, os numeros na primeira linha fornecem uma indicacao do numero total de postos de trabalho permanentes na amostra global. Titulos de emprego Categoria Reino Unido Permanent IT anuncios de emprego com uma correspondencia na categoria de Titulos de emprego Como de todos os postos de trabalho permanentes de TI localizados no Reino Unido Numero de salarios cotados Mediano mudanca de salario ano-a-ano 90 ofereceu um salario de mais de 10 ofereceu um salario de Mais do que Reino Unido, excluindo o salario medio de Londres Embedded C Software Engineer Empregos Demand Trend A tendencia de procura de anuncios de emprego que apresentaram Embedded C Software Engineer no cargo. Embedded C Software Engineer Salary Trend Este grafico fornece a media movel de 3 meses para os salarios citados em empregos permanentes de TI citando Embedded C Software Engineer dentro do Reino Unido. Embedded C Software Engineer Salario Histograma Esta tabela fornece um histograma de salario para empregos de TI citando Embedded C Software Engineer durante os 3 meses a 6 de outubro de 2016 no Reino Unido. Embedded C Software Engineer Top 30 locais de trabalho A tabela abaixo analisa a demanda e fornece um guia para os salarios medios citados em empregos de TI citando Embedded C Software Engineer dentro do Reino Unido durante os 3 meses a 6 de outubro de 2016. A coluna Rank Change Indicacao da variacao da procura dentro de cada localidade com base no mesmo periodo de 3 meses do ano anterior. A tendencia da procura de anuncios de emprego citando Embedded C como uma proporcao de todos os trabalhos de TI com uma correspondencia no Programa de Programacao Categoria Idiomas. Tendencia de Salario C Incorporado Este grafico fornece a media movel de 3 meses para salarios citados em empregos de TI permanentes citando Embedded C no Reino Unido. Histograma de salario C incorporado Este grafico fornece um histograma de salario para os trabalhos de TI citando Embedded C durante os 3 meses ate 6 de outubro de 2016 no Reino Unido. Embedded C Top 30 locais de trabalho A tabela abaixo analisa a demanda e fornece um guia para os salarios medios citados em empregos de TI citando Embedded C no Reino Unido durante os 3 meses ate 6 de outubro de 2016. A coluna de mudanca de Rank fornece uma indicacao da mudanca Na demanda dentro de cada localidade com base no mesmo periodo de 3 meses do ano passado. (Clique em ver estatisticas detalhadas e tendencias) Mudanca de Rank no mesmo periodo Ultimo ano Correspondencia Permanent IT Job Ads Salario mediano Last 3 Months Filtragem digital sem a dor Save to My Library Seguir Comentarios Gary A. GeissingerSeptember 28, 2005 Ha alguns anos, enquanto o ensino Um curso de graduacao em engenharia eletrica, eu precisava introduzir o conceito de filtragem digital. O truque era encontrar uma maneira de apresentar o material sem (pelo menos inicialmente) contando com conceitos matematicos avancados. Esta e a abordagem que eu estabeleci. Meio-medio Lembre-se de volta na escola quando voce aprendeu sobre medias Eles sao uma ferramenta poderosa. Na maioria das vezes, uma media e definida como: A ideia de adaptar a media para a filtragem digital e que se voce tiver n medidas ruidosas, a media dessas medicoes lhe dara a melhor estimativa da verdadeira natureza de x. Esta tecnica parece um filtro passa-baixa, mas na escola este termo nao faria muito sentido. Vamos considerar o caso mais simples de medicao das leituras. Neste caso, voce mede o sinal em uma taxa de amostragem fixa. Voce pode obter os dados de medicao usando um conversor analogico-digital (ADC) ou um voltimetro. A unica exigencia real e que um intervalo de tempo fixo ocorra entre cada leitura. A media mais simples que voce poderia executar seria: A implementacao e bastante simples. Basta adicionar a medida atual a medicao anterior e dividir pelo numero de medicoes, neste caso, simplesmente duas. Filtro FIR de media movel Este tipo de media tambem e um exemplo simples de um filtro digital de resposta de impulso finito simetrico (FIR). Por que a resposta e finita Como somente as duas ultimas amostras sao usadas, as amostras mais antigas nao estao disponiveis para uso no calculo. Portanto, a duracao da influencia de qualquer amostra na saida e finita. Em DSP terra, a equacao pode ser algo como isto: Os indices em xey indicam simplesmente a idade relativa dos dados e resultado. Alguns comentarios estao em ordem. Primeiro, note que os coeficientes sao simetricos (ambos sao 0,5), ou seja, a lista de coeficientes e identica quando examinada para frente ou para tras. Este palindrome numerico nao parece um grande negocio aqui com apenas dois coeficientes, mas alguns filtros FIR simetricos tem muitos, muitos coeficientes. Alem disso, observe que este filtro tem ganho unitario para uma entrada de corrente continua (constante). Afinal, a media de duas leituras identicas produz o mesmo valor das proprias leituras. O que nao pode ser tao obvio e que uma entrada na metade da taxa de amostragem cancela completamente, como voce pode ver na Figura 1. Figura 1: Tomados em pares, a entrada amostrada sempre somas a 0 Outra caracteristica importante deste filtro e que Sua incondicionalmente estavel. Sem feedback de qualquer tipo, essa estabilidade deve ser o caso. Como voce vera mais tarde, nem todos os filtros digitais podem fazer essa afirmacao. Quando voce amostrou os dados, voce sabia que tempo as amostras foram tomadas. Por que tempo e a saida do filtro definida em outras palavras, qual e o atraso do filtro Intuitivamente, uma vez que a magnitude da saida do filtro e a media de duas amostras sequenciais, parece que o atraso do filtro deve estar a meio caminho entre a media Amostras. Para um sinal com metade da taxa de amostragem, este seria um atraso de 1/4 do periodo da entrada, ou 90 graus. Verificando o desempenho do filtro usando Matlab Usamos um pouco de matematica e muita intuicao para determinar o desempenho do filtro. Uma ferramenta como o MATLAB pode nos dar uma imagem um pouco melhor. O programa MATLAB mostrado na Listagem 1 foi usado. Listagem 1: Programa MATLAB para determinar o desempenho do filtro O grafico de magnitude mostrado na Figura 2 verifica que o ganho e 1,0 em frequencia zero e cai para 0,0 quando a frequencia e metade da taxa de amostragem. Figura 2: Resposta de magnitude de FIR simples O grafico de fase na Figura 3 mostra que o filtro tem atraso linear que e um maximo de 90 graus a uma frequencia de metade da taxa de amostragem. Figura 3: Resposta de fase FIR simples Computacao manual de desempenho de filtro FIR simetrico Se voce gosta de mim, voce esta desconfiado das ferramentas de software ate fazer as contas manualmente. Para um filtro FIR simples nao e muito dificil. Na Equacao 3: os indices em xey indicaram a idade relativa dos dados de entrada e a saida do filtro. Vamos reescrever a equacao para este filtro usando o operador de intervalo de tempo de unidade z. O operador z e muito util. Permite a analise matematica de operacoes que dependem da amostragem em intervalos de tempo constantes. Em uma expressao matematica quando os dados sao multiplicados por z. O expoente de z indica a idade relativa dos dados. Enquanto uma discussao geral de z transforma esta alem do escopo deste artigo, aplicacoes simples de z transforma pode ser muito util. Usando o operador z, a Equacao 4 pode ser colocada da seguinte forma: X (z) indica uma serie de dados de entradas no filtro Y (z) indica uma serie temporal das saidas do filtro. Neste caso, a funcao de transferencia (o termo que converte a entrada na saida) e definida como: Cast para a terminologia usual DSP, nosso objetivo agora e encontrar as caracteristicas de nossa funcao de transferencia. Ao inves de passar um semestre em um curso de sistemas lineares, por agora vamos apenas pegar alguns fatos sobre z transforma que precisamos. Primeiro z pode ser definido como: Uma nota sobre j. Nao, voce nao pode tomar a raiz quadrada de -1, mas pense sobre as caracteristicas que j teria. Quando j e multiplicado por j. O resultado e -1. Dois termos contendo j podem ser adicionados em conjunto. Entao j e realmente apenas um operador que se comportaria como a raiz quadrada de -1. Uma pequena digressao aqui para falar sobre a largura de banda maxima de filtros digitais. A largura de banda de saida maxima de um filtro digital e definida como sendo inferior a metade da taxa de amostragem e e referida como banda de base. Se a taxa de amostragem for considerada como 2pi, entao definir a frequencia omega entre 0 e pi deve fazer sentido. Lembre-se de nosso objetivo aqui: encontrar a resposta do filtro em funcao da frequencia. O plano, matematicamente falando, e livrar-se dos termos z nas equacoes o mais rapido possivel. Voce pode fazer isso usando um pouco de trigonometria para reescrever Eulers Formula na forma: Podemos obter a nossa equacao nesta forma Sim, se lembrarmos que ambos os coeficientes sao identicos e aplicar um pouco de matematica passo a passo: Sobre este tempo voce pode olhar Equacao 9 e ser tentado a dizer, simplesmente otimo. E agora o que isso significa? Ha tres termos a considerar. O termo constante 2 b 0 e simplesmente 2 0,5 ou apenas 1. tem uma magnitude constante de 1, mas a sua fase varia linearmente com a frequencia. Esta variancia e a razao pela qual os filtros FIR simetricos sao considerados como tendo um desempenho de fase linear. By the way, desempenho de fase linear e uma coisa muito boa. Ele minimiza a distorcao dos dados filtrados. Tem uma amplitude que varia com a frequencia. Quando o omega e zero, a amplitude e 1. Quando o omega e igual a pi, a amplitude e zero. Isso duplica nossa compreensao do filtro da intuicao. A curva real e mostrada na Figura 4. Figura 4: Resposta de magnitude media de dois pontos Como voce pode ver, e bastante facil prever o desempenho de um filtro com apenas duas torneiras. Como voce pode imaginar, quando o numero de coeficientes aumenta, o desempenho do filtro aumenta tambem. Naturalmente, do ponto de vista do design do filtro, resolvemos o problema para tras no exemplo anterior. Agora vamos tentar ir na outra direcao. Design manual de um filtro FIR Voce pode projetar filtros FIR manualmente. Vamos adicionar a restricao de que quando a frequencia de entrada e um quarto da taxa de amostragem, o ganho do filtro e 0,5. Ainda queremos que o filtro seja um filtro passa-baixa com ganho unitario na frequencia zero e um ganho de zero a metade da taxa de amostragem. Porque acabamos de adicionar outra restricao, bem precisa adicionar outro coeficiente. Desde que queremos emparelhar termos, se voce inicialmente tem um numero par de torneiras, voce pode adicionar apenas um coeficiente. Se voce tiver um numero impar de toques, voce deve adicionar dois. Uma vez que o filtro original tinha dois toques, vamos precisar de tres isso faz com que a funcao de transferencia: Uma vez que estavam trabalhando com filtros FIR simetricos, a primeira e ultima torneiras get emparelhado, entao os coeficientes devem ser identicos. Trabalhando os rendimentos de matematica: Novamente, o exponencial restante da apenas o atraso do filtro neste caso, e um passo de tempo. A amplitude do filtro e dada pelo segundo termo. Alguma algebra sera necessaria para calcular os dois coeficientes. O termo Cos desaparece quando omega pi / 2. A essa frequencia queremos que a resposta seja 0,5, entao b 1 0,5. Quando a frequencia e 0, queremos que a resposta seja 1, entao b 0 0,25. Quando plotada, esta resposta produz a curva mostrada na Figura 5. Figura 5: Resposta de magnitude do filtro FIR de tres derivacoes Duas caracteristicas de qualquer filtro FIR simetrico de comprimento podem agora ser compreendidas. Primeiro, o atraso atraves do filtro aumenta a medida que o numero de termos (ou torneios) aumenta. O atraso e metade do atraso total dentro do filtro. Em segundo lugar, a medida que o numero de termos no filtro e aumentado, o filtro pode ser especificado em mais e mais pontos. Claramente, usando esta abordagem e possivel projetar filtros passa-baixa, passa-alta e passa-banda usando algebra. A medida que voce adiciona coeficientes, a quantidade de computacao aumenta eventualmente seu bastante inviavel para fazer a matematica a mao. Este processo tem sido automatizado em algoritmos de software frequentemente aplicados sao os algoritmos de troca Parks-McClelland e Remez. Um outro comentario: os verdadeiros filtros de parede de tijolos exigem infinitamente muitas torneiras, mas um filtro FIR simetrico projetado usando varios milhares de torneiras pode parecer muito bom mesmo Projetando um filtro FIR usando MATLAB Permite projetar um filtro que tem uma aplicacao em radio amador. O demodulador de teletipo de radio Dovetron MPC-1000R usa receptores superheterodinos separados para os tons de marca e espaco com uma frequencia intermediaria (IF) de 750Hz. O programa MATLAB na Listagem 2 produz um filtro IF de 750Hz usando DSP em vez de filtros ativos op-amp. Listagem 2: Programa MATLAB para determinar o desempenho do filtro O programa gerou o filtro usando 179 coeficientes mostrados na Figura 6. Naturalmente, quem usa filtros analogicos realmente odeia esse filtro. A onda pass-band parece alta ea rejeicao out-of-band e ruim, a 30dB. Voce pode alterar os parametros de ripple e construir um filtro melhor demonstrado na Figura 7. Figura 6: DoRemez resposta de magnitude Naturalmente, esta melhoria no desempenho requer mais coeficientes. Neste caso foram necessarios 369. Isso significa que pelo menos 369 adicoes e 185 multiplicacoes devem ser realizadas 8.000 vezes por segundo para manter o filtro atualizado. Dado que um demodulador de teletipo de radio exigiria dois destes filtros eo resto do codigo, filtros perfeitos podem executa-lo fora de ciclos de CPU. You should expect to compromise on filter length (and therefore performance) in real-world applications. Perhaps there is a more computationally efficient way to implement a digital filter. This requires us to go back to the concept of averages. Optimized average computation Lets say that you want to compute the average of the latest 100 data samples. This could be done using the following expression: Using this approach you have to hang on to the most recent 100 samples. To compute the new result, the oldest sample is thrown away and the newest sample inserted. This seems pretty inefficient, computationally speaking. Maybe you can get a similar effect without all the complexity. If you think about this for a minute, only one percent of the result depends on the latest data sample. The remaining 99 depends on the previous samples. Why not try this instead: This computation has a DC gain of 1, and the newest reading is weighted at 1 as desired. Its also much faster to compute and only the previous estimate and a new sample are required to update the filter. Because of the feedback (using the previous estimate), this is an infinite impulse response (IIR) filter Why is that the case Well, think about what happens if you get one really bad reading. After each new sample the effect of the bad sample is only reduced by a factor of 0.99. In a real-world DSP implementation, the effect of a bad sample is not truly infinite, but it can be a very long time. This example of a simple IIR filter is worth remembering. It works quite well when carefully implemented and can have a very long time constant. It makes a great variable-bandwidth lowpass filter just two coefficients have to be adjusted to change the bandwidth. The IIR filter transfer function The equation for what we just accomplished could be written as: With a little algebra we can arrive at the transfer function: In a standard format, numerator coefficient vector of the transfer function is called b the denominator coefficient vector is called a. The following MATLAB program was used to plot the filter response: The magnitude response plot in Figure 8 shows a steep low-pass response. As you can see, this filter has impressive performance given the simple math. Can you combine the simple FIR and IIR filters that have been examined Sure. Figure 8: Simple IIR magnitude response Combining (cascading) filters The FIR transfer function we found basically was: Equation 16 can be multiplied with the IIR transfer function: resulting in a new transfer function: This new first order IIR filter, shown in Figure 9, has the characteristics of both the previous filters. Figure 9: Combined IIR magnitude response The characteristics include the steep low-pass curve of the IIR filter with the 0 gain at half the sample frequency of the FIR filter. Since the new filter uses a previous filter output value, the filter must still be an IIR filter. Most practical IIR filters use a time series of both the input samples and the filter outputs. IIR filters dont have linear phase response as you can see in Figure 10. Figure 10: Combined IIR phase response Given that its possible to realize Bessel filters using an IIR design, this limitation can be mitigated in most cases. IIR filters and stability Consider the IIR filter example I just described with a constant input amplitude of 1.0. What happens, if due to a numerical error, the 0.99 coefficient is actually 1.0 As you can see in Table 1, the output is increasing with each sample. Given enough time, the estimated value will become quite large and eventually crash the process. It doesnt take much for an IIR filter to go unstable. Since an IIR filter uses feedback, it can obviously be unstable if it isnt designed correctly. As you can see from the example, the filter must be implemented correctly as well. It is possible--and pretty simple--to determine if a given IIR filter will be stable in design: 1. Repeatedly multiply all of the terms in the denominator of the transfer function by z until all powers of z are non-zero. This yields a polynomial in z in the denominator. 2. Solve for z in the denominator polynomial. 3. All of the roots of this denominator polynomial (often called poles) must be less than one in magnitude. This is usually stated as, The poles due in the denominator of a transfer function must reside inside of the unit disk. Finally, due to numerical errors, any given DSP system generally has a practical limit to the number of terms (taps) that are safe with an IIR filter. It can be as few as 15 or 20 denominator coefficients. Given a practical limit on the number of terms in an IIR filter, there is a way around the problem if a high-performance IIR filter is needed. A long IIR filter can be broken into smaller filters using partial fraction expansion and cascaded. Or simply cascade shorter identical IIR filter sections until you get the desired performance. Both solutions are commonly used in real-world designs. Software design of IIR filters IIR filters can be designed to implement traditional filter characteristics, such as Butterworth, Bessel, Cauer, and Chebyshev filters. Because of the long data persistence in IIR filters, an IIR filter of modest length can have the same basic amplitude performance as an FIR filter with many more taps. Here is a MATLAB program that designs a Bessel filter similar to the FIR-based IF filter we designed before. This program generates a transfer function with only 15 numerator coefficients and 15 denominator coefficients. That means the filter update requires only 30 additions and 30 multiplies. The filter performance, shown in Figure 11, is good considering the small number of coefficients. Figure 11: Bessel discrete bandpass magnitude Bessel filters are used because of the linear phase characteristics in the pass band. Note how linearly the phase changes from about 720 to 790Hz in Figure 12. Figure 12: Bessel discrete bandpass magnitude You need to be aware that the discontinuities are from phase wrapping in the plot. The nonlinear portion is best seen from 600 to 700Hz and 800 to 900Hz. With any luck, there wont be much energy passed by the filter in this region. Back to class By the way, the final project in the class was to design a complete DSP equivalent of the Dovetron MPC-1000R demodulator. By the time the students finished coding their projects and debugged them, they had FSK modulation and demodulation as well as radio teletype transmission and reception pretty well figured out. More than one expressed an interest in amateur radio Gary Geissinger is chief electrical engineer at DigitalGlobe Inc and teaches senior - and graduate-level hardware and software interface classes at the University of Colorado. You can reach him at ggeissingerdigitalglobe . Resources: Oppenheim, A. V. and R. W. Schafer. Digital Signal Processing . Prentice-Hall, Inc. 1975. Rabiner, L. R. and B. Gold. Theory and Application of Digital Signal Processing . Prentice-Hall, Inc. 1975. Stearns, S. D. and R. A. David. Signal Processing Algorithms . Englewood Cliffs: Prentice-Hall, Inc. 1988. Mitra, S. K. Digital Signal Processing: a computer-based approach . McGraw-Hill, 2001. Rorabaugh, C. B. Digital Filter Designers Handbook . McGraw-Hill, 1993. Lathi, B. P. Linear Systems and Signals. Berkeley-Cambridge, 1992.Averages/Simple moving average Averages/Simple moving average You are encouraged to solve this task according to the task description, using any language you may know. Computing the simple moving average of a series of numbers. Create a stateful function/class/instance that takes a period and returns a routine that takes a number as argument and returns a simple moving average of its arguments so far. A simple moving average is a method for computing an average of a stream of numbers by only averaging the last 160 P 160 numbers from the stream, 160 where 160 P 160 is known as the period. It can be implemented by calling an initialing routine with 160 P 160 as its argument, 160 I(P), 160 which should then return a routine that when called with individual, successive members of a stream of numbers, computes the mean of (up to), the last 160 P 160 of them, lets call this 160 SMA(). The word 160 stateful 160 in the task description refers to the need for 160 SMA() 160 to remember certain information between calls to it: 160 The period, 160 P 160 An ordered container of at least the last 160 P 160 numbers from each of its individual calls. Stateful 160 also means that successive calls to 160 I(), 160 the initializer, 160 should return separate routines that do 160 not 160 share saved state so they could be used on two independent streams of data. Pseudo-code for an implementation of 160 SMA 160 is: This version uses a persistent queue to hold the most recent p values. Each function returned from init-moving-average has its state in an atom holding a queue value. This implementation uses a circular list to store the numbers within the window at the beginning of each iteration pointer refers to the list cell which holds the value just moving out of the window and to be replaced with the just-added value. Using a Closure edit Currently this sma cant be nogc because it allocates a closure on the heap. Some escape analysis could remove the heap allocation. Using a Struct edit This version avoids the heap allocation of the closure keeping the data in the stack frame of the main function. Same output: To avoid the floating point approximations keep piling up and growing, the code could perform a periodic sum on the whole circular queue array. This implementation produces two (function) objects sharing state. It is idiomatic in E to separate input from output (read from write) rather than combining them into one object. The structure is the same as the implementation of Standard DeviationE. The elixir program below generates an anonymous function with an embedded period p, which is used as the period of the simple moving average. The run function reads numeric input and passes it to the newly created anonymous function, and then inspects the result to STDOUT. The output is shown below, with the average, followed by the grouped input, forming the basis of each moving average. Erlang has closures, but immutable variables. A solution then is to use processes and a simple message passing based API. Matrix languages have routines to compute the gliding avarages for a given sequence of items. It is less efficient to loop as in the following commands. Continuously prompts for an input I . which is added to the end of a list L1 . L1 can be found by pressing 2ND/1, and mean can be found in List/OPS Press ON to terminate the program. Function that returns a list containing the averaged data of the supplied argument Program that returns a simple value at each invocation: list is the list being averaged: p is the period: 5 returns the averaged list: Example 2: Using the program movinav2(i,5) - Initializing moving average calculation, and define period of 5 movinav2(3, x):x - new data in the list (value 3), and result will be stored on variable x, and displayed movinav2(4, x):x - new data (value 4), and the new result will be stored on variable x, and displayed (43)/2 . Description of the function movinavg: variable r - is the result (the averaged list) that will be returned variable i - is the index variable, and it points to the end of the sub-list the list being averaged. variable z - an helper variable The function uses variable i to determine which values of the list will be considered in the next average calculation. At every iteration, variable i points to the last value in the list that will be used in the average calculation. So we only need to figure out which will be the first value in the list. Usually well have to consider p elements, so the first element will be the one indexed by (i-p1). However on the first iterations that calculation will usually be negative, so the following equation will avoid negative indexes: max(i-p1,1) or, arranging the equation, max(i-p,0)1. But the number of elements on the first iterations will also be smaller, the correct value will be (end index - begin index 1) or, arranging the equation, (i - (max(i-p,0)1) 1),and then, (i-max(i-p,0)). Variable z holds the common value (max(i-p),0) so the beginindex will be (z1) and the numberofelements will be (i-z) mid(list, z1, i-z) will return the list of value that will be averaged sum(. ) will sum them sum(. )/(i-z) ri will average them and store the result in the appropriate place in the result list Using a closure and creating a function