Monday 10 July 2017

Movendo O Hardware Médio Do Filtro


O Guia de cientistas e engenheiros para processamento de sinal digital Por Steven W. Smith, Ph. D. Capítulo 15: Filtros médios móveis Parentes do filtro de média móvel Em um mundo perfeito, os designers de filtros só precisam lidar com informações codificadas no domínio do tempo ou no domínio da freqüência, mas nunca uma mistura dos dois no mesmo sinal. Infelizmente, existem algumas aplicações em que ambos os domínios são simultaneamente importantes. Por exemplo, sinais de televisão se enquadram nesta categoria desagradável. As informações de vídeo são codificadas no domínio do tempo, ou seja, a forma da forma de onda corresponde aos padrões de brilho na imagem. No entanto, durante a transmissão, o sinal de vídeo é tratado de acordo com sua composição de freqüência, como sua largura de banda total, como as ondas de suporte para cor de amplificador de som são adicionadas, restauração de amplificação de eliminação do componente de CC, etc. Como outro exemplo, interferência eletromagnética É melhor entendido no domínio de freqüência, mesmo que a informação de sinais seja codificada no domínio do tempo. Por exemplo, o monitor de temperatura em uma experiência científica pode estar contaminado com 60 hertz das linhas de energia, 30 kHz de uma fonte de alimentação de comutação ou 1320 kHz de uma estação de rádio AM local. Parentes do filtro de média móvel têm melhor desempenho de domínio de freqüência e podem ser úteis nestas aplicações de domínio misto. Os filtros médios móveis de passagem múltipla envolvem passar o sinal de entrada através de um filtro médio móvel duas ou mais vezes. A Figura 15-3a mostra o kernel geral do filtro resultante de uma, duas e quatro passagens. Duas passagens equivalem a usar um kernel de filtro triangular (um kernel de filtro retangular convolvido com ele próprio). Após quatro ou mais passagens, o kernel de filtro equivalente parece um Gaussiano (lembre-se do Teorema do Limite Central). Conforme mostrado em (b), as passagens múltiplas produzem uma resposta de passo em forma de S, em comparação com a linha reta da única passagem. As respostas de freqüência em (c) e (d) são dadas pela Eq. 15-2 multiplicado por si mesmo por cada passagem. Ou seja, cada vez que a convolução do domínio resulta em uma multiplicação dos espectros de freqüência. A Figura 15-4 mostra a resposta de freqüência de dois outros familiares do filtro de média móvel. Quando um Gaussiano puro é usado como um kernel de filtro, a resposta de freqüência também é gaussiana, conforme discutido no Capítulo 11. O gaussiano é importante porque é a resposta de impulso de muitos sistemas naturais e manmade. Por exemplo, um breve pulso de luz entrando em uma longa linha de transmissão de fibra óptica sairá como um pulso gaussiano, devido aos diferentes caminhos captados pelos fótons dentro da fibra. O kernel de filtro gaussiano também é usado extensivamente no processamento de imagens porque possui propriedades únicas que permitem rápidas ondulações bidimensionais (ver Capítulo 24). A segunda resposta de freqüência na Fig. 15-4 corresponde ao uso de uma janela Blackman como kernel de filtro. (A janela do termo não tem significado aqui é simplesmente parte do nome aceito desta curva). A forma exata da janela Blackman é dada no Capítulo 16 (Eq. 16-2, Fig. 16-2) no entanto, parece muito com um gaussiano. Como estes parentes do filtro de média móvel melhor do que o filtro de média móvel em si. Três maneiras: primeiro e mais importante, esses filtros têm melhor atenuação de parada do que o filtro de média móvel. Em segundo lugar, os grãos de filtro se afilam a uma amplitude menor perto das extremidades. Lembre-se de que cada ponto no sinal de saída é uma soma ponderada de um grupo de amostras da entrada. Se o kernel do filtro diminui, as amostras no sinal de entrada que estão mais distantes recebem menos peso do que as próximas. Em terceiro lugar, as respostas passo a passo são curvas suaves, em vez da linha direta abrupta da média móvel. Estes últimos dois geralmente são de benefício limitado, embora você possa encontrar aplicativos onde eles são vantagens genuínas. O filtro de média móvel e seus parentes são quase iguais em reduzir o ruído aleatório enquanto mantém uma resposta passo a passo. A ambigüidade reside na forma como o tempo de subida da resposta passo é medido. Se o tempo de subida for medido de 0 a 100 da etapa, o filtro médio móvel é o melhor que você pode fazer, como mostrado anteriormente. Em comparação, medir o tempo de subida de 10 a 90 torna a janela Blackman melhor do que o filtro de média móvel. O argumento é que isso é apenas dificuldades teóricas consideram esses filtros iguais neste parâmetro. A maior diferença nesses filtros é a velocidade de execução. Usando um algoritmo recursivo (descrito em seguida), o filtro de média móvel funcionará como um raio em seu computador. Na verdade, é o filtro digital mais rápido disponível. Várias passagens da média móvel serão correspondentemente mais lentas, mas ainda muito rápidas. Em comparação, os filtros gaussianos e negros são incrivelmente lentos, porque devem usar convolução. Acho um fator de dez vezes o número de pontos no kernel do filtro (com base na multiplicação sendo cerca de 10 vezes mais lento do que a adição). Por exemplo, espere que um gaussiano de 100 pontos seja 1000 vezes mais lento do que uma média móvel usando recursão. Estou codificando algo no momento em que eu estou levando um monte de valores ao longo do tempo a partir de uma bússola de hardware. Esta bússola é muito precisa e atualiza-se com muita frequência, com o resultado de que, se ela for ligeiramente leve, acabo com o valor estranho que é extremamente incompatível com seus vizinhos. Eu quero suavizar esses valores. Tendo feito alguma leitura ao redor, parece que o que eu quero é um filtro passa-alto, um filtro passa-baixa ou uma média móvel. Mudar a média com que consigo descer, mantenho um histórico dos últimos 5 valores ou o que quer que seja e use a média desses valores a jusante no meu código, onde acabei de usar o valor mais recente. Isso deve, penso eu, suavizar esses jiggles bem, mas isso me parece que é provavelmente bastante ineficiente, e este é provavelmente um desses problemas conhecidos para programadores adequados para os quais há uma solução de matemática Inteligente verdadeiramente arrumada. Eu sou, no entanto, um daqueles horríveis programadores autodidatas sem um pingo de educação formal em qualquer coisa, mesmo vagamente relacionada com CompSci ou Matemática. Ler em torno de um pouco sugere que este pode ser um filtro de passagem alta ou baixa, mas não consigo encontrar nada que explique em termos compreensíveis para um hack como eu, qual seria o efeito desses algoritmos em uma série de valores, e muito menos como as matemáticas trabalho. A resposta dada aqui. Por exemplo, tecnicamente responde a minha pergunta, mas apenas em termos compreensíveis para aqueles que provavelmente já saberiam como resolver o problema. Seria uma pessoa muito adorável e inteligente, de fato, quem poderia explicar o tipo de problema que isso é, e como funcionam as soluções, em termos compreensíveis para um graduado em artes. Perguntou 21 de setembro às 13:01 Se sua média móvel deve ser longa para conseguir o alisamento necessário e você realmente não precisa de nenhuma forma específica de kernel, então você estará melhor se usar uma média móvel exponencialmente decadente: onde você Escolha minúsculo para ser uma constante apropriada (por exemplo, se você escolher um pequeno 1- 1N, ele terá a mesma quantidade de média como uma janela de tamanho N, mas distribuído de maneira diferente em pontos mais antigos). De qualquer forma, uma vez que o próximo valor da média móvel depende apenas do anterior e de seus dados, você não precisa manter uma fila ou qualquer coisa. E você pode pensar nisso como fazendo algo como, Bem, eu tenho um novo ponto, mas eu realmente não confio nisso, então eu vou manter 80 da minha antiga estimativa da medição, e só confio neste novo ponto de dados 20. Isso é Praticamente o mesmo que dizer: Bem, eu só confio neste novo ponto 20, e eu uso 4 outros pontos que eu confio na mesma quantia, exceto que em vez de tomar explicitamente os 4 outros pontos, você está assumindo que a média que você fez na última vez Foi sensato para que você possa usar seu trabalho anterior. Respondeu 21 de setembro 10 às 14:27 Ei, eu sei que isso é 5 anos de atraso, mas obrigado por uma ótima resposta. Estou trabalhando em um jogo onde o som muda com base em sua velocidade, mas, devido ao funcionamento do jogo em um computador de câmera lenta, a velocidade flutuaria selvagemente, o que era bom para a direção, mas super irritante em termos de som. Esta foi uma solução muito simples e barata para algo que pensei que seria um problema realmente complexo. Ndash Adam Mar 16 15 at 20:20 Se você está tentando remover o valor ímpar ocasional, um filtro passa-baixa é a melhor das três opções que você identificou. Os filtros de passagem baixa permitem mudanças de baixa velocidade, como as causadas pela rotação de uma bússola à mão, ao mesmo tempo que rejeitam mudanças de alta velocidade, como as causadas por solavancos na estrada, por exemplo. Uma média móvel provavelmente não será suficiente, uma vez que os efeitos de uma única descarga em seus dados afetarão vários valores subsequentes, dependendo do tamanho da sua janela média móvel. Se os valores estranhos forem facilmente detectados, você pode até estar melhor com um algoritmo de remoção de falhas que os ignora completamente: Aqui está um gráfico de guick para ilustrar: O primeiro gráfico é o sinal de entrada, com uma falha desagradável. O segundo gráfico mostra o efeito de uma média móvel de 10 amostras. O gráfico final é uma combinação da média de 10 amostras e do algoritmo de detecção de falha simples mostrado acima. Quando a falha é detectada, a média de 10 amostras é usada em vez do valor real. Mover média com a qual posso descer. Mas parece-me que é provavelmente bastante ineficiente. Realmente, nenhum motivo para uma média móvel deve ser ineficiente. Você mantém o número de pontos de dados desejados em algum buffer (como uma fila circular). Em cada novo ponto de dados, você exibe o valor mais antigo e subtrai-lo de uma soma, e empurre o mais novo e adicione-o à soma. Portanto, cada novo ponto de dados realmente só envolve um poppush, uma adição e uma subtração. Sua média móvel é sempre essa soma de mudança dividida pelo número de valores em seu buffer. Isso fica um pouco mais complicado se você estiver recebendo dados simultaneamente de vários tópicos, mas como seus dados são provenientes de um dispositivo de hardware que parece muito duvidoso para mim. Ah, e também: os horríveis programadores autodidatas se unem) A média móvel pareceu ineficiente para mim porque você precisa armazenar um buffer de valores - melhor para fazer algumas Matemáticas Inteligentes com seu valor de entrada e valor de trabalho atual Eu acho que isso é como a média móvel exponencial trabalho. Uma otimização que eu vi para este tipo de média móvel envolve o uso de um amplificador de espera de comprimento fixo, um ponteiro para onde você está na fila, e apenas empacotando o ponteiro ao redor (com ou um if). Voila Não há pushpop caro. Poder para os amadores, irmão ndash Henry Cooke 22 de setembro 10 às 0:54 Henry: Para uma média móvel direta, você precisa do buffer simplesmente para que você saiba o valor que aparece quando o próximo valor é empurrado. Dito isto, o amplo amplificador de espera de comprimento fixo que você está descrevendo é exatamente o que eu quis dizer com uma fila quotcircular. Por isso, eu estava dizendo que isso não é ineficiente. O que você achou que eu quis dizer E se sua resposta é uma matriz quotan que muda seus valores de volta em cada remoção indexada (como std :: vector em C). Bem, então, eu já estou doente, nem quero falar com você mais) ndash Dan Tao 22 de setembro 10 às 1:58 Henry: Eu não sei sobre AS3, mas um programador de Java tem coleções como CircularQueue em sua disposição (I39m não é um Desenvolvedor de Java, então eu tenho certeza de que há exemplos melhores lá fora, esse é o que eu encontrei a partir de uma busca rápida do Google), que implementa precisamente a funcionalidade em que estamos falando. Estou bastante confiante de que a maioria das linguagens de nível médio e baixo com bibliotecas padrão tem algo semelhante (por exemplo, no. NET there39s QueueltTgt). Enfim, eu também era filosofia. tudo é perdoado. Ndash Dan Tao 22 de setembro 10 às 12:44 Uma média móvel exponencialmente decadente pode ser calculada manualmente com apenas a tendência se você usar os valores apropriados. Veja quatromilab. chhackdiete4 para uma idéia sobre como fazer isso rapidamente com uma caneta e papel, se você estiver procurando uma média móvel suavemente exponencial com 10 suavização. Mas, como você tem um computador, você provavelmente deseja fazer mudanças binárias em oposição à mudança decimal). Desta forma, tudo que você precisa é uma variável para seu valor atual e outra para a média. A próxima média pode então ser calculada a partir disso. Respondeu 21 de setembro 10 às 14:39 há uma técnica chamada de portão de alcance que funciona bem com amostras espúrias de baixa ocorrência. Assumindo o uso de uma das técnicas de filtro mencionadas acima (média móvel, exponencial), uma vez que você tenha um histórico suficiente (uma Constante de Tempo), você pode testar a nova amostra de dados recebidos por razoabilidade, antes de ser adicionada à computação. É necessário algum conhecimento da taxa de mudança máxima razoável do sinal. A amostra bruta é comparada ao valor mais liso e se o valor absoluto dessa diferença é maior que o intervalo permitido, essa amostra é descartada (ou substituída por alguma heurística, por exemplo, uma previsão baseada no diferencial de inclinação ou na tendência Valor de previsão a partir de suavização exponencial dupla) respondeu Apr 30 16 às 6: 56Como outros já mencionaram, você deve considerar um filtro IIR (resposta de impulso infinito) em vez do filtro FIR (filtro de resposta finito) que você está usando agora. Há mais, mas à primeira vista os filtros FIR são implementados como convoluções explícitas e filtros IIR com equações. O filtro IIR particular que eu uso muito em microcontroladores é um filtro passa-baixa de um único pólo. Este é o equivalente digital de um simples filtro analógico R-C. Para a maioria dos aplicativos, estes terão melhores características do que o filtro de caixa que você está usando. A maioria dos usos de um filtro de caixa que eu encontrei são resultado de alguém que não presta atenção na classe de processamento de sinal digital, não como resultado de precisar de suas características particulares. Se você quiser apenas atenuar as altas freqüências que você conhece são ruim, um filtro passa-baixa de um único pólo é melhor. A melhor maneira de implementar um digitalmente em um microcontrolador é geralmente: FILT lt-- FILT FF (NEW-FILT) FILT é um pedaço de estado persistente. Esta é a única variável persistente que você precisa para calcular este filtro. NOVO é o novo valor que o filtro está sendo atualizado com esta iteração. FF é a fração do filtro. Que ajusta o peso do filtro. Olhe para este algoritmo e veja que para FF 0 o filtro é infinitamente pesado, já que a saída nunca muda. Para FF 1, realmente não há nenhum filtro, já que a saída apenas segue a entrada. Os valores úteis estão no meio. Em sistemas pequenos, você escolhe FF para ser 12 N, de modo que o multiplica por FF pode ser realizado como uma mudança direta por N bits. Por exemplo, FF pode ser 116 e multiplicar por FF, portanto, uma mudança direta de 4 bits. Caso contrário, este filtro precisa apenas de uma subtração e de um som, embora os números geralmente sejam mais amplos do que o valor de entrada (mais na precisão numérica em uma seção separada abaixo). Normalmente, tomo as leituras do AD significativamente mais rápidas do que são necessárias e aplico dois desses filtros em cascata. Este é o equivalente digital de dois filtros R-C em série e atenua 12 dBoctave acima da frequência de rolagem. No entanto, para as leituras de AD, geralmente é mais relevante olhar para o filtro no domínio do tempo, considerando sua resposta passo a passo. Isso indica o quão rápido o sistema verá uma mudança quando a coisa que você está medindo muda. Para facilitar a concepção desses filtros (o que significa apenas escolher FF e decidir quantos deles entrar em cascata), uso o meu programa FILTBITS. Você especifica o número de bits de mudança para cada FF na série de filtros em cascata, e ele calcula a resposta de passo e outros valores. Na verdade, eu costumo executar isso através do meu script wrapper PLOTFILT. Isso executa FILTBITS, que faz um arquivo CSV e, em seguida, traça o arquivo CSV. Por exemplo, aqui é o resultado do PLOTFILT 4 4: os dois parâmetros para PLOTFILT significam que haverá dois filtros em cascata do tipo descrito acima. Os valores de 4 indicam o número de bits de mudança para realizar o multiplicar pelo FF. Os dois valores FF são, portanto, 116 neste caso. O rastreamento vermelho é a resposta do passo da unidade, e é o principal aspecto a ser observado. Por exemplo, isso indica que, se a entrada muda instantaneamente, a saída do filtro combinado será fixada em 90 do novo valor em 60 iterações. Se você se preocupa com 95 horas de colonização, então você precisa esperar cerca de 73 iterações e por 50 horas de reposição apenas 26 iterações. O traço verde mostra a saída de um único pico de amplitude total. Isso dá uma idéia da supressão de ruído aleatória. Parece que nenhuma amostra única causará mais de 2,5 mudanças na saída. O traço azul é dar uma sensação subjetiva do que este filtro faz com o ruído branco. Este não é um teste rigoroso, uma vez que não há garantia de que exatamente o conteúdo era dos números aleatórios escolhidos como entrada de ruído branco para esta corrida de PLOTFILT. É só dar-lhe uma sensação áspera de quanto ele será esmagado e quão suave é. PLOTFILT, talvez FILTBITS, e muitas outras coisas úteis, especialmente para o desenvolvimento de firmware PIC, estão disponíveis na versão do software PIC Development Tools na minha página de downloads de software. Adicionado sobre a precisão numérica que vejo a partir dos comentários e agora uma nova resposta que tem interesse em discutir o número de bits necessários para implementar este filtro. Observe que o Multiply by FF criará novos bits do Log 2 (FF) abaixo do ponto binário. Em sistemas pequenos, FF é geralmente escolhido para ser 12 N, de modo que esse multiplicação seja efetivamente realizado por uma mudança direta de N bits. FILT é, portanto, geralmente um inteiro de ponto fixo. Observe que isso não altera nenhuma das matemáticas do ponto de vista dos processadores. Por exemplo, se você estiver filtrando as leituras de AD de 10 bit e N 4 (FF 116), então você precisa de 4 bits de fração abaixo das leituras de AD inteiras de 10 bits. A maioria dos processadores, você estará fazendo operações inteiras de 16 bits devido às leituras AD de 10 bits. Nesse caso, você ainda pode fazer exatamente as mesmas operações de inteiro de 16 bits, mas comece com as leituras de AD esquerda deslocadas em 4 bits. O processador não conhece a diferença e não precisa. Fazer matemática em inteiros inteiros de 16 bits funciona se você considera que eles são 12.4 pontos fixos ou verdadeiros inteiros de 16 bits (16.0 ponto fixo). Em geral, você precisa adicionar N bits cada pólo de filtro se você não deseja adicionar ruído devido à representação numérica. No exemplo acima, o segundo filtro de dois teria que ter 1044 18 bits para não perder informações. Na prática, em uma máquina de 8 bits que significa que você use valores de 24 bits. Tecnicamente, apenas o segundo pólo de dois precisaria do valor mais amplo, mas, para a simplicidade do firmware, costumo usar a mesma representação e, desse modo, o mesmo código para todos os pólos de um filtro. Geralmente eu escrevo uma sub-rotina ou macro para executar uma operação de polio de filtro, depois aplique isso a cada pólo. Se uma sub-rotina ou macro depende se os ciclos ou a memória do programa são mais importantes nesse projeto específico. De qualquer forma, eu uso algum estado de rascunho para passar NOVO no subroutinemacro, que atualiza FILT, mas também carrega isso no mesmo estado de rascunho NOVO estava dentro. Isso facilita a aplicação de vários pólos desde que o FILT atualizado de um pólo é o NOVO Do próximo. Quando uma sub-rotina, é útil ter um ponteiro apontar para FILT no caminho, que é atualizado logo após FILT no caminho de saída. Dessa forma, a sub-rotina atua automaticamente em filtros consecutivos na memória se for chamado várias vezes. Com uma macro, você não precisa de um ponteiro, pois você passa no endereço para operar em cada iteração. Exemplos de código Aqui está um exemplo de uma macro como descrito acima para um PIC 18: E aqui está uma macro semelhante para um PIC 24 ou dsPIC 30 ou 33: Ambos esses exemplos são implementados como macros usando o meu pré-processador PIC assembler. Que é mais capaz do que qualquer uma das instalações de macro incorporadas. Clabacchio: Outro problema que eu deveria ter mencionado é a implementação do firmware. Você pode escrever uma sub-rotina de filtro passa-baixa de um único pó uma vez, e depois aplicá-la várias vezes. Na verdade, geralmente escrevo uma sub-rotina para levar um ponteiro na memória para o estado do filtro, então, avance o ponteiro para que possa ser chamado sucessivamente de forma fácil para realizar filtros multipolar. Ndash Olin Lathrop 20 de abril 12 às 15:03 1. Muito obrigado por suas respostas - todos eles. Eu decidi usar este Filtro IIR, mas este Filtro não é usado como um Filtro LowPass Padrão, pois eu preciso usar os Valores de Contador médios e compará-los para detectar Mudanças em um determinado intervalo. Uma vez que estes valores são de dimensões muito diferentes dependendo do hardware que eu queria tomar uma média para poder reagir automaticamente a essas mudanças específicas de hardware. Ndash sensslen 21 de maio 12 às 12:06 Se você pode viver com a restrição de um poder de dois itens a média (ou seja, 2,4,8,16,32 etc.), então a divisão pode ser feita com facilidade e eficiência em uma Micro de baixo desempenho sem divisão dedicada porque pode ser feito como uma mudança de bit. Cada turno para a direita é um poder de dois, por exemplo: O OP pensou que ele tinha dois problemas, dividindo-se em um PIC16 e memória para o buffer de anel. Esta resposta mostra que a divisão não é difícil. É certo que não aborda o problema da memória, mas o sistema SE permite respostas parciais, e os usuários podem tirar algo de cada resposta por si mesmos, ou mesmo editar e combinar as respostas de outros. Uma vez que algumas das outras respostas exigem uma operação de divisão, elas são igualmente incompletas, uma vez que não mostram como conseguir isso eficientemente em um PIC16. Ndash Martin 20 de abril 12 às 13:01 Há uma resposta para um verdadeiro filtro de média móvel (aka filtro de caixa de depósito) com menos requisitos de memória, se você não se importa com o downsampling. É chamado de filtro integrador-pente em cascata (CIC). A idéia é que você tenha um integrador que você tome diferenças em um período de tempo, e o dispositivo chave de economia de memória é que, por downsampling, você não precisa armazenar todos os valores do integrador. Ele pode ser implementado usando o seguinte pseudocódigo: seu comprimento médio móvel efetivo é decimationFactorstatesize, mas você só precisa manter em torno de amostras estadisticas. Obviamente, você pode obter um melhor desempenho se o seu estadista e decimationFactor forem poderes de 2, de modo que os operadores de divisão e restante sejam substituídos por turnos e máscaras-es. Postscript: Eu concordo com a Olin que você sempre deve considerar filtros IIR simples antes de um filtro de média móvel. Se você não precisar da freqüência-nulos de um filtro de caixa, um filtro passa-baixa de 1 pólo ou 2 pólos provavelmente funcionará bem. Por outro lado, se você estiver filtrando para fins de decimação (tomando uma entrada de alta taxa de amostragem e avaliando-a para uso por um processo de baixa taxa), um filtro CIC pode ser exatamente o que você está procurando. (Especialmente se você pode usar statesize1 e evitar o buffer de toque completamente com apenas um único valor de integrador anterior) Há uma análise aprofundada da matemática por trás do uso do filtro IIR de primeira ordem que Olin Lathrop já descreveu na troca de pilha de processamento de sinal digital (Inclui muitas imagens bonitas.) A equação para este filtro IIR é: Isto pode ser implementado usando apenas números inteiros e sem divisão usando o seguinte código (pode precisar de alguma depuração como eu estava digitando de memória.) Este filtro se aproxima de uma média móvel de As últimas K amostras, definindo o valor de alfa para 1K. Faça isso no código anterior, definindo BITS para LOG2 (K), ou seja, para K 16, defina BITS para 4, para K 4, defina BITS para 2, etc. (Verifique o código listado aqui assim que eu receber uma mudança e Edite esta resposta, se necessário.) Respondeu 23 de junho 12 às 4:04 Heres um filtro passa-baixa de um único polo (média móvel, com freqüência de corte CutoffFrequency). Muito simples, muito rápido, funciona muito bem e quase sem memória. Nota: Todas as variáveis ​​têm um alcance além da função de filtro, exceto o passado em newInput Note: Este é um filtro de estágio único. Múltiplos estágios podem ser conectados em cascata para aumentar a nitidez do filtro. Se você usar mais de um estágio, você precisará ajustar o DecayFactor (como se relaciona com a frequência de corte) para compensar. E, obviamente, tudo que você precisa é que as duas linhas colocadas em qualquer lugar, eles não precisam de sua própria função. Este filtro possui um tempo de aceleração antes que a média móvel represente a do sinal de entrada. Se você precisar ignorar esse tempo de aceleração, basta inicializar o MovingAverage para o primeiro valor do newInput em vez de 0 e espero que o primeiro NewInput não seja um outlier. (CutoffFrequencySampleRate) tem um intervalo entre 0 e 0,5. DecayFactor é um valor entre 0 e 1, geralmente perto de 1. Os flutuadores de precisão única são bons o suficiente para a maioria das coisas, eu apenas prefiro duplas. Se você precisa ficar com números inteiros, você pode converter DecayFactor e Factor de amplitude em inteiros fracionários, nos quais o numerador é armazenado como inteiro e o denominador é uma potência inteira de 2 (para que você possa mudar de bit para a direita como o Denominador em vez de ter que dividir durante o ciclo do filtro). Por exemplo, se DecayFactor 0.99 e você deseja usar números inteiros, você pode definir o DecayFactor 0.99 65536 64881. E então, sempre que você se multiplicar pelo DecayFactor no loop do filtro, basta mudar o resultado 16. Para obter mais informações sobre isso, um excelente livro é esse Online, capítulo 19 em filtros recursivos: dspguidech19.htm PS Para o paradigma da Média em Movimento, uma abordagem diferente para definir DecayFactor e AmplitudeFactor que pode ser mais relevante para suas necessidades, digamos que você quer o anterior, cerca de 6 itens em média juntos, fazendo isso discretamente, você adicionará 6 itens e dividirá por 6, então Você pode configurar o AmplitudeFactor para 16, e DecayFactor para (1.0 - AmplitudeFactor). Respondeu 12 de maio 12 às 22:55 Todos os outros comentaram detalhadamente sobre a utilidade do IIR vs. FIR e sobre a divisão de poder de dois. Eu gostaria de dar alguns detalhes de implementação. O abaixo funciona bem em pequenos microcontroladores sem FPU. Não há multiplicação, e se você mantém N um poder de dois, toda a divisão é de um único ciclo de mudança de bits. Tampão de anel FIR básico: mantenha um buffer de execução dos últimos valores de N e uma SOM em execução de todos os valores no buffer. Cada vez que uma nova amostra vem, subtrair o valor mais antigo no buffer de SUM, substituí-lo pela nova amostra, adicionar a nova amostra a SUM e SOMN de saída. Tampão de anel IIR modificado: mantenha uma SOM executória dos últimos valores de N. Cada vez que uma nova amostra vem, SUM - SUMN, adicione a nova amostra e saia SUMN. Respondeu 28 de agosto 13 às 13:45 Se eu tiver lido você direito, você descreve um filtro IIR de primeiro ordem, o valor que você está subtraindo não é o valor mais antigo que está caindo, mas sim a média dos valores anteriores. Os filtros IIR de primeiro orden certamente podem ser úteis, mas eu não tenho certeza do que você quer dizer quando você sugere que a saída seja a mesma para todos os sinais periódicos. A uma taxa de amostragem de 10KHz, a alimentação de uma onda quadrada de 100Hz em um filtro de caixa de 20 estágios produzirá um sinal que sobe uniformemente para 20 amostras, fica alto por 30, cai uniformemente para 20 amostras e fica com baixo para 30. Uma ordem de primeira ordem Filtro IIR. Ndash supercat 28 de agosto 13 às 15:31 renderá uma onda que começa a subir bruscamente e gradualmente se nivela perto (mas não em) o máximo de entrada, então começa a cair bruscamente e gradualmente nivela perto (mas não at) o mínimo de entrada. Comportamento muito diferente. Ndash supercat 28 de agosto 13 às 15:32 Uma questão é que uma média móvel simples pode ou não ser útil. Com um filtro IIR, você pode obter um bom filtro com relativamente poucos calcs. O FIR que você descreve só pode dar-lhe um retângulo no tempo - um sinc na freq - e você pode gerenciar os lobos laterais. Pode valer a pena lançar alguns números inteiros para tornar uma boa FIR sintonizada simétrica se você pode poupar os tiques do relógio. Ndash Scott Seidman 29 de agosto 13 às 13:50 ScottSeidman: Não há necessidade de se multiplicar se um simplesmente tiver cada estágio da FIR ou produzir a média da entrada para esse estágio e seu valor armazenado anterior, e depois armazenar a entrada (se tiver O intervalo numérico, pode-se usar a soma em vez da média). Se isso é melhor do que um filtro de caixa depende do aplicativo (a resposta de passo de um filtro de caixa com um atraso total de 1 ms, por exemplo, terá um pico d2dt desagradável quando a entrada muda, e novamente 1 ms depois, mas terá o mínimo Possível ddt para um filtro com um atraso total de 1ms). Ndash supercat 29 de agosto às 15:25 Como disse mikeselectricstuff, se você realmente precisa reduzir suas necessidades de memória e você não se importa que sua resposta de impulso seja exponencial (em vez de um pulso retangular), eu iria por um filtro exponencial de média móvel . Eu os uso extensivamente. Com esse tipo de filtro, você não precisa de nenhum buffer. Você não precisa armazenar N amostras passadas. Apenas um. Então, seus requisitos de memória são reduzidos por um fator de N. Além disso, você não precisa de nenhuma divisão para isso. Somente multiplicações. Se você tem acesso à aritmética de ponto flutuante, use as multiplicações de ponto flutuante. Caso contrário, faça multiplicações inteiras e mude para a direita. No entanto, estamos em 2012 e eu recomendaria que você usasse compiladores (e MCUs) que permitem que você trabalhe com números de ponto flutuante. Além de ser mais eficiente e mais eficiente em memória (você não precisa atualizar itens em qualquer buffer circular), eu diria que também é mais natural. Porque uma resposta exponencial de impulso corresponde melhor à maneira como a natureza se comporta, na maioria dos casos. Respondeu 20 de abril 12 às 9:59 Um problema com o filtro IIR como quase tocado por olin e supercat, mas aparentemente desconsiderado por outros é que o arredondamento apresenta alguma imprecisão (e potencialmente biastruncação). Assumindo que N é um poder de dois, e apenas uma aritmética inteira é usada, a direita de mudança elimina sistematicamente os LSBs da nova amostra. Isso significa que, quanto tempo a série possa ser, a média nunca levará em consideração essa série. Por exemplo, suponha uma série que diminua lentamente (8,8,8. 8,7,7,7. 7,6,6) e assume que a média é de fato 8 no início. A amostra do punho 7 trará a média para 7, independentemente da força do filtro. Apenas para uma amostra. A mesma história para 6, etc. Agora pense no contrário. A série sobe. A média permanecerá em 7 para sempre, até que a amostra seja grande o suficiente para fazê-la mudar. Claro, você pode corrigir o viés, adicionando 12N2, mas isso realmente não resolverá o problema de precisão. Nesse caso a série decrescente permanecerá para sempre em 8 até a amostra ser 8-12 (N2). Para N4, por exemplo, qualquer amostra acima de zero manterá a média inalterada. Eu acredito que uma solução para isso implicaria manter um acumulador de LSBs perdidos. Mas eu não consegui o suficiente para ter o código pronto, e não tenho certeza de que isso não prejudicaria o poder do IIR em alguns outros casos de séries (por exemplo, se 7,9,7,9 seria médio para 8). Olin, sua cascata de dois estágios também precisaria de alguma explicação. Você quer dizer segurar dois valores médios com o resultado do primeiro alimentado no segundo em cada iteração. Qual é o benefício disso

No comments:

Post a Comment