The experiment using this program is introduced on "Interface" No.4, CQ publishing Co.,Ltd, 2015. 本プログラムを使った実験は,CQ出版社のインターフェース 2015年4月号で紹介しています.
Dependencies: DSProcessingIO mbed
FFT_Sampling.cpp@1:655f6a72e47e, 2014-07-29 (annotated)
- Committer:
- CQpub0Mikami
- Date:
- Tue Jul 29 06:52:38 2014 +0000
- Revision:
- 1:655f6a72e47e
- Parent:
- 0:c740f515e0b7
ver.2
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
CQpub0Mikami | 0:c740f515e0b7 | 1 | //-------------------------------------------------------------- |
CQpub0Mikami | 0:c740f515e0b7 | 2 | // Sampling and Spectrum analysis using FFT |
CQpub0Mikami | 0:c740f515e0b7 | 3 | // Copyright (c) 2014 MIKAMI, Naoki, 2014/06/29 |
CQpub0Mikami | 0:c740f515e0b7 | 4 | //-------------------------------------------------------------- |
CQpub0Mikami | 0:c740f515e0b7 | 5 | |
CQpub0Mikami | 0:c740f515e0b7 | 6 | #include "mbed.h" |
CQpub0Mikami | 0:c740f515e0b7 | 7 | #include "AdcInternal.hpp" |
CQpub0Mikami | 0:c740f515e0b7 | 8 | #include "fftReal.hpp" |
CQpub0Mikami | 0:c740f515e0b7 | 9 | |
CQpub0Mikami | 0:c740f515e0b7 | 10 | using namespace Mikami; |
CQpub0Mikami | 0:c740f515e0b7 | 11 | |
CQpub0Mikami | 0:c740f515e0b7 | 12 | // sampling frequency |
CQpub0Mikami | 0:c740f515e0b7 | 13 | const float FS_ = 10.0e3f; |
CQpub0Mikami | 0:c740f515e0b7 | 14 | const int N_FFT_ = 256; |
CQpub0Mikami | 0:c740f515e0b7 | 15 | |
CQpub0Mikami | 0:c740f515e0b7 | 16 | Adc adc_(A0); |
CQpub0Mikami | 0:c740f515e0b7 | 17 | Ticker timer_; // for timer interrupt |
CQpub0Mikami | 0:c740f515e0b7 | 18 | DigitalIn userButton_(USER_BUTTON); |
CQpub0Mikami | 0:c740f515e0b7 | 19 | FftReal fft_(N_FFT_); |
CQpub0Mikami | 0:c740f515e0b7 | 20 | |
CQpub0Mikami | 0:c740f515e0b7 | 21 | float xn_[N_FFT_+1]; |
CQpub0Mikami | 0:c740f515e0b7 | 22 | volatile int count_; |
CQpub0Mikami | 0:c740f515e0b7 | 23 | |
CQpub0Mikami | 0:c740f515e0b7 | 24 | // Sampling |
CQpub0Mikami | 0:c740f515e0b7 | 25 | void TimerIsr() |
CQpub0Mikami | 0:c740f515e0b7 | 26 | { |
CQpub0Mikami | 0:c740f515e0b7 | 27 | xn_[count_] = adc_.Read(); // AD |
CQpub0Mikami | 0:c740f515e0b7 | 28 | count_++; |
CQpub0Mikami | 0:c740f515e0b7 | 29 | } |
CQpub0Mikami | 0:c740f515e0b7 | 30 | |
CQpub0Mikami | 0:c740f515e0b7 | 31 | int main() |
CQpub0Mikami | 0:c740f515e0b7 | 32 | { |
CQpub0Mikami | 0:c740f515e0b7 | 33 | printf("Ready.\r\n"); |
CQpub0Mikami | 0:c740f515e0b7 | 34 | while(userButton_); // wait for user button pressed |
CQpub0Mikami | 0:c740f515e0b7 | 35 | printf("User button is pushed!\r\n"); |
CQpub0Mikami | 0:c740f515e0b7 | 36 | |
CQpub0Mikami | 0:c740f515e0b7 | 37 | count_ = 0; |
CQpub0Mikami | 0:c740f515e0b7 | 38 | timer_.attach_us(&TimerIsr, 1.0e6f/FS_); |
CQpub0Mikami | 0:c740f515e0b7 | 39 | while (count_ < N_FFT_+1); |
CQpub0Mikami | 0:c740f515e0b7 | 40 | timer_.detach(); // Detach TimerIsr |
CQpub0Mikami | 0:c740f515e0b7 | 41 | printf("End of Sampling.\r\n"); |
CQpub0Mikami | 0:c740f515e0b7 | 42 | |
CQpub0Mikami | 0:c740f515e0b7 | 43 | float xnW[N_FFT_]; // for windowed data |
CQpub0Mikami | 0:c740f515e0b7 | 44 | Complex yk[N_FFT_/2+1]; |
CQpub0Mikami | 0:c740f515e0b7 | 45 | float yDb[N_FFT_/2+1]; |
CQpub0Mikami | 0:c740f515e0b7 | 46 | |
CQpub0Mikami | 0:c740f515e0b7 | 47 | // Windowing |
CQpub0Mikami | 0:c740f515e0b7 | 48 | float pi2N = 6.283185f/N_FFT_; |
CQpub0Mikami | 0:c740f515e0b7 | 49 | for (int n=0; n<N_FFT_; n++) |
CQpub0Mikami | 0:c740f515e0b7 | 50 | xnW[n] = (xn_[n+1] - xn_[n])*(0.54f - 0.46f*cosf(pi2N*n)); |
CQpub0Mikami | 0:c740f515e0b7 | 51 | |
CQpub0Mikami | 0:c740f515e0b7 | 52 | // Execute FFT |
CQpub0Mikami | 0:c740f515e0b7 | 53 | fft_.Execute(xnW, yk); |
CQpub0Mikami | 0:c740f515e0b7 | 54 | |
CQpub0Mikami | 0:c740f515e0b7 | 55 | // Square of absolute value of FFT |
CQpub0Mikami | 0:c740f515e0b7 | 56 | for (int n=0; n<=N_FFT_/2; n++) |
CQpub0Mikami | 0:c740f515e0b7 | 57 | yDb[n] = norm(yk[n]); |
CQpub0Mikami | 0:c740f515e0b7 | 58 | |
CQpub0Mikami | 0:c740f515e0b7 | 59 | // Get maximum value of yk[n] |
CQpub0Mikami | 0:c740f515e0b7 | 60 | float max = 0; |
CQpub0Mikami | 0:c740f515e0b7 | 61 | for (int n=0; n<=N_FFT_/2; n++) |
CQpub0Mikami | 0:c740f515e0b7 | 62 | max = (yDb[n] > max) ? yDb[n] : max; |
CQpub0Mikami | 0:c740f515e0b7 | 63 | |
CQpub0Mikami | 0:c740f515e0b7 | 64 | // Normalized spectra to dB |
CQpub0Mikami | 0:c740f515e0b7 | 65 | for (int n=0; n<=N_FFT_/2; n++) |
CQpub0Mikami | 0:c740f515e0b7 | 66 | if (yDb[n] > 0) |
CQpub0Mikami | 0:c740f515e0b7 | 67 | yDb[n] = 10.0f*log10f(yDb[n]/max); |
CQpub0Mikami | 0:c740f515e0b7 | 68 | else |
CQpub0Mikami | 0:c740f515e0b7 | 69 | yDb[n] = -100.0f; |
CQpub0Mikami | 0:c740f515e0b7 | 70 | |
CQpub0Mikami | 0:c740f515e0b7 | 71 | // Output to terminal |
CQpub0Mikami | 0:c740f515e0b7 | 72 | float dt = 1.0e3f/FS_; |
CQpub0Mikami | 0:c740f515e0b7 | 73 | float df = FS_/N_FFT_; |
CQpub0Mikami | 0:c740f515e0b7 | 74 | for (int n=0; n<N_FFT_; n++) |
CQpub0Mikami | 0:c740f515e0b7 | 75 | { |
CQpub0Mikami | 0:c740f515e0b7 | 76 | if (n <= N_FFT_/2) |
CQpub0Mikami | 0:c740f515e0b7 | 77 | printf("%3d, %4.1f,%8.4f, %10.4f,%6.1f\r\n", |
CQpub0Mikami | 0:c740f515e0b7 | 78 | n, n*dt, xn_[n], n*df, yDb[n]); |
CQpub0Mikami | 0:c740f515e0b7 | 79 | else |
CQpub0Mikami | 0:c740f515e0b7 | 80 | printf("%3d, %4.1f,%8.4f\r\n", n, n*dt, xn_[n]); |
CQpub0Mikami | 0:c740f515e0b7 | 81 | } |
CQpub0Mikami | 0:c740f515e0b7 | 82 | } |
CQpub0Mikami | 0:c740f515e0b7 | 83 |