flann 0 8 апреля, 2008 Опубликовано 8 апреля, 2008 · Жалоба Во первых уберите [x] при вызове функции а во вторых, я уже исправил предыдущий пост, нужно сделать так: four2(Buf_FFT,128,1) Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andreichk 0 8 апреля, 2008 Опубликовано 8 апреля, 2008 · Жалоба всё исправил, но всё равно рисует просто кривую Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
flann 0 8 апреля, 2008 Опубликовано 8 апреля, 2008 · Жалоба всё исправил, но всё равно рисует просто кривую еще раз посмотрел на вашу функцию four2(), во первых это опять функция для комплексного преобразования фурье, вам нужно преобразование для реальных чисел (гдето раньше вы уже выкладывали нужную процедуру) Хотя... лучше возьмите вот эту: void realFFT(float a[], unsigned int tnn, char inversefft) { float twr,twi,twpr,twpi,twtemp,ttheta; int i,i1,i2,i3,i4; float c1, c2, h1r, h1i, h2r,h2i,wrs, wis; int nn,ii, jj,n, mmax, m,j,istep,isign; float wtemp, wr,wpr, wpi, wi,theta,tempr,tempi; if( tnn==1 )return; if( !inversefft ){ ttheta = 6.28318530717959/tnn; c1 = 0.5; c2 = -0.5; }else{ ttheta = 6.28318530717959/tnn; c1 = 0.5; c2 = 0.5; ttheta = -ttheta; twpr = -2.0*(sin(0.5*ttheta))*(sin(0.5*ttheta)); twpi = sin(ttheta); twr = 1.0+twpr; twi = twpi; for(i = 2; i <= tnn/4+1; i++){ i1 = i+i-2; i2 = i1+1; i3 = tnn+1-i2; i4 = i3+1; wrs = twr; wis = twi; h1r = c1*(a[i1]+a[i3]); h1i = c1*(a[i2]-a[i4]); h2r = -c2*(a[i2]+a[i4]); h2i = c2*(a[i1]-a[i3]); a[i1] = h1r+wrs*h2r-wis*h2i; a[i2] = h1i+wrs*h2i+wis*h2r; a[i3] = h1r-wrs*h2r+wis*h2i; a[i4] = -h1i+wrs*h2i+wis*h2r; twtemp = twr; twr = twr*twpr-twi*twpi+twr; twi = twi*twpr+twtemp*twpi+twi; } h1r = a[0]; a[0] = c1*(h1r+a[1]); a[1] = c1*(h1r-a[1]); } if( inversefft ) isign = -1; else isign = 1; n = tnn; nn = tnn/2; j = 1; for(ii = 1; ii <= nn; ii++) { i = 2*ii-1; if( j>i ) { tempr = a[j-1]; tempi = a[j]; a[j-1] = a[i-1]; a[j] = a[i]; a[i-1] = tempr; a[i] = tempi; } m = n/2; while(m>=2&&j>m) { j = j-m; m = m/2; } j = j+m; } mmax = 2; while(n>mmax) { istep = 2*mmax; theta = 6.28318530717959/(isign*mmax); wpr = -2.0*(sin(0.5*theta))*(sin(0.5*theta)); wpi = sin(theta); wr = 1.0; wi = 0.0; for(ii = 1; ii <= mmax/2; ii++) { m = 2*ii-1; for(jj = 0; jj <= (n-m)/istep; jj++) { i = m+jj*istep; j = i+mmax; tempr = wr*a[j-1]-wi*a[j]; tempi = wr*a[j]+wi*a[j-1]; a[j-1] = a[i-1]-tempr; a[j] = a[i]-tempi; a[i-1] = a[i-1]+tempr; a[i] = a[i]+tempi; } wtemp = wr; wr = wr*wpr-wi*wpi+wr; wi = wi*wpr+wtemp*wpi+wi; } mmax = istep; } if( inversefft ) { for(i = 1; i <= 2*nn; i++) { a[i-1] = a[i-1]/nn; } } if( !inversefft ) { twpr = -2.0*(sin(0.5*ttheta))*(sin(0.5*theta)); twpi = sin(ttheta); twr = 1.0+twpr; twi = twpi; for(i = 2; i <= tnn/4+1; i++) { i1 = i+i-2; i2 = i1+1; i3 = tnn+1-i2; i4 = i3+1; wrs = twr; wis = twi; h1r = c1*(a[i1]+a[i3]); h1i = c1*(a[i2]-a[i4]); h2r = -c2*(a[i2]+a[i4]); h2i = c2*(a[i1]-a[i3]); a[i1] = h1r+wrs*h2r-wis*h2i; a[i2] = h1i+wrs*h2i+wis*h2r; a[i3] = h1r-wrs*h2r+wis*h2i; a[i4] = -h1i+wrs*h2i+wis*h2r; twtemp = twr; twr = twr*twpr-twi*twpi+twr; twi = twi*twpr+twtemp*twpi+twi; } h1r = a[0]; a[0] = h1r+a[1]; a[1] = h1r-a[1]; } } вызывайте ее так: realFFT(Buf_FFT, 256, 0); а после вызова сделайте такой цикл: for(i=0;i<256;i+=2){ Buf_FFT[k++]=pow((Buf_FFT[i]*Buf_FFT[i]+Buf_FFT[i+1]*Buf_FFT[i+1]),0.5); } Buf_FFT[0]=0; Затем распечатайте на экран первые 128 значений буффера Только перед распечаткой нужно еще пронормировать на максимальное значение (чтобы было равно высоте экрана) Да, еще старайтесь чтобы на экран умещалось побольше периодов сигнала, чтобы лучше увидеть пик Кстати, почитайте, очень похожий проект: http://rf.atnn.ru/s10/digital_osc.html там и про FFT че-то написано, даже есть исходник в низу страницы. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andreichk 0 8 апреля, 2008 Опубликовано 8 апреля, 2008 (изменено) · Жалоба экран замирает и ничего не происходит :07: void spectrum_analizator(unsigned int8 y_pos) {unsigned int8 x=0,y,yy,k=0,i=0;unsigned int16 n=0; //----------------------------------------------------------------------------- if (n++>8192){// Если дошли до сюда, значит не удалось найти период return;// Занулим частоту (типа не посчитали... ) } //----------------------------------------------------------------------------- for(x=0;x<255;x++){ #asm BCF 0x0F8B,2//LATC2=0; #endasm Buf[x]=255 - input_b(); //чтение порта В #asm BSF 0x0F8B,2//LATC2=1; #endasm } for(x=0;x<255;x++){ Buf_FFT[x]=Buf[x];// } realFFT(Buf_FFT, 256, 0); for(i=0;i<256;i+=2){ Buf_FFT[k++]=pow((Buf_FFT[i]*Buf_FFT[i]+Buf_FFT[i+1]*Buf_FFT[i+1]),0.5); } Buf_FFT[0]=0; for(x=0;x<128;x++){ yy=y; y = Buf_FFT[x] + y_pos;// y = (y > 200) ? 200 : y; //ограничитель до выбранной величины if (yy>y) front(x,yy,y);// Рисуем фронт if (yy<y) spad(x,yy,y); // Рисуем спад pixel(x,y,1); // Рисуем вершину } setCursorAddress(0x2581); clear_graphic(); } //######################################### закрыл это- опять стала рисовать просто импульсы //for(i=0;i<256;i+=2){ // Buf_FFT[k++]=pow((Buf_FFT[i]*Buf_FFT[i]+Buf_FFT[i+1]*Buf_FFT[i+1]),0.5); //} изменил размерность переменной i на unsigned int16- на экране появились импульсы в два раза уже , чем обычные и прим. на одну треть выше Изменено 8 апреля, 2008 пользователем andreichk Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
flann 0 8 апреля, 2008 Опубликовано 8 апреля, 2008 · Жалоба Что-то вы шаманством каким-то занимаетесь... :( Не вижу у вас нормировки сигнала.... Давайте сделаем так: signed int16 Buf_FFT[512]; // переобъявим массив как int void spectrum_analizator(void) { unsigned int8 x=0,y,yy; unsigned int16 i=0,max=0,k=0; setCursorAddress(0x2581); //Я так понимаю чистить экран нужно перед отрисовкой а не после... clear_graphic(); #asm BCF 0x0F8B,0 //Output_bit(PLCD_FIFO_RES,0);//PIN_C0 сброс FIFO в "0" BSF 0x0F8B,0 //Output_bit(PLCD_FIFO_RES,1);//PIN_C0 и разрешение на считывание BSF 0x0F8B,1 //Output_bit(READ_FIFO_B,1);//PIN_C1 запрет канала B #endasm for(i=0;i<512;i++){ #asm BCF 0x0F8B,2//LATC2=0; #endasm Buf_FFT[i]=input_b(); //чтение порта В #asm BSF 0x0F8B,2//LATC2=1; #endasm } realFFT(Buf_FFT, 512, 0); for(i=0;i<512;i+=2){ Buf_FFT[k++]=pow((Buf_FFT[i]*Buf_FFT[i]+Buf_FFT[i+1]*Buf_FFT[i+1]),0.5); } Buf_FFT[0]=0; for(i=0;i<256;i++) if(Buf_FFT[i]>max) max=Buf_FFT[i]; // ищем max for(i=0;i<256;i++) Buf_FFT[i]=236-(Buf_FFT[i]*230/max); //нормировка по max, и инвертирование перед распечаткой for(x=1;x<254;x++){ yy=y; y = Buf_FFT[x]; if (yy>y) front(x,yy,y);// Рисуем фронт if (yy<y) spad(x,yy,y); // Рисуем спад pixel(x,y,1); // Рисуем вершину } } а процедуру realFFT переобъявим следующим образом: void realFFT(signed int16 a[], unsigned int tnn, char inversefft) Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andreichk 0 8 апреля, 2008 Опубликовано 8 апреля, 2008 · Жалоба по-прежнему просто узкие , но очень большие по аплитуде импульсы. Они теперь даже не влезают в экран. зы.я не шаман,теперь я как все зелёный человечек. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
flann 0 8 апреля, 2008 Опубликовано 8 апреля, 2008 · Жалоба по-прежнему просто узкие , но очень большие по аплитуде импульсы. Они теперь даже не влезают в экран. зы.я не шаман,теперь я как все зелёный человечек. Хачу видеть 2 картинки - исходного сигнала и его спектра. Не меняя частоту тактирования FIFO. Сделайте так чтобы на экран при этом входило периодов 8 примерно Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andreichk 0 8 апреля, 2008 Опубликовано 8 апреля, 2008 · Жалоба выставил сейчас прямоугольники 400кГц, развёртка на 3.2мксек.амплитуда прим. 3 вольта одно могу сказать пока, они в два раза Уже и по аплитуде скачут то вверх, то вниз.Рисуются медленней и плохо синхронизируются как в режиме спектра, так и в осциллографическом. вот и фотки 1 скоп 2 спектр хачу таааак :crying: Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
flann 0 8 апреля, 2008 Опубликовано 8 апреля, 2008 · Жалоба выставил сейчас прямоугольники 400кГц, развёртка на 3.2мксек.амплитуда прим. 3 вольта одно могу сказать пока, они в два раза Уже и по аплитуде скачут то вверх, то вниз.Рисуются медленней и плохо синхронизируются как в режиме спектра, так и в осциллографическом. вот и фотки 1 скоп 2 спектр хачу таааак :crying: Да это у вас совсем не спектр... :( Приведите в итоге весь цикл как вы получаете и отрисовываете спектр. Не понял что значит рисуется медленней? У вас чтоли одновременно и спектр и сигнал рисуется, или я че-то не догоняю.... Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andreichk 0 8 апреля, 2008 Опубликовано 8 апреля, 2008 · Жалоба вызываем процедуру void spectr_A(unsigned int8 y_pos_A) void spectr_A(unsigned int8 y_pos_A) // пытаемся нарисовать спектр { unsigned int16 n=0,amplitude; #asm BCF 0x0F8B,0 //Output_bit(PLCD_FIFO_RES,0);//PIN_C0 сброс FIFO в "0" BSF 0x0F8B,0 //Output_bit(PLCD_FIFO_RES,1);//PIN_C0 и разрешение на считывание BSF 0x0F8B,1 //Output_bit(READ_FIFO_B,1);//PIN_C1 запрет канала B #endasm //-------------------- синхронизация --------------------------- for(ever){ #asm BCF 0x0F8B,2//LATC2=0;//Output_bit(READ_FIFO_A ,0);//PIN_C2. разрешить #endasm amplitude=input_b(); //чтение порта В #asm BSF 0x0F8B,2//LATC2=1;//Output_bit(READ_FIFO_A ,1);//PIN_C2.запретить #endasm amplitude = (amplitude > 200) ? 200 : amplitude; //ограничитель до выбранной величины amplitude = 255 - amplitude; // разворот на 180° по вертикали if (n++>MAXN) break;// В этой попытке смотреть дальше не имеет смысла if (syncA){//синхронизация по фронту A if(amplitude>sync_volume_A) continue; else break; }else{//синхронизация по спаду A if(amplitude<=sync_volume_A+115) continue; else break; } } spectrum_analizator(y_pos_A,n);//Сюда попадем только если нашли фронт синхронизации }//--------------------------OK //#################################################################### void spectrum_analizator(unsigned int8 y_pos,unsigned int16 n) { unsigned int8 x=0,y,yy; unsigned int16 i=0,max=0,k=0; //----------------------------------------------------------------------------- if (n++>8192){// Если дошли до сюда, значит не удалось найти период return;// Занулим частоту (типа не посчитали... ) } //----------------------------------------------------------------------------- #asm BCF 0x0F8B,0 //Output_bit(PLCD_FIFO_RES,0);//PIN_C0 сброс FIFO в "0" BSF 0x0F8B,0 //Output_bit(PLCD_FIFO_RES,1);//PIN_C0 и разрешение на считывание BSF 0x0F8B,1 //Output_bit(READ_FIFO_B,1);//PIN_C1 запрет канала B #endasm for(i=0;i<512;i++){ #asm BCF 0x0F8B,2//LATC2=0; #endasm Buf_FFT[i]=input_b(); //чтение порта В #asm BSF 0x0F8B,2//LATC2=1; #endasm } realFFT(Buf_FFT, 512, 0); for(i=0;i<512;i+=2){ Buf_FFT[k++]=pow((Buf_FFT[i]*Buf_FFT[i]+Buf_FFT[i+1]*Buf_FFT[i+1]),0.5); } Buf_FFT[0]=0; for(i=0;i<256;i++) if(Buf_FFT[i]>max) max=Buf_FFT[i]; //ищем max for(i=0;i<256;i++) Buf_FFT[i]=236-(Buf_FFT[i]*230/max);//нормировка по max, и инвертирование перед распечаткой for(x=1;x<254;x++){ yy=y; y = Buf_FFT[x]; if (yy>y) front(x,yy,y);// Рисуем фронт if (yy<y) spad(x,yy,y); // Рисуем спад pixel(x,y,1); // Рисуем вершину } setCursorAddress(0x2581); // чистить экран clear_graphic(); } ну насчёт медленнее рисует-это я наверное погорячился.просто чем больше развёртка, тем медленнее рисует. или чем больше элементов для рисования, тем больше времени на это требуется. #define EVER ;; //приколы нашего двора Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
flann 0 9 апреля, 2008 Опубликовано 9 апреля, 2008 · Жалоба Так, на вид, почти все нормально. Но давайте для на чала отладим сам алгоритм FFT. Для этого сделаем тестовую процедуру, и заполним массив известным меандром: (я специально взял такой период (28 отсчетов) чтобы в 512 отсчетов не укладывалось ровное число периодов, иначе картинка будет слишком красивая, и далекая от реальности) void testspectr(void) { unsigned int8 x=0,y,yy; unsigned int16 i=0,max=0,k=0; setCursorAddress(0x2581); // чистить экран clear_graphic(); for(i=0;i<512;i++){ if (k<14) {Buf_FFT[i]=10;k++;} else if(k<28) {Buf_FFT[i]=230;k++;} else {Buf_FFT[i]=10;k=1;} } realFFT(Buf_FFT, 512, 0); for(i=0;i<512;i+=2){ Buf_FFT[k++]=pow((Buf_FFT[i]*Buf_FFT[i]+Buf_FFT[i+1]*Buf_FFT[i+1]),0.5); } Buf_FFT[0]=Buf_FFT[1]; for(i=0;i<256;i++) if(Buf_FFT[i]>max) max=Buf_FFT[i]; //ищем max for(i=0;i<256;i++) Buf_FFT[i]=236-(Buf_FFT[i]*230/max);//нормировка по max, и инвертирование перед распечаткой for(x=1;x<254;x++){ yy=y; y = Buf_FFT[x]; if (yy>y) front(x,yy,y);// Рисуем фронт if (yy<y) spad(x,yy,y); // Рисуем спад pixel(x,y,1); // Рисуем вершину } } Я специально не поленился, и написал программку для Borland. Все один в один. Получились следующие картинки: СИГНАЛ: СПЕКТР: P.S. Хочу посмотреть что получиться у вас ;) Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
flann 0 9 апреля, 2008 Опубликовано 9 апреля, 2008 · Жалоба фотки пока нет. график представляет из себя следующее, слева-направо с отступом от лев.края в 10 пикселей длинная закрашенная палка на весь экран толщиной в 4 пикселя,далее 17 прямоугольников при по 8 пикселей шапка 8 пикселей яма . Всё это рисуется от самого низа экрана Что-то по описанию явно бред какой-то..... приведите еще раз ф-ию realFFT(); Просто, не понятно в чем косяк - процедурка то ведь рабочая. Я же проверил... Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andreichk 0 9 апреля, 2008 Опубликовано 9 апреля, 2008 · Жалоба первое фото было получено при обозначении процедуры void realFFT(char *a, unsigned int tnn, char inversefft) а второе при void realFFT(signed int16 a[] , unsigned int tnn, char inversefft) в обоих случаях это мало похоже на ожидаемый результат при более детальном рассмотрении второго графика я замечаю интересный момент- мне кажется что первые 4 или 5 всплесков отрисовались в области первых 16ти пикселей, начиная от левого края, но почему-то каждый последующий начинался не с низу, а от какого-то другого значения.Остальной меандр- это просто мусор какой-то Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andreichk 0 9 апреля, 2008 Опубликовано 9 апреля, 2008 · Жалоба я тут подумал и мы решили, а вообще в каком диапазоне частот работает наш спектроскоп? И ещё вопрос- как эта функция передаёт значения в буфер? void realFFT(signed int16 a[] , unsigned int tnn, char inversefft) Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
flann 0 10 апреля, 2008 Опубликовано 10 апреля, 2008 · Жалоба Да... такое ощущение что у вас вообще буфер не обрабатывается.... первое фото было получено при обозначении процедуры void realFFT(char *a, unsigned int tnn, char inversefft) Так точно не правильно, лучше попробывать так: void realFFT(int *a, unsigned int tnn, char inversefft) еще в функции realFFT() есть цикл: while(m>=2&&j>m) попробуйте заменить на: while((m>=2)&&(j>m)) также в процедуре есть float переменные tempr и tempi. сделайте их int: int tempr,tempi; я тут подумал и мы решили, а вообще в каком диапазоне частот работает наш спектроскоп? Диапазон зависит от текущей частоты оцифровки (F) следующим образом: от 0 до F/2 промежуточные частоты равны: i*F/512, где 1<i<N/2 И ещё вопрос- как эта функция передаёт значения в буфер? void realFFT(signed int16 a[] , unsigned int tnn, char inversefft) Мы же ей передаем указатель на начало буфера. она присваивает его a. А дальше тупо обращается по индексам... А вообще грешить помоему уже надо на компилятор.... все-таки приведите текст вашей realFFT() может че-то в ней случайно изменилось. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться