Быстрое преобразование Фурье fft для DUE

saer
Offline
Зарегистрирован: 12.05.2014

Добрый!

Залип на вопросе ФФТ.

Пытаюсь снять с аналогового входа сигнал и пропустить его чз ФФТ.

Вроде даже есть библиотека здесь: http://forum.arduino.cc/index.php?topic=225204.0  - библиотека не включается из-за ошибки в ней

Есть вот: https://coolarduino.wordpress.com/2014/03/11/fft-library-for-arduino-due-sam3x-cpu/ - включилась. Но при попытке достучаться - молчит.

Кто-нить знает про работающее ФФТ для DUE?

Logik
Offline
Зарегистрирован: 05.08.2014

Да, оно бывает работающее. Я знаю, точно бывает, сам видел. Только не такое уж и быстрое оно. Писать долго, работает медленно т.к. много умножений. 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Logik пишет:

не такое уж и быстрое

Попытайтесь сделать простое FT на выборке в 32768 отсчетов и сравните в FFT. Тогда сразу поймете, где быстрое, а где - нет.

Logik
Offline
Зарегистрирован: 05.08.2014

andriano пишет:

Logik пишет:

не такое уж и быстрое

Попытайтесь сделать простое FT на выборке в 32768 отсчетов и сравните в FFT. Тогда сразу поймете, где быстрое, а где - нет.

Если FT на DSP а FFT на ардуине, то пойму только что задача не по камню.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Logik пишет:

Если FT на DSP а FFT на ардуине, то пойму только что задача не по камню.

Простого FT на DSP не бывает. Там только FFT. По понятным причинам: в приведденном мною примере FFT - это порядка полумиллиона операций, а простое FT - более миллиарда.

saer
Offline
Зарегистрирован: 12.05.2014

Согласен, но при всем том - есть примеры БЫСТРО работающего ФФТ : http://arduino.ru/projects/analizator-spektra-zvuka-na-arduino

На AVR - платах это работает.

На ARM - запустить не удалось. Может нужно код в "чистом " С писать  или еще что-то - я не знаю.

Кто-нить видел живую библиотеку FFT для DUE?

 

MagicianT
Offline
Зарегистрирован: 03.10.2015

saer пишет:

Есть вот: https://coolarduino.wordpress.com/2014/03/11/fft-library-for-arduino-due-sam3x-cpu/ - включилась. Но при попытке достучаться - молчит.

Kak eto molchit, tam zhe primer est' chtob cherez serial printovat'. Biblioteka, kstati na C. 

dezz0riented
dezz0riented аватар
Offline
Зарегистрирован: 27.07.2014

saer пишет:

Согласен, но при всем том - есть примеры БЫСТРО работающего ФФТ : http://arduino.ru/projects/analizator-spektra-zvuka-na-arduino

Кстати о том примере. Библиотека не встанет на новые версии IDE. Была ситуация, после меня проектец один потрошили и удивлялись, я-то его на 1.0.4 делал :)

diakin
diakin аватар
Offline
Зарегистрирован: 04.06.2016

Сайт  https://coolarduino.wordpress.com/2014/03/11/fft-library-for-arduino-due-sam3x-cpu/     приказал долго жить.
Есть какая-нибудь FFT библиотека, компилящаяся под DUE? Какие-то нашел, но с ними примеры не компилятся.

 

diakin
diakin аватар
Offline
Зарегистрирован: 04.06.2016

Вот допилил как-то, но не компилится - выдает ошибку.

Arduino: 1.6.0 (Windows XP), Плата"Arduino Due (Programming Port)"

Error while uploading: missing 'recipe.S.o.pattern' configuration parameter

/*
This Example acquire analog signal from A0 of Arduino, and Serial out to Processing application to visualize.
Tested with preamplified audio data. Take a look at http://www.youtube.com/watch?v=drYWullBWcI

Analog signal is captured at 9.6 KHz, 64 spectrum bands each 150Hz which can be change from adcInit()
Load the this file to Arduio, run Processing application.

Original Fixed point FFT library is from ELM Chan, http://elm-chan.org/works/akilcd/report_e.html
Ported to the library and demo codes are from AMurchick http://arduino.cc/forum/index.php/topic,37751.0.html
Processing code is from boolscott http://boolscott.wordpress.com/2010/02/04/arduino-processing-analogue-ba...
*/


#include <stdint.h>
#include <ffft.h>
//#include <FFT.h>


#define  IR_AUDIO  0 // ADC channel to capture
#define FFT_N 1024
#define NumPoint FFT_N

int16_t capture[FFT_N];			/* Wave captureing buffer */
complex_t bfly_buff[FFT_N];		/* FFT buffer */
uint16_t spektrum[FFT_N / 2];		/* Spectrum output buffer */

void setup()
{
  Serial.begin(57600);
}

void loop()
{
  unsigned long timeB, timeE;
  float timeIZMsec;
  
  timeB = micros();
  for (int i = 0; i < NumPoint; i++)
  {
    capture[i] = analogRead(A0); //(30*sin(100*Tsample*i+3.14159*0)-0) ; // analogRead(A0) ; // 1023/5=204,6 на 1 вольт  /Kus1
    delayMicroseconds(125);        // pauses for 50 microseconds
  }
  timeE = micros(); //12,3 мкс на отсчет = 80 кгц частота дискретизации
  //Serial.println("----------------")  ;
  timeIZMsec = float(timeE - timeB) / 1000000;

  fft_input(capture, bfly_buff);
  fft_execute(bfly_buff);
  fft_output(bfly_buff, spektrum);

}

 

MagicianT
Offline
Зарегистрирован: 03.10.2015

Попробуй скачать здесь:   https://cloud.mail.ru/public/FtFv/WorrYQnFB

Отпишись если чё не так потом.

diakin
diakin аватар
Offline
Зарегистрирован: 04.06.2016

А все работает  )
Пример для Ардуины Due
Время измерения подобрано 1 сек. (5 мкс на analogRead(A0) + 483 мкс задержка между отсчетами.
Получается 2048*0.488 мс=1 сек.
Вход ловит наводку 50 Гц, для длительности 1 сек это 50-я гармоника.
Что и видно в мониторе - начиная с 0 гармоники (1007 ступенек АЦП) и максимум на 50 гармонике - 363 ступеньки. (Ну это на моей плате с проводками на входах )

Ура! ))
Большое спасибо!

/*
This Example acquire analog signal from A0 of Arduino? make FFT and show result //via Serial out.
*/

#include <UTFT.h>
#include <SplitRadixRealP.h>
// FFT_SIZE IS DEFINED in Header file Radix4.h 
// #define   FFT_SIZE           2048

#define   MIRROR         FFT_SIZE / 2
#define   INP_BUFF       FFT_SIZE 
         
int         f_r[FFT_SIZE]   = { 0};
int         out1[MIRROR]    = { 0};     // Magnitudes
int         out2[MIRROR]    = { 0};     // Magnitudes

const       int         dc_offset       = 1023; 

unsigned long time_start;
unsigned int  time_hamng, time_revbn, time_radix, time_gainr, time_sqrtl, time_sqrtl2;
                 
SplitRadixRealP     radix;

#define FFT_N FFT_SIZE
#define NumPoint FFT_N

void setup()
{
  Serial.begin(57600);
}

void loop()
{
  unsigned long timeB, timeE;
  float timeIZMsec;
  
  timeB = micros();
  for (int i = 0; i < NumPoint; i++)
  {
    f_r[i] = analogRead(A0); //(30*sin(100*Tsample*i+3.14159*0)-0) ; // analogRead(A0) ; // 1023/5=204,6 на 1 вольт  /Kus1
    delayMicroseconds(483);        // pauses for 50 microseconds
  }
  timeE = micros(); //12,3 мкс на отсчет = 80 кгц частота дискретизации
  //Serial.println("----------------")  ;
  timeIZMsec = float(timeE - timeB) / 1000000;

   time_start = micros();
   radix.rev_bin( f_r, FFT_SIZE);
   time_revbn  = micros() - time_start;

   time_start = micros();
   radix.fft_split_radix_real( f_r, LOG2_FFT);
   time_radix  = micros() - time_start;

   time_start = micros();
   radix.gain_Reset( f_r, LOG2_FFT -1); 
   time_gainr  = micros() - time_start;

   time_start = micros();
   radix.get_Magnit1( f_r, out1);
   time_sqrtl  = micros() - time_start;

   time_start = micros();
   radix.get_Magnit2( f_r, out2);
   time_sqrtl2  = micros() - time_start;
   
            Serial.print("timeIZMsec="+String(timeIZMsec)+" "+"\n\tMagnitudes: ");    
            prnt_out2( out1, MIRROR);
//            prnt_out2( out2, MIRROR);
   

}

void prnt_out2( int *array, int dlina) 
{
  Serial.print("\n\t");      
     for ( uint32_t i = 0; i < dlina; i++)
     {
       Serial.print(String(array[i]));       
       Serial.print("\t");    
       if ((i+1)%16 == 0) Serial.print("\n\t");
     }
  Serial.println("\n\t");
}


 

MagicianT
Offline
Зарегистрирован: 03.10.2015

Рад за вас. Но в оригинале частота сэмплирования задаётся просто

 
#define   SMP_RATE          48000UL 

т.е. поменять на 

#define   SMP_RATE         2048UL 
надо было, и всё. 
А чтобы небыло постоянки в 0-м бине, надо два одинаковых резистора по 100к или около того соединить
 +3.3 /\/\/\/\/\- analog-/\/\/\/\/\ - GND. 
                          |
                         --+
                         --
                          |
 
Сигнал потом подавать через конденсатор, 1-10 мкФ, если электролит то плюсом на ардуино вход
diakin
diakin аватар
Offline
Зарегистрирован: 04.06.2016

Немножко врет однако.

 float Tsample = 3.14159 * 2 / NumPoint;
f_r[i] = (10*sin(100*Tsample*i+3.14159*0)-15) ;

В спектре должны быть 100-я гармоника амплитудой 10 и нулевая амплитудой 15

Показывает нулевую ампл. -29 и сотую ампл. 9

зы. Ну хотя

int         f_r[FFT_SIZE]   = {     0};

зызы

f_r[i] = (1400*sin(100*Tsample*i+3.14159*1)-1500) ;

ахаха..
Magnitudes:
 0      -2998 
 100    1399
 

f_r[i] = (-1500) ; // 1400*sin(100*Tsample*i+3.14159*1) analogRead(A0); 

0      -2999

 

 

MagicianT
Offline
Зарегистрирован: 03.10.2015

Ясен пень, там же целочисленная математика, ошибки округления. Магнитуда 10 от 2047 всего 0.488%. 

Не нравится, ищите неадаптированный код с плавающей запятой, на ардуино без fCPU раз в 100 медленее считать будет. 
diakin
diakin аватар
Offline
Зарегистрирован: 04.06.2016

На due в 20 раз медленнее.
Кстати есть целочисленные библиотеки, где входные данные с плавающей точкой.

Там типа

 /*  Float -> int convertion.
 */
 int fix ( int *pz, int n )
 {
	int i, x, emax ;
	unsigned int sx, y ;
	register unsigned int ax, e ;
	int *px, *pxx ;

	px = pz + 1 ;
	emax = 0 ;
	for ( i = 0 ; i < n ; i++ )  /* search for max exponent */
	{                                                               
	  e = *px & 0X7F80 ;
	  if ( e > emax ) emax = e ;
	  px += 2 ;
	} ;
	emax >>= 7 ;
	px = pxx = pz ;
	for ( i=0 ; i<n ; i++ )
	{
	  x = *pxx ; y = *( pxx + 1 ) ;
	  ax = ((( y << 7 ) | 0X4000 ) & 0X7FFF ) | (( x >> 9 ) & 0X7F ) ;
	  sx = y & 0X8000 ;
	  e = emax - (( y & 0X7F80 ) >> 7 ) ;
	  x = e < 15 ? ax >> e : 0 ;
	  *px = sx ? -x : x ;
	  px++ ; pxx += 2 ;
	} ;
	return ( emax ) ;
 }

и обратное

diakin
diakin аватар
Offline
Зарегистрирован: 04.06.2016

Это скетч FFT с плавающей точкой

/*
This Example acquire analog signal from A0 of Arduino? make FFT and show result //via Serial out.
*/

#include <UTFT.h>
//********************** FFT ********************************************************
// https://ru.wikibooks.org/wiki/%D0%A0%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0...
// AVal - массив анализируемых данных, Nvl - длина массива должна быть кратна степени 2.
// FTvl - массив полученных значений, Nft - длина массива должна быть равна Nvl.

const double TwoPi = 6.283185307179586;

//void FFTAnalysis(double *AVal, double *FTvl, int Nvl, int Nft)
void FFTAnalysis(float AVal[], float FTvl[], int Nvl, int Nft)
{
  int i, j, n, m, Mmax, Istp;
  double Tmpr, Tmpi, Wtmp, Theta;
  double Wpr, Wpi, Wr, Wi;
  double *Tmvl;

  n = Nvl * 2; Tmvl = new double[n];

  for (i = 0; i < n; i += 2) 
  {
    Tmvl[i] = 0;
    Tmvl[i + 1] = AVal[i / 2];
  }

  i = 1; j = 1;
  while (i < n) 
  {
    if (j > i) 
    {
      Tmpr = Tmvl[i]; Tmvl[i] = Tmvl[j]; Tmvl[j] = Tmpr;
      Tmpr = Tmvl[i + 1]; Tmvl[i + 1] = Tmvl[j + 1]; Tmvl[j + 1] = Tmpr;
    }
    i = i + 2; m = Nvl;
    while ((m >= 2) && (j > m)) 
    {
      j = j - m; m = m >> 1;
    }
    j = j + m;
  }

  Mmax = 2;
  while (n > Mmax) 
  {
    Theta = -TwoPi / Mmax; Wpi = sin(Theta);
    Wtmp = sin(Theta / 2); Wpr = Wtmp * Wtmp * 2;
    Istp = Mmax * 2; Wr = 1; Wi = 0; m = 1;

    while (m < Mmax) 
    {
      i = m; m = m + 2; Tmpr = Wr; Tmpi = Wi;
      Wr = Wr - Tmpr * Wpr - Tmpi * Wpi;
      Wi = Wi + Tmpr * Wpi - Tmpi * Wpr;

      while (i < n) 
      {
        j = i + Mmax;
        Tmpr = Wr * Tmvl[j] - Wi * Tmvl[j - 1];
        Tmpi = Wi * Tmvl[j] + Wr * Tmvl[j - 1];

        Tmvl[j] = Tmvl[i] - Tmpr; Tmvl[j - 1] = Tmvl[i - 1] - Tmpi;
        Tmvl[i] = Tmvl[i] + Tmpr; Tmvl[i - 1] = Tmvl[i - 1] + Tmpi;
        i = i + Istp;
      }
    }

    Mmax = Istp;
  }

  for (i = 0; i < Nft; i++) 
  {
    j = i * 2; FTvl[i] = 2 * sqrt(pow(Tmvl[j], 2) + pow(Tmvl[j + 1], 2)) / Nvl;
  }

  delete []Tmvl;
}
/////////////////////////////////////////////////////////////////////////////////
#define   FFT_SIZE           2048
#define   MIRROR         FFT_SIZE / 2
#define   INP_BUFF       FFT_SIZE

float         f_r[FFT_SIZE]   = { 0};
float         out1[MIRROR]   = { 0};
const  int    dc_offset       = 1023;
unsigned long time_start;

#define FFT_N FFT_SIZE
#define NumPoint FFT_N

void setup()

{
  Serial.begin(57600);
}


void loop()
{
  unsigned long timeB, timeE,time_revbn;
  float timeIZMsec;
  float Tsample = 3.14159 * 2 / NumPoint;

  timeB = micros();
  for (int i = 0; i < NumPoint; i++)
  {
    f_r[i] =  140*sin(100*Tsample*i+3.14159*1)+0.123456789*sin(2*Tsample*i); // analogRead(A0); //analogRead(A0) ; // 1023/5=204,6 на 1 вольт  /Kus1
    delayMicroseconds(483);        // pauses for 50 microseconds
  }

  timeE = micros(); //12,3 мкс на отсчет = 80 кгц частота дискретизации
  //Serial.println("----------------")  ;
  timeIZMsec = float(timeE - timeB) / 1000000;

  time_start = micros();
FFTAnalysis(f_r, out1,NumPoint , NumPoint/2);
  time_revbn  = micros() - time_start;

  Serial.print("timeIZMsec=" + String(timeIZMsec) + " time_revbn="+ String(time_revbn) + "\n\tMagnitudes: ");
  prnt_out2( out1, MIRROR);
}

void prnt_out2( float *array, int dlina)
{
  Serial.print("\n\t");
  for ( uint32_t i = 0; i < dlina; i++)
  {
    Serial.print(String(array[i],6)); // 6 знаков после запятой
    Serial.print("\t");
    if ((i + 1) % 16 == 0) Serial.print("\n\t");
  }
  Serial.println("\n\t");
}



 

MagicianT
Offline
Зарегистрирован: 03.10.2015

У меня время (мерялось в 2014) примерно

* Hamng 904 Revb 765 SplitRR 3479 GainR 465 Sqrt 6423 Sqrt2 404
 765 + 3479 + 465 + 6423 = 11.132
 
у вас:    timeIZMsec=1.19 time_revbn=237237
 итого 237237  / 11 132 = 21.31 раз медленнее.
Если магнитуду считать по второму алгоритму
 765 + 3479 + 465 + 404 = 5.113
 итого 237237  / 5.113 =  46.398 раз медленнее.  Удивительно, мне казалось разница будет больше
 

 

diakin
diakin аватар
Offline
Зарегистрирован: 04.06.2016

Вот еще добавил измерение фазы

void FFTAnalysis(float AVal[], float FTvl[], float Phvl[], int Nvl, int Nft)
{
[.....]

  Phvl[i]=atan(Tmvl[j + 1]/Tmvl[j])/TwoPi*360; // фаза в градусах :)
}

 

Andrey2020
Offline
Зарегистрирован: 09.07.2020

Коллеги,

Два вопроса - я так понял на MEGA это не работает - не хватает памяти нужно DUE

И второй вопрос - библиотеки где взять? ссылки не работают
не могу найти UTFT.h - это что за зверь? TFT ?

b707
Offline
Зарегистрирован: 26.05.2017

Andrey2020 пишет:
И второй вопрос - библиотеки где взять? ссылки не работают не могу найти UTFT.h?

прямо в тексте этого сообщения выделяете UTFT.h, нажимаете правую кнопку мыши и выбираете "Искать UTFT.h в гугле"

И, на будущее - стесняйтесь задавать идиотские вопросы...

Andrey2020
Offline
Зарегистрирован: 09.07.2020

B707, я хоть и новичок в этом вопросе но я уже искал в инете UTFT.h

И нашёл несколько... но во всех них написано что это библиотека для TFT дисплея... Судя по Скетчу вывод информации идёт в сериальный порт. Причём тут библиотека TFT и FFT ума не приложу...

Может всё таки аффтары ответят???

Andrey2020
Offline
Зарегистрирован: 09.07.2020

Коллега, послушайте, все авторы которые ниже offline..

Может быть вы знаете что за зверь UTFT.h которые они применяют ниже в своих скетчах по FFT.

Смотрел в гугле - везде находится только UTFT.h - что это библиотека TFT.

Но причём тут TFT и FFT??? ведь в скетчах вывод информации идёт на экран монитора...

ХЕЛП!

b707
Offline
Зарегистрирован: 26.05.2017

попробуйте закомментировать строчку с этой либой - и посмотрите, вылезут ли ошибки при компиляции

Andrey2020
Offline
Зарегистрирован: 09.07.2020

Спасибо, вечером проверю.

А ещё глупый вопрос - в Arduino IDE нет платы DUE... нужно другую прогу закачать?

 

b707
Offline
Зарегистрирован: 26.05.2017

Andrey2020 пишет:

А ещё глупый вопрос - в Arduino IDE нет платы DUE... нужно другую прогу закачать?

нужно установить поддержку Дуе, как - описано в тысячах мест в гугле, вот первая попавшаяся ссылка:

http://robotosha.ru/arduino/install-core-arduino-ide.html

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Andrey2020 пишет:

Спасибо, вечером проверю.

А ещё глупый вопрос - в Arduino IDE нет платы DUE... нужно другую прогу закачать?

Да, в стандартной поставке ее нет. В IDE в том же пункте меню, где выбираете плату, в самом верху есть менеджер плат. Через него и докачиваете нужную плату.

Andrey2020
Offline
Зарегистрирован: 09.07.2020

andriano, скажите а по поводу моего вопроса касательно UTFT.h - который используется в скетчах - нет понятия что это?

Спасибо!

diakin
diakin аватар
Offline
Зарегистрирован: 04.06.2016

https://habr.com/ru/post/196600/

Для работы с TFT дисплеями используется набор библиотек UTFT. Наиболее свежие версии этих библиотек можно найти на сайте разработчика: http://www.henningkarlsen.com/electronics/
 

 

Andrey2020
Offline
Зарегистрирован: 09.07.2020

Коллега, добрый день!

 

Писал тут всем... по поводу библиотеки UTFT.h которую Вы все используете в скетчах FFT.

ЧТо это за зверь?  Гугл говорит что это библиотека TFT...

Но это странно!

Прошу помощи - где взять правильный UTFT.h

ХЕЛП!

Заранее огромное спасибо!

 

Andrey2020
Offline
Зарегистрирован: 09.07.2020

Я понял! Так а зачем тут TFT ?  У ВАс же в скетчах вывод идёт на Сериальный порт на экран монитора или я что-то не заметил случайно??? Я думал UTFT.h это что-то имеющее отношение к FFT

diakin
diakin аватар
Offline
Зарегистрирован: 04.06.2016

Ну это кусок программы, где использовался вывод на экран. 
Для FFT он не нужен, #include <UTFT.h> можно закомментировать.
В свою программу вы вставляете функцию FFTAnalysis, и обращаетесь к ней, как показано в примере. 

Andrey2020
Offline
Зарегистрирован: 09.07.2020

Спасибо за инфу.

А ссылкой не поделитесь где взять FFTAnalysis ?

Что-то так в прямую не ищется!

Заранее благодарен!

b707
Offline
Зарегистрирован: 26.05.2017

Andrey2020 пишет:

Спасибо за инфу.

А ссылкой не поделитесь где взять FFTAnalysis ?

Что-то так в прямую не ищется!

Заранее благодарен!

Андрей, второй раз делаю замечание за идиотские вопросы. Сначала думаем. потом спрашиваем. FFTAnalysis - это функция, (например строка 118 из кода сообщения 16) - искать ее в инете не надо.

Andrey2020
Offline
Зарегистрирован: 09.07.2020

Спасибо я исправлюсь!

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Andrey2020 пишет:

andriano, скажите а по поводу моего вопроса касательно UTFT.h - который используется в скетчах - нет понятия что это?

Спасибо!

Мне известно, что такое название имеет одна из распространенных Ардуино библиотек для растровых дисплеев. Более подробно не скажу, т.к. ни этой библиотекой, ни какими другими библиотеками для экрана не пользуюсь, предпочитаю писать свое. 

Подозреваю, что UTFT никакого отношения к FFT не имеет, но может использоваться в конкретном проекте для вывода результатов FFT на экран.

Logik
Offline
Зарегистрирован: 05.08.2014

Знаешь, если бы она использовалась конкретно в этом проекте, то было бы не так смешно. А так жеж ведь и не используется даже, просто инклудили и все. Но вполне очевидный совет выкинуть ту строку, хотяб закоментировать, он не слышит ))) С таким уровнем только с БПФ остается разбиратся!

Andrey2020
Offline
Зарегистрирован: 09.07.2020

Послушайте, совместными Вашими усилиями всё сделал. плату DUE купил, всё скомпилил без ошибок...

А что должно быть на выходе то?

Правильно ли я понимаю что надо смотреть на Serial порте?

Там какая-то мешанина выплёвывается и всё..

Я думал будет или числа или бары... может с 2016 года в IDE print.serial изменился кардинально..

Тут точно нужен совет :)

 

 

 

Andrey2020
Offline
Зарегистрирован: 09.07.2020

Послушайте, совместными Вашими усилиями всё сделал. плату DUE купил, всё скомпилил без ошибок...

А что должно быть на выходе то?

Правильно ли я понимаю что надо смотреть на Serial порте?

Там какая-то мешанина выплёвывается и всё..

Я думал будет или числа или бары... может с 2016 года в IDE print.serial изменился кардинально..

Тут точно нужен совет :)

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

А у Вас скорость порта в скетче и в мониторе порта совпадает?

Andrey2020
Offline
Зарегистрирован: 09.07.2020

Сорян... не обратил на это внимание... конечно не совпадали.

Сейчас исправил.

Выводится 16 колонок с цифрами - матрица ..

Так и должно быть

Andrey2020
Offline
Зарегистрирован: 09.07.2020

diakin пишет:

А все работает  )
Пример для Ардуины Due
Время измерения подобрано 1 сек. (5 мкс на analogRead(A0) + 483 мкс задержка между отсчетами.
Получается 2048*0.488 мс=1 сек.
Вход ловит наводку 50 Гц, для длительности 1 сек это 50-я гармоника.
Что и видно в мониторе - начиная с 0 гармоники (1007 ступенек АЦП) и максимум на 50 гармонике - 363 ступеньки. (Ну это на моей плате с проводками на входах )

Ура! ))
Большое спасибо!

/*
This Example acquire analog signal from A0 of Arduino? make FFT and show result //via Serial out.
*/

#include <UTFT.h>
#include <SplitRadixRealP.h>
// FFT_SIZE IS DEFINED in Header file Radix4.h 
// #define   FFT_SIZE           2048

#define   MIRROR         FFT_SIZE / 2
#define   INP_BUFF       FFT_SIZE 
         
int         f_r[FFT_SIZE]   = { 0};
int         out1[MIRROR]    = { 0};     // Magnitudes
int         out2[MIRROR]    = { 0};     // Magnitudes

const       int         dc_offset       = 1023; 

unsigned long time_start;
unsigned int  time_hamng, time_revbn, time_radix, time_gainr, time_sqrtl, time_sqrtl2;
                 
SplitRadixRealP     radix;

#define FFT_N FFT_SIZE
#define NumPoint FFT_N

void setup()
{
  Serial.begin(57600);
}

void loop()
{
  unsigned long timeB, timeE;
  float timeIZMsec;
  
  timeB = micros();
  for (int i = 0; i < NumPoint; i++)
  {
    f_r[i] = analogRead(A0); //(30*sin(100*Tsample*i+3.14159*0)-0) ; // analogRead(A0) ; // 1023/5=204,6 на 1 вольт  /Kus1
    delayMicroseconds(483);        // pauses for 50 microseconds
  }
  timeE = micros(); //12,3 мкс на отсчет = 80 кгц частота дискретизации
  //Serial.println("----------------")  ;
  timeIZMsec = float(timeE - timeB) / 1000000;

   time_start = micros();
   radix.rev_bin( f_r, FFT_SIZE);
   time_revbn  = micros() - time_start;

   time_start = micros();
   radix.fft_split_radix_real( f_r, LOG2_FFT);
   time_radix  = micros() - time_start;

   time_start = micros();
   radix.gain_Reset( f_r, LOG2_FFT -1); 
   time_gainr  = micros() - time_start;

   time_start = micros();
   radix.get_Magnit1( f_r, out1);
   time_sqrtl  = micros() - time_start;

   time_start = micros();
   radix.get_Magnit2( f_r, out2);
   time_sqrtl2  = micros() - time_start;
   
            Serial.print("timeIZMsec="+String(timeIZMsec)+" "+"\n\tMagnitudes: ");    
            prnt_out2( out1, MIRROR);
//            prnt_out2( out2, MIRROR);
   

}

void prnt_out2( int *array, int dlina) 
{
  Serial.print("\n\t");      
     for ( uint32_t i = 0; i < dlina; i++)
     {
       Serial.print(String(array[i]));       
       Serial.print("\t");    
       if ((i+1)%16 == 0) Serial.print("\n\t");
     }
  Serial.println("\n\t");
}


 

Коллеги, а какие в этом примере нужно поменять константы чтобы буфер сделать не 2048 а 1024 и потом сэмплинг не 80кгц сделать а 20кгц - это мне достаточно!

Спасибо

 

Morroc
Offline
Зарегистрирован: 24.10.2016

Про частоту прям в цитировании вашем написано, про размер в коде на англицком.

Andrey2020
Offline
Зарегистрирован: 09.07.2020

Да там написано что 2048 константа находится в Splitradix.h

Нашёл её..  Интересно если её изменить то... будет работать? Там же константы внутри - массив … он универсальный или рассчитан на 2048

Второй момент... там ещё есть константа в теле проги 1023... ещё то;е поделить пополам надо?? т.е. 511 ??

И третье… по поводу 80кгц... там таймер закомментирован. вместо этого стоит задержка при чтении с порта 50мкс... это 20 килогерц как раз..

Но у меня вопрос - почему применяется delay ? это же просто задержка и всё. почему не делается анализ таймера через micros() ??? получается несинхронное чтение АЦП тогда и как следствие - Jitter...

Я не прав?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Andrey2020 пишет:

Но у меня вопрос - почему применяется delay ? это же просто задержка и всё. почему не делается анализ таймера через micros() ??? получается несинхронное чтение АЦП тогда и как следствие - Jitter...

Я не прав?

Нет. С "анализом таймера через micros()" будет точно такой же джиттер. В принципе - небольшой. А чтобы совсем без него - нужно считывать в прерывании по таймеру, а еще лучше - натравить на это дело DMA. В то же время, примеров программирования SAM3 в И-нете довольно мало (по сравнению с AVR или STM), практически единственное справочное пособие - это дэйташит. Вот и пишут люди, как проще.

Для сравнения можете посмотреть здесь: http://arduino.ru/forum/proekty/konstruktsiya-vykhodnogo-dnya-prostoi-spektranalizator-480-polos-60-db-na-stm32f103-i-

там первый вариант точно так же - на задержке (но и написан он целиком менее, чем за день), а последний - уже по таймеру через DMA - как положено (но на доведение до ума ушло почти два месяца).

Andrey2020
Offline
Зарегистрирован: 09.07.2020

andriano пишет:

Andrey2020 пишет:

Но у меня вопрос - почему применяется delay ? это же просто задержка и всё. почему не делается анализ таймера через micros() ??? получается несинхронное чтение АЦП тогда и как следствие - Jitter...

Я не прав?

Нет. С "анализом таймера через micros()" будет точно такой же джиттер. В принципе - небольшой. А чтобы совсем без него - нужно считывать в прерывании по таймеру, а еще лучше - натравить на это дело DMA. В то же время, примеров программирования SAM3 в И-нете довольно мало (по сравнению с AVR или STM), практически единственное справочное пособие - это дэйташит. Вот и пишут люди, как проще.

Для сравнения можете посмотреть здесь: http://arduino.ru/forum/proekty/konstruktsiya-vykhodnogo-dnya-prostoi-spektranalizator-480-polos-60-db-na-stm32f103-i-

там первый вариант точно так же - на задержке (но и написан он целиком менее, чем за день), а последний - уже по таймеру через DMA - как положено (но на доведение до ума ушло почти два месяца).

прерывание таймера это заморочисто… Я попробую по micros() потом подам синус с генератора на вход ADC и проверю что выдаёт Фурье на выходе. Для этого мне и нужен был вывод через плоттер на монитор. Графику удобнее глядеть чем числа..!

Andrey2020
Offline
Зарегистрирован: 09.07.2020

Коллеги,

не подскажите как вычислить major peak  (частоту главного пика) для FFT/FHT

такая функция нужна для определения частоты спектра (делаю доплеровский радар.)

функция есть в библиотеке в библиотеке ArduinoFFT но она с плавающей точкой и медленно работает.

Есть библиотеки FFT.h и FHT.h у них логарифмический выход в байтах они очень быстрые и меня устраивают.

Но там нет стандартной функции типа major_peak();

может есть какой-то код... поделитесь пожалуйста.

можно конечно самому писать типа методом сравнения и нормализации но нужен хороший алгоритм. сложность в том например что на выходе в первых двух бинах всегда пик постоянной составляющей... что с ним делать ? отрезать ? начинать перебирать бины с 3-го??

diakin
diakin аватар
Offline
Зарегистрирован: 04.06.2016

Andrey2020 пишет:

...major peak  (частоту главного пика) для FFT/FHT

...частоты спектра

А что это такое?

Andrey2020
Offline
Зарегистрирован: 09.07.2020

diakin пишет:

Andrey2020 пишет:

...major peak  (частоту главного пика) для FFT/FHT

...частоты спектра

А что это такое?

major peak?

к примеру на вход FFT или FHT подан синусоидный сигнал.

На выходе в одном из бинов - пик.

Специальная подпрограмма хитрым способом находит его (отличая от первых бинов где находится пик постоянки) и используя сэмлинг рейт вычисляет фактическую частоту этого пика выдавая значение float

diakin
diakin аватар
Offline
Зарегистрирован: 04.06.2016

А если на входе будет 10 синусоид, то кто из них будет major peak?
Если частота входного сигнала и время измерения известны, то надо поделить первое на второе, и получится номер гармоники (бина). Это видимо и будет major peak.