Stm32f4 Discovery DSP LİB kullanımı

Başlatan Kaanx, 03 Haziran 2013, 23:23:42

Mucit23

Farklı birşey yok bendede. Ben hazır kütüphane kullanma peşindeyim aslında. Pek fazla işim olmayacak çünkü.

Kaanx

Stm32f4 de hazır kutuphane bulmakta sorun hocam

superconductor

Kullandığım fft fonksiyonu şu şekilde.Bende linkini verdiğim pic ile yapılmış projeden alıntı yaptım. Kullanımı projenin içinde detaylı anlatılmış.
Aslında en iyisi öğrenerek gitmek ama iş yetiştirmem gerektiğinden benim fırsatım olmadı.


void fft(int fr[],int fi[],int m)
{
long int mr = 0, nn, i, j, l, k, istep, n, shift;
  short qr, qi, tr, ti, wr, wi;
	
	n = 1 << m;
  nn = n - 1;
	
	 for (m=1; m<=nn; ++m)
   {
      l = n;
      do
      {
         l >>= 1;
      } while (mr+l > nn);
      
      mr = (mr & (l-1)) + l;
      if (mr <= m) continue;
      
      tr = fr[m];
      fr[m] = fr[mr];
      fr[mr] = tr;
      ti = fi[m];
      fi[m] = fi[mr];
      fi[mr] = ti;
   }
	l = 1;
   k = LOG2_N_WAVE-1;
	
	while (l < n)
   {
   
      long int c;
      short b;
      
      istep = l << 1;
       for (m=0; m<l; ++m)
      {
         j = m << k;
        
         wr =  Sinewave[j+N_WAVE/4];
         wi = -Sinewave[j];

         wr >>= 1;
         wi >>= 1;
         
         for (i=m; i<n; i+=istep)
         {
            j = i + l;
            
           
            c = ((long int)wr * (long int)fr[j]);
            c = c >> 14;
            b = c & 0x01;
            tr = (c >> 1) + b;
            
            c = ((long int)wi * (long int)fi[j]);
            c = c >> 14;
            b = c & 0x01;
            tr = tr - ((c >> 1) + b);
            
					  
           
            c = ((long int)wr * (long int)fi[j]);
            c = c >> 14;
            b = c & 0x01;
            ti = (c >> 1) + b;
            
            c = ((long int)wi * (long int)fr[j]);
            c = c >> 14;
            b = c & 0x01;
            ti = ti + ((c >> 1) + b);
            
					
						
            qr = fr[i];
            qi = fi[i];
            qr >>= 1;
            qi >>= 1;

            fr[j] = qr - tr;
            fi[j] = qi - ti;
            fr[i] = qr + tr;
            fi[i] = qi + ti;
         }
      }
      
      --k;
      l = istep;
   }




Mucit23

DSP Library üzerinde çalışıyorum. Diğer konuda bahsettiğim timer sorununu çözdüm. #define kısmında __ASSEMBLY__ tanımlamasıda olması gerekiyormuş.

Şimdi ADC den 32Khz frekansta N kadar örnek alıp DMA ile diziye atabiliyorum.

Şuanda Yapmaya çalıştığım şey Max 16Khz frekansı FFT ile 32 noktada görüntüleyebilmek. Bunun için ADC örnekleme frekansını 32Khz yaptım. Daha önceki çalışmalarımdan örnekleme frekansı max. görüntülenmek istenen frekansın iki katı olarak seçilmesi gerektiğini biliyorum.

DSP Library içerisinde bir örnek program var o ve alttaki linkte bulduğum örneğe bakarak birşeyler yapmaya çalışıyorum.
http://stm32f4-discovery.com/2014/10/stm32f4-fft-example/

Amacım DSP library ile FFT almayı öğrenmek.

FFT almak için sırayla aşağıdaki işlemleri yaptım.
if(FFT_Ready_Flag)
		{
			 SampleIndex=0;
			
			 for(i=0;i<ADC_SAMPLES;i=i+2) //Loading input buffer
			 {
			    Input[i]=(float32_t)((float32_t)ADCConvertedValue[SampleIndex]-(float32_t)2048.0)/(float32_t)2048.0;
				  Input[i+1]=0;       //Clearing imaginary Values
				  SampleIndex++;
			 } 
			
			 /* Initialize the CFFT/CIFFT module */
     	                 arm_cfft_radix4_init_f32(&FFT_Module, FFT_SIZE, 0, 1);
		         /* Process the data through the CFFT/CIFFT module */
		         arm_cfft_radix4_f32(&FFT_Module, Input);
			 /* Process the data through the Complex Magnitude Module for calculating the magnitude at each bin */
		         arm_cmplx_mag_f32(Input, Output, FFT_SIZE);
			 /* Calculates maxValue and returns corresponding value */
			 arm_max_f32(Output, FFT_SIZE, &MaxValue, &MaxValueIndex);
			 /*Clearing FFT Buffer */
			 FFT_Ready_Flag=0;  
		}


DSB libraryde Complex FFT alınmak istediğinde giriş verisi Çıkış verisinin 2 katı seçilmiş. Yani Öneğin Bana 32 noktada örnek lazım. Input dizisini 64 seçip ADC değerleri birer boşluk bırakılarak Input dizisine yerleştiriliyor.

Input[N]=ADC değeri ise Input[N+1]=0 olarak ayarlanıyor. N. eleman reel kısım ise N+1 imaginer kısım olarak açıklanmış örnekte.

Yukarıda verdiğim kodlarda en baştaki for döngüsüyle bu işlemi yapıyorum. Sayının +-1 aralığında değişmesi için ADC den okuduğum değeri 2048 den çıkarıp 2048'e böldüm. verdiğim linkteki adamda öyle yapmış sanırım sayıları küçültmek için böyle yapıyor.

DSP library içerisindeki Örnek data aşağıdaki gibi. Gördüğünüz gibi birer boşluk bırakılarak değerler yerleştirilmiş.
float32_t testInput_f32_10khz[2048] = 
{   
-0.865129623056441, 	0.000000000000000, 	-2.655020678073846, 	0.000000000000000, 	0.600664612949661, 	0.000000000000000, 	0.080378093886515, 	0.000000000000000, 	
-2.899160484012034, 	0.000000000000000, 	2.563004262857762, 	0.000000000000000, 	3.078328403304206, 	0.000000000000000, 	0.105906778385130, 	0.000000000000000, 	
0.048366940168201, 	0.000000000000000, 	-0.145696461188734, 	0.000000000000000, 	-0.023417155362879,


Birinci anlamadığım kısım neden komplex sayılarla işlem yapılıyor? Daha doğrusu CFFT nin RFFT den farkı ne? Mesela FFT fonksiyonları içerisinde arm_rfft_fast_f32 fonksiyonuda var. Uygulamada hangisinin artıları var onu bilmiyorum.

Diğer bir konu ise yukarıda yazdığım kodların gerçekte garip bir şekilde çalışması. Yine bir yerlerde hata yapıyorum.

yukarıda 32 nokta için bu işlemi yaptığımı söylemiştim. Output dizisinin ilk 20 elemanını doğrudan ekrana yazdırdım ve ADC den verdiğim ses sinyaline göre çıkış nasıl değişiyor onu anlamaya çalıştım.

Max örnekleme frekansımız 16Khz, Bunu 32parçaya bölersek 0, 500Hz 1000hz 1500hz gibi 500hz aralıklarla ölçüm yapabilmemiz gerekir.

Gerçekte 1Khz sinüs verdiğimde Output dizisinin 1, 18,19,20 ve 21. elemanlarında ufak artışlar görüyorum. 2Khz yapsam yine olmaması artmaması gereken elemanlarda artış görüyorum Bunun sebebini anlayamadım. Bunun gibi hiçbir frekansta çıkış değerim tutarlı değil.

Sonuç olarak çalıştıramadım. Fonksiyonların kullanımı tam olarak nasıl? Teorik olarak hata yaptığım bir yer varmı?

Mucit23

Arkadaşlar DSP library'deki kodu başka nasıl test edebilirim?


Şuanda ADC den veri giriyorum. ADC ye ise Telefon ile sinyal uyguluyorum.

ADC girişine 1.65V ofset eklemek için yukarıdaki devreyi kurdum. Değerler dediğim gibi anlamsız oluyor. Aldığım sonuçları henuz bargraph'a çizmedim ama yinede 0-16khz arası dizi elemanlarının değerleri sırasıyla artması lazım. Mantıken öyle ama yukarıdaki kodlar pratikte öyle çalışmıyor.


Fikri olan var mı?

beatname

Mucit23 sorunu halledebildin mi? Bende FFT konusunda bir çalışma gerçekleştirdim. Fakat takıldığım noktalar var

Mucit23

Selamlar

Uzun zaman olmuş fft ile uğraşmayalı. DSP Library ile yine bir sinyal örneklemem gerekti.
35Khz'de örnek alıyorum. Örnek sayım 128. Dolayısıyla FFT algoritması bana 64 noktanın değerini vermesi gerekiyor. Sonucu daha iyi yorumlamak için Spektrum çizdirdim.

FFT Sonucum Çift görünüyor. Örneğin aşağıdaki resimde girişe 8 küsür Khz sinyal uyguluyorum.


Sanki İşlem sonucu hep 32 band gibi görünüyor. Diğer 32 band birebir aynı.

Bu neden olur?

RaMu

Acaba neden,
nyquist mezarında ters döndü,
simetrik olması gerek zaten diye kemikleri sızlıyor :)


Çok iddialı konuştum,
hatırladığım kadarıyla
fourier dönüşümü çıkan sonuç simetrik oluyordu,
neydi niyeydi hatırlamıyorum ama
şimdi merak ettim biraz bakacağım.
Sorularınıza hızlı cevap alın: http://www.picproje.org/index.php/topic,57135.0.html

Mucit23

Alıntı yapılan: RaMu - 21 Mayıs 2017, 23:17:01
nyquist mezarında ters döndü,
simetrik olması gerek zaten diye kemikleri sızlıyor :)

Aman hocam durun. Konuyu tam olarak hatırlamıyorum. Teorik bilgilerimi tazelemem lazım :) Ama sanki böyle değildi. Konuya tekrar bir bakayım.

RaMu

Şimdi @berat23 olaydı şak diye söylerdi,
FT hakkında bilgi sahibi başka üyeler de vardı ama nikler aklıma gelmedi,
bilenler görse hemen hatırlatırlar cevabı aslında.

Sorularınıza hızlı cevap alın: http://www.picproje.org/index.php/topic,57135.0.html

berat23

Alıntı yapılan: RaMu - 21 Mayıs 2017, 23:43:07
Şimdi @berat23 olaydı şak diye söylerdi,
FT hakkında bilgi sahibi başka üyeler de vardı ama nikler aklıma gelmedi,
bilenler görse hemen hatırlatırlar cevabı aslında.


davete icabet edelim.


verilen rakamlara göre manzarada bir hata yok. şöyle ki 35khz denmiş, yuvarlak olsun diye 32 diyelim. sonuç 32 uzunluklu gelmiş, yani yarısı 16 örnek 16khz'e denk geliyor. sinyal de 8khz ise 8. ve 24. örneklerde bir tepe olması lazım ki olmuş. yani bu sonuç doğru.


fft belli uzunluklarla yapılan bir işlem, o uzunluklarda ikinin kuvveti. şimdi senin elinde 128 örnek varsa buna illa 128 uzunluklu fft almak zorunda değilsin. uzunluğun az olursa işlemsel yükün azalır ama frekans çözünürlüğün düşer. fft uzunluğunu arttırırsan kompleksite artar ama çözünürlüğün de artar. daha uzun fft almak için veriye ekleme yapman lazım, mesela zero padding ile istediğin uzunluğa getirirsin.


burdaki durum muhtemelen şu; kullandığın fonksiyon 32 uzunluklu fft alıyor. dolayısıyla sonuçlar veri ne uzunlukta olursa olsun 32 oluyor.

Mucit23

@berat23 Cevap için teşekkürler

FFT almak için arm_cfft_radix4_f32 fonksiyonunu kullanıyorum. Buradaki f32 tanımı acaba boyutumu veriyor? Ben Float 32 kısaltması şeklinde yorumluyordum.

Diğer türlü örnek sayımı 128 yapıp fonksiyona verince saçma sapan çıktılar alıyorum. FFT ile alakası yok.

FFT almak içinde aşağıdaki yapıyı kullanıyorum.

if(FFT_Ready)
			{ 
				 FFT_Ready=0;
				 
			   for(i=0;i<SAMPLES;i=i+2)
				 {
				    Input[(uint16_t)i] = (float32_t)(ADC3ConvertedValues[i/2] - 2048.0) / (float32_t)2048.0;
					  /* Imaginary part */
            Input[(uint16_t)(i + 1)] = 0;
				 }
				 
				 /* Initialize the CFFT/CIFFT module, intFlag = 0, doBitReverse = 1 */
         arm_cfft_radix4_init_f32(&S, FFT_SIZE, 0, 1);
        
         /* Process the data through the CFFT/CIFFT module */
         arm_cfft_radix4_f32(&S, Input);
        
         /* Process the data through the Complex Magniture Module for calculating the magnitude at each bin */
         arm_cmplx_mag_f32(Input, Output, FFT_SIZE);
        
         /* Calculates maxValue and returns corresponding value */
         arm_max_f32(Output, FFT_SIZE, &maxValue, &maxIndex);
    }


Örnek sayım 128 ama Input dizisinin boyutu 256. Bu diziye birer boşluk bırakarak yerleştiriyorum elemanları. Dizinin tek indisli elemanları imajiner değerler(sabit olarak 0 veriyorum), Çift indisli elemanları ise reel değerler. Bu değerlere ise ADC den okunan değerleri +-1 aralıığına oranlayıp fonksiyona veriyorum.

Hocam peki nasıl yapmam gerekiyor? 64 çıkış veya 128 çıkış için dsp library'yi nasıl kullanacağım?

Mucit23

Güncel,


Hocam 64 Nokta Çıkış için ne yapmam gerekiyor? Çözemedim. Sample Sayısını arttırınca sistem sapıtıyor.

berat23

arm_cfft_radix4_f32 isminden ben kompleks, radix4 ve float32 yi anlıyorum. bunlar da uzunlukla alakalı değil. sonundaki f32'nin aslında ne olduğunu da bence siz koda bakıp daha iyi anlayabilirsiniz, ayrıca st'nin ise library, mutlaka dökümantasyonu vardır bakın bence.

bundan sonrası o koda özel işler, ben şahsen hiç birşey yapmadım dsp lib ile. dolayısıyla ben burda bitiyorum.

comme_il_faut

Bu arada matlab code generation ile fft fonksiyonunun c koduna dönüştürülmesi mümkün bilginiz olsun. Sonuçlar cmsis dsp "fft" fonksiyonundan çok daha hassastı diye hatırlıyorum.