FFT アナライザ このプログラムの説明は,CQ出版社「トランジスタ技術」の2021年10月号から開始された連載記事「STM32マイコンではじめるPC計測」の中にあります.このプログラムといっしょに使うPC側のプログラムについても同誌を参照してください.
Dependencies: Array_Matrix mbed SerialTxRxIntr DSP_ADDA UIT_FFT_Real Window
Revision 1:d9dbfbe95c8d, committed 2021-11-03
- Comitter:
- MikamiUitOpen
- Date:
- Wed Nov 03 01:29:16 2021 +0000
- Parent:
- 0:e5fc70976c00
- Commit message:
- 2
Changed in this revision
diff -r e5fc70976c00 -r d9dbfbe95c8d DoubleBuffer.hpp --- a/DoubleBuffer.hpp Thu Sep 09 08:52:33 2021 +0000 +++ b/DoubleBuffer.hpp Wed Nov 03 01:29:16 2021 +0000 @@ -2,7 +2,7 @@ // ダブル・バッファの template クラス // バッファに2次元配列(Matrix クラス)を使用 // -// 2021/05/22, Copyright (c) 2021 MIKAMI, Naoki +// 2021/10/22, Copyright (c) 2021 MIKAMI, Naoki //-------------------------------------------------------- #ifndef DOUBLE_BUFFER_HPP @@ -11,19 +11,19 @@ #include "Matrix.hpp" using namespace Mikami; -template<class T> class DoubleBuffer +class DoubleBuffer { public: // コンストラクタ - explicit DoubleBuffer(int size, T initialValue = 0) + explicit DoubleBuffer(int size, float initialValue = 0) : N_(size), buf_(2, size, initialValue), ping_(0), pong_(1), index_(0), full_(false) {} // データを格納 - void Store(T data) { buf_[ping_][index_++] = data; } + void Store(float data) { buf_[ping_][index_++] = data; } // 出力バッファからデータの取り出し - T Get(int n) const { return buf_[pong_][n]; } + float Get(int n) const { return buf_[pong_][n]; } // バッファが満杯でバッファを切り替える void IsFullSwitch() @@ -46,7 +46,7 @@ private: const int N_; // バッファのサイズ - Matrix<T> buf_; // バッファ + Matrix<float> buf_; // バッファ int ping_, pong_; // バッファ切替用 int index_; // 入力データのカウンタ bool full_; // 満杯の場合 true
diff -r e5fc70976c00 -r d9dbfbe95c8d IIR_Filter/Coefs_IIR_LP.hpp --- a/IIR_Filter/Coefs_IIR_LP.hpp Thu Sep 09 08:52:33 2021 +0000 +++ b/IIR_Filter/Coefs_IIR_LP.hpp Wed Nov 03 01:29:16 2021 +0000 @@ -1,7 +1,7 @@ //----------------------------------------------------- // 縦続形 IIR フィルタの次数と係数の定義 // -// 2021/06/01, Copyright (c) 2021 MIKAMI, Naoki +// 2021/10/08, Copyright (c) 2021 MIKAMI, Naoki //----------------------------------------------------- #include "Biquad.hpp" @@ -28,8 +28,8 @@ const float G01_ = 1.232249E-03f; // 利得定数 // 白色雑音発生器で使うフィルタ -// 標本化周波数が 100 kHz の場合, -// 100/(4π) ≒8.15 kHz 以上で +// 標本化周波数が 102.4 kHz の場合, +// 102.4/(4π) ≒ 8.15 kHz 以上で // 少なくとも 60 dB 減衰させる LPF // 低域通過フィルタ
diff -r e5fc70976c00 -r d9dbfbe95c8d MSeq16.hpp --- a/MSeq16.hpp Thu Sep 09 08:52:33 2021 +0000 +++ b/MSeq16.hpp Wed Nov 03 01:29:16 2021 +0000 @@ -1,7 +1,7 @@ //--------------------------------------------------------- -// M 系列信号発生器(N = 16) +// M 系列信号発生器(N = 16) // -// 2020/10/17, Copyright (c) 2020 MIKAMI, Naoki +// 2021/09/28, Copyright (c) 2021 MIKAMI, Naoki //--------------------------------------------------------- #include "mbed.h" @@ -11,32 +11,25 @@ namespace Mikami { - class MSeq16 - { - public: - MSeq16() : reg_(1) {} + class MSeq16 + { + public: + MSeq16() : reg_(1) {} - // 戻り値: 1 => 1, 0 => -1 - int Execute() - { - if ((reg_ & B_M_) == B_M_) - { - reg_ = ((reg_ ^ XOR_) << 1) | 1; // 1 の場合の処理 - return 1; - } - else - { - reg_ = reg_ << 1; // 0 の場合の処理 - return -1; - } - } - private: - static const uint16_t XOR_ = (1 << (2-1)) - | (1 << (3-1)) - | (1 << (5-1)); // XOR の位置に対応する定数 - static const uint16_t B_M_ = 1 << (16-1); // 16 段目に相当するビットを調べる - - uint16_t reg_; - }; + // 戻り値: 0 => -0.5, 1 => 0.5 + float Execute() + { + msb_ = reg_ >> 15; + reg_ = ((reg_ ^ XOR_[msb_]) << 1) | msb_; + return RET_[msb_]; + } + private: + static const uint16_t XOR_[2]; // XOR の一方の入力 + static const float RET_[2]; // 戻り値として使用 + uint16_t reg_; // 16 段の D フリップ・フロップに対応 + uint16_t msb_; // 16 段目に相当するビット + }; + const uint16_t MSeq16::XOR_[2] = { 0, 0x16 }; + const float MSeq16::RET_[2] = { -0.5f, 0.5f }; } -#endif // MSEQ16_HPP \ No newline at end of file +#endif // MSEQ16_HPP \ No newline at end of file
diff -r e5fc70976c00 -r d9dbfbe95c8d MyFFT_Analyzer/FFT_Analyzer.hpp --- a/MyFFT_Analyzer/FFT_Analyzer.hpp Thu Sep 09 08:52:33 2021 +0000 +++ b/MyFFT_Analyzer/FFT_Analyzer.hpp Wed Nov 03 01:29:16 2021 +0000 @@ -1,7 +1,7 @@ //------------------------------------------------------- // FFT を使ってスペクトル解析を行うクラス(ヘッダ) // -// 2021/05/22, Copyright (c) 2021 MIKAMI, Naoki +// 2021/10/19, Copyright (c) 2021 MIKAMI, Naoki //------------------------------------------------------- #ifndef FFT_ANALYZER_HPP @@ -17,7 +17,7 @@ { public: // nFft: FFT のデータ点の数 - FftAnalyzer(int nFft); + explicit FftAnalyzer(int nFft); virtual ~FftAnalyzer() {} void Execute(const Array<float> &xn, Array<float> &absFt);
diff -r e5fc70976c00 -r d9dbfbe95c8d main.cpp --- a/main.cpp Thu Sep 09 08:52:33 2021 +0000 +++ b/main.cpp Wed Nov 03 01:29:16 2021 +0000 @@ -8,7 +8,7 @@ // ● 入力: A1 // ● 白色雑音の出力:A2 // -// 2021/07/11, Copyright (c) 2021 MIKAMI, Naoki +// 2021/10/22, Copyright (c) 2021 MIKAMI, Naoki //--------------------------------------------------------------------- #include <string> @@ -30,14 +30,14 @@ const int N_FFT_ = 1024; // FFT の点数 const int N_FRAME_ = N_FFT_; // 1フレーム当たり標本化するデータ数 const int N_SPC_ = N_FFT_/2 + 1; // 有効なスペクトルの点数 -const int RATIO_ = 10; // オーバーサンプリングの倍率 +const int RATIO_ = 10; // ダウンサンプリングの倍率:1/10 const int N_TX_ = 501; // PC に転送するデータ数 -DoubleBuffer<float> buf_(N_FRAME_); // AD の結果を保存するバッファ +DoubleBuffer buf_(N_FRAME_); // ダウンサンプリングの結果を保存するバッファ DspAdcIntr myAdc_(10.24f*RATIO_, A1); // 標本化周波数: 102.4 kHz -DspDac myDac; +DspDac myDac_; IirCascade df1_(ORDER1_, CK1_, G01_); // ダウンサンプリング用 Anti-alias フィルタ -IirCascade df2_(ORDER2_, CK2_, G02_); // 白色雑音発生用低域通貨フィルタ +IirCascade df2_(ORDER2_, CK2_, G02_); // 白色雑音発生用低域通過フィルタ MSeq16 mSeq_; // M 系列信号発生器(N = 16) // ADC 変換終了割り込みに対する割り込みサービス・ルーチン @@ -48,7 +48,7 @@ float xn = myAdc_.Read(); // AD 変換された値を取得 float noise = df2_.Execute(mSeq_.Execute()); - myDac.Write(0.8f*noise); // 白色雑音出力 + myDac_.Write(1.6f*noise); // 白色雑音出力 float yn = df1_.Execute(xn); // ダウンサンプリング用 Anti-alias フィルタの実行