「ArduinoのFFTライブラリ動かしてみた。」
Arduino この間
Arduinoの寄贈ライブラリを改めて眺めてたら
見つかった
FFTライブラリ。(いつの間に公開されてた
んだろうね?)
サンプルプログラムが付いてたので、とりあえず
コンパイルして流し込んでみることに。お試し。
…どうやらFFT結果を16進数のまま吐き出す仕様に
なっているみたいなので、シリアルモニタじゃぁ
訳がわかんない状態。
あと、適当にADCからサンプリングしてFFTを掛けて
いるっていう仕様なので、どんな周波数の信号を
検出してるのかも全然不明。
これじゃぁ嫌なので、タイマ割込み使ってサンプリング
させつつ、テキスト文字出力するように変更してみた。
…とりあえずそれっぽいデータが吐き出されてきた。
うん。ただ、実数、虚数の平方和の平方根を取ってから
log(対数)取ってるので、なんとなく数字が微妙か?
対数取らずにリニアに出力するように変更してみた。
スケッチはこんな感じ。
#define LIN_OUT 1 // use the lin output function
#define FFT_N 32 // set number of point fft
#include <FFT.h> // include the library
#include
volatile int i; // index for data points
void timerIsr()
{
while(!(ADCSRA & 0x10)); // wait for adc to be ready
ADCSRA = 0xf5; // restart adc
byte m = ADCL; // fetch adc data
byte j = ADCH;
int k = (j << 8) | m; // form into an int
k -= 0x0200; // form into a signed int
k <<= 6; // form into a 16b signed int
fft_input[i] = k; // put real data into even bins
fft_input[i+1] = 0; // set odd bins to 0
i += 2;
}
void setup() {
Serial.begin(115200); // use the serial port
TIMSK0 = 0; // turn off timer0 for lower jitter
ADCSRA = 0xe5; // set the adc to free running mode
ADMUX = 0x40; // use adc0
DIDR0 = 0x01; // turn off the digital input for adc0
i = 0;
Timer1.initialize(1000); // set a timer of length 100 microseconds (10000Hz)
Timer1.attachInterrupt( timerIsr ); // attach the service routine here
}
void loop() {
while(i < FFT_N*2) {
}
cli(); // UDRE interrupt slows this way down on arduino1.0
fft_window(); // window the data for better frequency response
fft_reorder(); // reorder the data before doing the fft
fft_run(); // process the data in the fft
fft_mag_lin(); // take the output of the fft
i = 0;
for (int l=0; l<FFT_N/2; l++){
Serial.print(fft_lin_out[l]); // send out the data
Serial.print(",");
}
Serial.println();
sei();
}
ちなみに#define LIN_OUTとか、fft_mag_lin()関数とか、
出力先の配列fft_lin_outとかは、FFT.hの中身を
見ないとどれを指定すればいいかがワカラナイっぽい。
(説明書いてあるページが見当たらなかった)
まぁ、スケッチの通り32点FFTにして、窓関数を掛けて
(なんの窓か良くわかんない)、線形のまま出力として、
ADCのサンプリングはTimerOneライブラリで自由に間隔を
変えられるようにしておいた。
目下1000マイクロ秒毎(1m秒毎)に割り込み発生する
ようにしてあるので、ナイキスト周波数は500Hz。
これに、
以前作ったDDSファンクションジェネレータで
100Hzとか200Hzとか適当な周波数で信号を入れて、
FFTを掛けてみた。
確かに想定したところに値が載るのがわかってなにより。
good。
本当は、サンプルレートをもっと高くして10Kspsくらい
にしたかったんだけど、なぜかシリアル出力の文字数
(1行分の文字数)が一定以上多くなるときに、
Arduinoがフリーズを起こしてしまうことが判ったので、
とりあえず1000spsにしてある。…原因不明。
とりあえず32点FFTで数値を16個表示させるには、
このくらいのサンプリングレートが限界ギリギリ。
シリアル出力の時間が結構長く掛かるのはガッテン
承知の助だったので、サンプリング完了からシリアル出力
が済むまで割り込み禁止にしておいたんだけど、
そこらへんが何か悪さしてるみたい。良くわかんない。
TimerOneライブラリか、FFTライブラリか、どっちかが
うまく噛みあわない状態になってるんだろうな…
改めて、対数取る指定と、8ビットに切り詰める指定も
試してみた。動く、動く。
とりあえず今日はココまで。
http://akizukidenshi.com/catalog/g/gM-06255/ STM32F0DISCOVERYが800円。STM32もLPCも買ったまま
あまり手が進んでないんだよな…
http://www.sanspo.com/geino/news/20121115/eco12111512310002-n1.html なんじゃ?この前身エアバッグの電気自動車…
http://www.youtube.com/watch?v=_kK2xkyXjW4 スペースシャトルが飛んじゃったり、
http://www.youtube.com/watch?v=4QoLmpPX63Y タイファイターが飛んじゃったり、
http://www.youtube.com/watch?v=A6STlxPrwJE USSエンタープライズまで…。ラジコンって、
結構自由度高いんだな。
アンドロメダとか、あの形のまま飛ばないかな…
http://www.youtube.com/watch?v=KxLuShpaKrQ ダクテットファンじゃなくてジェットエンジンの
音だよな。これも。
ラジコン用ジェットエンジンが小さくなったのか、
それとも機体がでかいのか…
2