「シリアルプロッタを作る」でプロッタを作成したので、フーリエ変換を行うプログラムも作ってみました。使用している言語はProcessingです。
FFT変換プログラムはFFT.javaのものを使わせてもらいました。
動作画面
プログラム RS232CgraphFFT03.pde
プログラム fft.pde
FFT変換プログラムはFFT.javaのものを使わせてもらいました。
動作画面
プログラム RS232CgraphFFT03.pde
- // シリアルFFTアナライザ
- // シリアル入力の値をフーリエ変換する
- //
- // 参考サイト http://shirotsuku.sakura.ne.jp/blog/?p=192
- // http://hp.vector.co.jp/authors/VA046927/fft4gjava.html
- // https://www.ee.columbia.edu/~ronw/code/MEAPsoft/doc/html/FFT_8java-source.html
- //
- //
- import processing.serial.*;
- float gscale = 10; // 縦軸の倍率
- float goffset = 30; //オフセット
- float fmag = 2; //横軸の倍率
- int samplingrate = 1000; //サンプリングレート
- int displayxsize = 1000; //ディスプレイの横幅
- int displayysize = 600; //ディスプレイの高さ
- String comport = "COM5"; //シリアルポート
- int comspeed = 115200; //通信速度
- //fft data size 2^N
- int DATASIZE = 1024;
- Serial myPort;
- float val;
- float [] x = new float[DATASIZE]; //グラフ用データ x:時間
- float [] y1 = new float[DATASIZE]; //グラフ用データ y:電圧
- float [] y2 = new float[DATASIZE]; //グラフ用データ y:電圧
- //FFT用
- int fftdatasize = DATASIZE;
- FFT fft = new FFT(fftdatasize);
- float[] fftdata1r = new float[fftdatasize]; //data1実数部
- float[] fftdata1i = new float[fftdatasize]; //data1虚数部
- float[] fftdata2r = new float[fftdatasize]; //data2実数部
- float[] fftdata2i = new float[fftdatasize]; //data2虚数部
- float[] fftdata1 = new float[fftdatasize]; //data1絶対値
- float[] fftdata2 = new float[fftdatasize]; //data2絶対値
- void setup()
- {
- frameRate(50); //20msec毎にグラフを更新
- size(displayxsize, displayysize);
- myPort = new Serial(this, comport, comspeed);
- textSize(20);
- //グラフ用データの初期化
- for (int i = 0; i < x.length; i++) {
- x[i] = (float)i * (float)(displayxsize-100)/(float)DATASIZE*fmag;
- y1[i] = 0;
- y2[i] = 0;
- }
- }
- //縦軸の数値の加工 対数化
- float dispfunc(float data)
- {
- float ans;
- ans = gscale *( log(data) + goffset);
- return ans;
- }
- void draw()
- {
- background(0);
- //グラフエリアの描画
- fill(255);
- text((int)(samplingrate/fmag) + "Hz", displayxsize - 80, displayysize-10);
- float t = DATASIZE/1000;
- text("0Hz", 30, displayysize-10);
- fill(0, 255, 0);
- for (int i = 0; i < fftdata1r.length; i++)
- {
- float[] wnd = fft.getWindow();
- fftdata1[i] = (fftdata1r[i]*fftdata1r[i]+fftdata1i[i]*fftdata1i[i]);
- fftdata2[i] = (fftdata2r[i]*fftdata2r[i]+fftdata2i[i]*fftdata2i[i]);
- fftdata1r[i] = y1[i] * wnd[i];
- fftdata2r[i] = y2[i] * wnd[i];
- fftdata1i[i] = fftdata2i[i]=0;
- }
- fft.fft(fftdata1r, fftdata1i);
- fft.fft(fftdata2r, fftdata2i);
- //グラフのプロット
- pushMatrix();
- translate(50, displayysize-50);
- scale(1, -1);
- fill(0);
- stroke(255);
- rect(0, 0, displayxsize-100, displayysize-94);
- stroke(0, 255, 0);
- strokeWeight(1);
- for (int i = 0; i < x.length/fmag - 1; i++) {
- line(x[i], dispfunc(fftdata1[i]), x[i+1], dispfunc(fftdata1[i+1]));
- }
- stroke(255, 0, 0);
- for (int i = 0; i < x.length/fmag - 1; i++) {
- line(x[i], dispfunc(fftdata2[i]), x[i+1], dispfunc(fftdata2[i+1]));
- }
- popMatrix();
- }
- int bufsize = 512;
- char[] buf = new char[bufsize];
- int i = 0;
- void serialEvent(Serial myPort) {
- char c = char(myPort.read());
- if ((i<bufsize)&&(c!='\n'))
- {
- buf[i] = c;
- i++;
- } else
- {
- buf[i]='\0';
- i=0;
- String s = new String(buf);
- float data[] = float(s.split(",", 0));
- //グラフ用データの更新
- for (int i = 0; i < y1.length - 1; i++) {
- y1[i] = y1[i+1];
- y2[i] = y2[i+1];
- }
- y1[y1.length - 1] = data[0];
- y2[y2.length - 1] = data[1];
- }
- }
プログラム fft.pde
- /*
- * Copyright 2006-2007 Columbia University.
- *
- * This file is part of MEAPsoft.
- *
- * MEAPsoft is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * MEAPsoft is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with MEAPsoft; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- * See the file "COPYING" for the text of the license.
- */
- public class FFT {
- int n, m;
- // Lookup tables. Only need to recompute when size of FFT changes.
- float[] cos;
- float[] sin;
- float[] window;
- public FFT(int n) {
- this.n = n;
- this.m = (int)(log(n) / log(2));
- // Make sure n is a power of 2
- if (n != (1<<m))
- throw new RuntimeException("FFT length must be power of 2");
- // precompute tables
- cos = new float[n/2];
- sin = new float[n/2];
- for (int i=0; i<n/2; i++) {
- cos[i] = cos(-2*PI*i/n);
- sin[i] = sin(-2*PI*i/n);
- }
- makeWindow();
- }
- protected void makeWindow() {
- // Make a blackman window:
- // w(n)=0.42-0.5cos{(2*PI*n)/(N-1)}+0.08cos{(4*PI*n)/(N-1)};
- window = new float[n];
- for (int i = 0; i < window.length; i++)
- window[i] = 0.42 - 0.5 * cos(2*PI*i/(n-1))
- + 0.08 * cos(4*PI*i/(n-1));
- }
- public float[] getWindow() {
- return window;
- }
- /***************************************************************
- * fft.c
- * Douglas L. Jones
- * University of Illinois at Urbana-Champaign
- * January 19, 1992
- * http://cnx.rice.edu/content/m12016/latest/
- *
- * fft: in-place radix-2 DIT DFT of a complex input
- *
- * input:
- * n: length of FFT: must be a power of two
- * m: n = 2**m
- * input/output
- * x: float array of length n with real part of data
- * y: float array of length n with imag part of data
- *
- * Permission to copy and use this program is granted
- * as long as this header is included.
- ****************************************************************/
- public void fft(float[] x, float[] y)
- {
- int i, j, k, n1, n2, a;
- float c, s, e, t1, t2;
- // Bit-reverse
- j = 0;
- n2 = n/2;
- for (i=1; i < n - 1; i++) {
- n1 = n2;
- while ( j >= n1 ) {
- j = j - n1;
- n1 = n1/2;
- }
- j = j + n1;
- if (i < j) {
- t1 = x[i];
- x[i] = x[j];
- x[j] = t1;
- t1 = y[i];
- y[i] = y[j];
- y[j] = t1;
- }
- }
- // FFT
- n1 = 0;
- n2 = 1;
- for (i=0; i < m; i++) {
- n1 = n2;
- n2 = n2 + n2;
- a = 0;
- for (j=0; j < n1; j++) {
- c = cos[a];
- s = sin[a];
- a += 1 << (m-i-1);
- for (k=j; k < n; k=k+n2) {
- t1 = c*x[k+n1] - s*y[k+n1];
- t2 = s*x[k+n1] + c*y[k+n1];
- x[k+n1] = x[k] - t1;
- y[k+n1] = y[k] - t2;
- x[k] = x[k] + t1;
- y[k] = y[k] + t2;
- }
- }
- }
- }
- }
※コメント投稿者のブログIDはブログ作成者のみに通知されます