Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Manufacturing Technology >> Processo de manufatura

EasyFFT:Fast Fourier Transform (FFT) para Arduino

Componentes e suprimentos

Arduino Nano R3
× 1

Aplicativos e serviços online

Arduino IDE

Sobre este projeto




A medição da frequência do sinal capturado pode ser uma tarefa difícil, especialmente no Arduino, pois tem menor poder computacional. Existem métodos disponíveis para capturar o cruzamento de zero, onde a frequência é capturada, verificando quantas vezes o sinal cruza as linhas de zero dentro do tempo determinado. Esse método pode não funcionar quando o sinal é uma combinação de várias frequências.

Isso é de alguma forma difícil de codificar se você não tiver esse histórico. Mas sendo um remendador, este código pode ser muito útil para vários projetos relacionados à música, análise de sinais. O motivo deste projeto foi preparar um código que seja fácil de implementar no Arduino sem entrar em seus antecedentes.

Este projeto não explica o funcionamento da FFT, mas explica a aplicação da função FFT. O mesmo processo também é explicado no vídeo anexo.

Se você está interessado apenas na aplicação do código e não em uma explicação sobre ele. Você pode pular diretamente para a etapa 3.



Se você precisa executar FFT com alta velocidade (3x) com pequeno comprometimento na precisão (cerca de 5%), consulte meu outro artigo sobre ApproxFFT.

https://create.arduino.cc/projecthub/abhilashpatel121/approxfft-fastest-fft-function-for-arduino-fd4917?ref=user&ref_id=1593632&offset=0






Etapa 1:Transformação Rápida de Fourier


Para tornar o cálculo do DFT mais rápido, o algoritmo FFT foi desenvolvido por James Cooley e John Tukey. Este algoritmo também é considerado um dos algoritmos mais importantes do século XX. Ele divide um sinal em uma parte de sequência ímpar e par, o que reduz o número de cálculos necessários. Ao usá-lo, a multiplicação complexa total necessária pode ser reduzida a NlogN. o que é uma melhoria significativa. DFT típico leva N * N multiplicação complexa para resultados, enquanto FFT leva apenas N * logN. esta é uma vantagem significativa quando os números da amostra são altos.

Você pode consultar as referências abaixo que me referi ao escrever o código para uma compreensão detalhada da matemática por trás da FFT:

1. https://flylib.com/books/en/2.729.1/derivation_of _...

2. https://jakevdp.github.io/blog/2013/08/28/understa ...

3. https://cnx.org/contents/[email protected]:zmcmahhR @ 7 / D ...

4. https://en.wikipedia.org/wiki/Fast_Fourier_transfo ...





Etapa 2:Explicação do código


1. Seno e cosseno rápidos:

O cálculo FFT leva o valor de vários seno e cosseno várias vezes. A função embutida do Arduino não é rápida o suficiente e leva muito tempo para fornecer o valor necessário. O que torna o código significativamente mais lento (dobra o tempo para 64 amostras). Para neutralizar esse valor de emissão de seno de 0 a 90 graus, é armazenado como múltiplo de 255. Fazer isso eliminará a necessidade de armazenar números como flutuante e podemos armazená-lo como byte, que ocupa 1/4 de espaço no Arduino. O sine_data [] precisa ser colado no topo do código para declará-lo como uma variável global.

Além de sine_data, uma matriz chamada f_peaks [] declarada como uma variável global . Após cada execução da função FFT, este array é atualizado. Onde f_peaks [0] é a frequência mais dominante e outros valores em ordem decrescente.
  byte sine_data [91] ={0, 4, 9, 13, 18, 22, 27, 31, 35, 40, 44, 49, 53, 57, 62, 66, 70, 75, 79 , 83, 87, 91, 96, 100, 104, 108, 112, 116, 120, 124, 127, 131, 135, 139, 143, 146, 150, 153, 157, 160, 164, 167, 171, 174 , 177, 180, 183, 186, 189, 192, 195, 198, 201, 204, 206, 209, 211, 214, 216, 219, 221, 223, 225, 227, 229, 231, 233, 235, 236 , 238, 240, 241, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 253, 254, 254, 254, 255, 255, 255, 255, 255}; flutuar f_peaks [5 ];  

Como armazenamos o valor de seno de 0 a 90 graus, qualquer valor de seno ou cosseno pode ser calculado. Abaixo da função a primeira rodada do número para a casa decimal zero e o valor de retorno dos dados armazenados. este método precisa de apenas uma divisão flutuante. Isso pode ser reduzido ainda mais armazenando diretamente os valores do seno (não o múltiplo de 255). mas isso consome muita memória no Arduino.

Usar o procedimento acima reduz a precisão, mas melhora a velocidade. Para 64 pontos dá uma vantagem de 8ms e para 128 pontos dá uma vantagem de 20ms.





Etapa 3:Explicação do código:Função FFT


A FFT só pode ser realizada para o tamanho da amostra de 2, 4, 8, 16, 32, 64 e assim por diante. se o valor não for 2 ^ n, ele assumirá o lado inferior do valor. Por exemplo, se escolhermos o tamanho da amostra de 70, ele irá considerar apenas as primeiras 64 amostras e omitir o resto.

É sempre recomendado ter um tamanho de amostra de 2 ^ n. que pode ser:

2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, ...

Dois flutuadores out_r e out_im ocuparão uma grande quantidade de memória. para Arduino nano não funcionará para amostras superiores a 128 (e em alguns casos 128) devido à falta de memória disponível.
  dados int não assinados [13] ={1,2,4,8,16,32,64,128,256,512,1024,2048}; int a, c1, f, o, x; a =N; for (int i =0; i <12; i ++) // calculando os níveis {if (data [i] <=a) {o =i;}} int in_ps [data [o]] ={}; // entrada para sequencingfloat out_r [data [o]] ={}; // parte real de transformfloat out_im [data [o]] ={}; // parte da imaginação da transformação  

O fluxo adicional é o seguinte:

1. O código gera um bit invertido na ordem para o tamanho de amostra fornecido (detalhes sobre a reversão do bit nas referências:etapa 2)

2. Dados de entrada ordenados de acordo com o pedido gerado,

3. FFT realizada

4. A amplitude do número complexo calculado,

5. Os picos são detectados e ordenados em ordem decrescente

6. os resultados podem ser acessados ​​em f_peaks [].

[para acessar outros dados (além da frequência de pico), o código deve ser modificado, de modo que a variável local possa ser copiada para alguma variável global predefinida]





Etapa 4:Teste do código


Uma amostra de onda de triângulo é fornecida como entrada. para esta onda, a frequência de amostragem é 10 Hz e a frequência da própria onda é 1,25 Hz.

Como pode ser mostrado na saída bruta, o valor é compatível com o FFT calculado pelo Scilab. no entanto, esses valores não são exatamente os mesmos que temos baixa precisão, mas onda senoidal mais rápida.

Na frequência de saída, a frequência da matriz é 1,25 e 3,75. não é necessário obter o valor exato todas as vezes. normalmente, esses números são chamados de compartimentos de frequência. portanto, o valor de saída pode estar em qualquer lugar dentro das caixas especificadas.

Velocidade:

para Arduino nano é preciso:
  • 16 pontos:4ms
  • 32 pontos:10 ms
  • 64 pontos:26 ms
  • 128 pontos:53ms





Etapa 5:Conclusão


Este código FFT pode ser usado em aplicativos em tempo real. Uma vez que leva cerca de 30 ms para completar o cálculo. No entanto, sua resolução é limitada por um número de amostras. O número da amostra é limitado pela memória do Arduino. Usando o Arduino Mega ou outra placa de maior desempenho, a precisão pode ser melhorada.

Se você tiver alguma dúvida, sugestão ou correção, sinta-se à vontade para comentar.

Código

  • EasyFFT
EasyFFT Arduino
Este código executa FFT e atualiza a matriz F_peasks com as 5 frequências mais dominantes.
 / * // Exemplo de dados:dados internos [64] ={14, 30, 35, 34, 34, 40, 46, 45, 30 , 4, -26, -48, -55, -49, -37, -28, -24, -22, -13, 6, 32, 55, 65, 57, 38, 17, 1, -6, - 11, -19, -34, -51, -61, -56, -35, -7, 18, 32, 35, 34, 35, 41, 46, 43, 26, -2, -31, -50, -55, -47, -35, -27, -24, -21, -10, 11, 37, 58, 64, 55, 34, 13, -1, -7}; * /// ---- -------------------------------------------------- --------------------- // byte sine_data [91] ={0, 4, 9, 13, 18, 22, 27, 31, 35, 40, 44, 49, 53, 57, 62, 66, 70, 75, 79, 83, 87, 91, 96, 100, 104, 108, 112, 116, 120, 124, 127, 131, 135, 139, 143, 146, 150, 153, 157, 160, 164, 167, 171, 174, 177, 180, 183, 186, 189, 192, 195, // Cole no início do programa 198, 201, 204, 206, 209, 211 , 214, 216, 219, 221, 223, 225, 227, 229, 231, 233, 235, 236, 238, 240, 241, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252 , 253, 253, 254, 254, 254, 255, 255, 255, 255}; float f_peaks [5]; // 5 principais picos de frequências em ordem decrescente // --------------------------------------- ------------------------------------ // void setup () {Serial.begin (250000); } void loop () {/ * // exampleFFT (dados, 64.100); // para obter os cinco principais valores de frequências de X com 64 amostras em 100 Hz samplingSerial.println (f_peaks [0]); Serial.println (f_peaks [1]); delay (99999); * // * após ruir acima de FFT ( ), frequências disponíveis em f_peaks [0], f_peaks [1], f_peaks [2], f_peaks [3], f_peaks [4], * /} // --------------- -------------- Função FFT ---------------------------------- ------------ // float FFT (int in [], int N, float Frequency) {/ * Código para executar FFT no arduino, setup:paste sine_data [91] no topo do programa [ variável global], cole a função FFT no final do programTerm:1. in []:Matriz de dados, 2. N:Número da amostra (tamanho de amostra recomendado 2,4,8,16,32,64,128 ...) 3. Frequência:frequência de amostragem necessária como entrada (Hz) Se o tamanho da amostra não estiver na potência de 2, ela será cortada para o lado inferior do número. ou seja, para 150 números de amostras, o código irá considerar a primeira 128 amostra, a amostra restante será omitida. Para Arduino nano, FFT de mais de 128 amostras não é possível devido à limitação mamory (64 recomendado) Para maior número de amostra pode surgir relacionado a Mamory emissão, Código por ABHILASHContato:[email protected] Documentação:https://www.instructables.com/member/abhilash_patel/instructables/2/3/2021:alterar o tipo de dados N de float para int para> =256 amostras * / dados int sem sinal [13] ={1,2,4,8,16,32,64,128,256,512,1024,2048}; int a, c1, f, o, x; a =N; for (int i =0; i <12; i ++) // calculando os níveis {if (data [i] <=a) {o =i;}} int in_ps [data [o]] ={}; // entrada para sequencingfloat out_r [data [o]] ={}; // parte real de transformfloat out_im [data [o]] ={}; // parte da imaginação da transformação x =0; para (int b =0; b  a) {out_r [i] =in [in_ps [i] -a];}} int i10, i11, n1; float e, c, s, tr, ti; para (int i =0; i  aqui em diante out_r contém amplitude e our_in conecta a frequência (Hz) para (int i =0; i  out_r [i-1] &&out_r [i]> out_r [i + 1] ) {in_ps [x] =i; // array in_ps usado para armazenamento do número de pico x =x + 1;}} s =0; c =0; for (int i =0; i  360) {j =j-360;} if (j> -1 &&j <91) {out =sine_data [j];} else if (j> 90 &&j <181) {out =sine_data [180-j];} else if (j> 180 &&j <271) {out =-sine_data [j-180];} else if (j> 270 &&j <361) {out =-sine_data [360-j];} return (out / 255);} float cosseno (int i) {int j =i; flutuar; while (j <0) {j =j + 360;} while (j> 360) {j =j-360;} if (j> -1 &&j <91) {out =sine_data [90-j];} else if (j> 90 &&j <181) {out =-sine_data [j-90];} else if (j> 180 &&j <271) {out =-sine_data [270-j];} else if (j> 270 &&j <361) {out =sine_data [j-270];} return (out / 255);} // ---------------------- -------------------------------------------------- ------------ // 

Esquemas


Processo de manufatura

  1. O que é a transformada de Fourier?
  2. Decodificador DTMF usando apenas Arduino
  3. Sistema de alarme Arduino:SERENA
  4. Comunicação Python3 e Arduino
  5. Monitoramento de temperatura SMART para escolas
  6. Biblioteca de portas IO de 8 bits para Arduino
  7. Matriz de teclado de prototipagem de 64 teclas para Arduino
  8. Uma entrada analógica isolada para Arduino
  9. Robô para navegação interna supercool
  10. O que é o código HS para bomba hidráulica?