FFT によるスペクトル解析器

Dependencies:   Array_Matrix mbed SerialTxRxIntr UIT_FFT_Real DSP_ADDA

Committer:
MikamiUitOpen
Date:
Fri Jan 08 02:27:46 2021 +0000
Revision:
0:91cc5a03f0ca
1

Who changed what in which revision?

UserRevisionLine numberNew contents of line
MikamiUitOpen 0:91cc5a03f0ca 1 //---------------------------------------------------------------------
MikamiUitOpen 0:91cc5a03f0ca 2 // FFT によるスペクトルアナライザ,白色雑音発生器付き (Nucleo-F446RE 用)
MikamiUitOpen 0:91cc5a03f0ca 3 //
MikamiUitOpen 0:91cc5a03f0ca 4 // ● ST-Link Firmware の V2.J37.M26 で動作確認
MikamiUitOpen 0:91cc5a03f0ca 5 //
MikamiUitOpen 0:91cc5a03f0ca 6 // ● ST-Link Firmware のアップグレードには stsw-link007_V2-37-26.zip
MikamiUitOpen 0:91cc5a03f0ca 7 // に含まれている "ST-LinkUpgrade.exe" を使う
MikamiUitOpen 0:91cc5a03f0ca 8 //
MikamiUitOpen 0:91cc5a03f0ca 9 // ● PC 側のプログラム: "F446_FFT_Analyzer"
MikamiUitOpen 0:91cc5a03f0ca 10 // ● ボーレート: 460800 baud
MikamiUitOpen 0:91cc5a03f0ca 11 // ● 受信データの文字列の終了マーク: "\r"
MikamiUitOpen 0:91cc5a03f0ca 12 //
MikamiUitOpen 0:91cc5a03f0ca 13 // ● 入力: A1
MikamiUitOpen 0:91cc5a03f0ca 14 // ● 白色雑音の出力:A2
MikamiUitOpen 0:91cc5a03f0ca 15 //
MikamiUitOpen 0:91cc5a03f0ca 16 // 2021/01/08, Copyright (c) 2021 MIKAMI, Naoki
MikamiUitOpen 0:91cc5a03f0ca 17 //---------------------------------------------------------------------
MikamiUitOpen 0:91cc5a03f0ca 18
MikamiUitOpen 0:91cc5a03f0ca 19 #include "mbed.h"
MikamiUitOpen 0:91cc5a03f0ca 20 #include <string>
MikamiUitOpen 0:91cc5a03f0ca 21 #include "Array.hpp"
MikamiUitOpen 0:91cc5a03f0ca 22 #include "DSP_AdcIntr.hpp"
MikamiUitOpen 0:91cc5a03f0ca 23 #include "DSP_Dac.hpp"
MikamiUitOpen 0:91cc5a03f0ca 24 #include "FFT_Analyzer.hpp"
MikamiUitOpen 0:91cc5a03f0ca 25 #include "DoubleBuffer.hpp"
MikamiUitOpen 0:91cc5a03f0ca 26 #include "Coefs_IIR_LP.hpp" // 縦続形 IIR フィルタの係数
MikamiUitOpen 0:91cc5a03f0ca 27 #include "IirCascade.hpp" // 縦続形 IIR フィルタ
MikamiUitOpen 0:91cc5a03f0ca 28 #include "MSeq16.hpp" // M 系列発生器
MikamiUitOpen 0:91cc5a03f0ca 29 #include "Xfer.hpp"
MikamiUitOpen 0:91cc5a03f0ca 30 using namespace Mikami;
MikamiUitOpen 0:91cc5a03f0ca 31
MikamiUitOpen 0:91cc5a03f0ca 32 const int N_FFT_ = 1024; // FFT の点数
MikamiUitOpen 0:91cc5a03f0ca 33 const int N_FRAME_ = N_FFT_; // 1フレーム当たり標本化するデータ数
MikamiUitOpen 0:91cc5a03f0ca 34 const int N_SPC_ = N_FFT_/2 + 1; // 有効なスペクトルの点数
MikamiUitOpen 0:91cc5a03f0ca 35 const int RATIO_ = 10; // オーバーサンプリングの倍率
MikamiUitOpen 0:91cc5a03f0ca 36
MikamiUitOpen 0:91cc5a03f0ca 37 DoubleBuffer<float, N_FRAME_> buf_(0); // AD の結果を保存するバッファ
MikamiUitOpen 0:91cc5a03f0ca 38 DspAdcIntr myAdc_(10*RATIO_, A1); // 標本化周波数: 100 kHz
MikamiUitOpen 0:91cc5a03f0ca 39 DspDac myDac;
MikamiUitOpen 0:91cc5a03f0ca 40 IirCascade df1_(ORDER1_, CK1_, G01_); // ダウンサンプリング用 Anti-alias フィルタ
MikamiUitOpen 0:91cc5a03f0ca 41 IirCascade df2_(ORDER2_, CK2_, G02_); // 白色雑音発生用
MikamiUitOpen 0:91cc5a03f0ca 42 MSeq16 mSeq_;
MikamiUitOpen 0:91cc5a03f0ca 43
MikamiUitOpen 0:91cc5a03f0ca 44 // ADC 変換終了割り込みに対する割り込みサービス・ルーチン
MikamiUitOpen 0:91cc5a03f0ca 45 void AdcIsr()
MikamiUitOpen 0:91cc5a03f0ca 46 {
MikamiUitOpen 0:91cc5a03f0ca 47 static int count = 0;
MikamiUitOpen 0:91cc5a03f0ca 48
MikamiUitOpen 0:91cc5a03f0ca 49 float xn = myAdc_.Read();
MikamiUitOpen 0:91cc5a03f0ca 50
MikamiUitOpen 0:91cc5a03f0ca 51 float noise = df2_.Execute(mSeq_.Execute());
MikamiUitOpen 0:91cc5a03f0ca 52 myDac.Write(0.8f*noise); // 白色雑音出力
MikamiUitOpen 0:91cc5a03f0ca 53
MikamiUitOpen 0:91cc5a03f0ca 54 float yn = df1_.Execute(xn); // ダウンサンプリング用 Anti-alias フィルタの実行
MikamiUitOpen 0:91cc5a03f0ca 55
MikamiUitOpen 0:91cc5a03f0ca 56 if (++count >= RATIO_)
MikamiUitOpen 0:91cc5a03f0ca 57 {
MikamiUitOpen 0:91cc5a03f0ca 58 buf_.Store(yn); // ダウンサンプリングされたデータをバッファへ格納
MikamiUitOpen 0:91cc5a03f0ca 59 count = 0;
MikamiUitOpen 0:91cc5a03f0ca 60 buf_.IfFullSwitch(); // バッファが満杯であればバッファを切り替える
MikamiUitOpen 0:91cc5a03f0ca 61 }
MikamiUitOpen 0:91cc5a03f0ca 62 }
MikamiUitOpen 0:91cc5a03f0ca 63
MikamiUitOpen 0:91cc5a03f0ca 64 int main()
MikamiUitOpen 0:91cc5a03f0ca 65 {
MikamiUitOpen 0:91cc5a03f0ca 66 SerialRxTxIntr rxTx(32, 460800); // PC との通信用
MikamiUitOpen 0:91cc5a03f0ca 67 Xfer tx(rxTx, N_SPC_); // PC に転送するためのオブジェクトの生成
MikamiUitOpen 0:91cc5a03f0ca 68 FftAnalyzer analyzer(N_FFT_); // FFT によるスペクトル解析オブジェクトの生成
MikamiUitOpen 0:91cc5a03f0ca 69
MikamiUitOpen 0:91cc5a03f0ca 70 Array<float> sn(N_FFT_, 0.0f); // スペクトル解析の対象となるデータ
MikamiUitOpen 0:91cc5a03f0ca 71 Array<float> absFt(N_SPC_); // 解析結果:スペクトルの絶対値
MikamiUitOpen 0:91cc5a03f0ca 72
MikamiUitOpen 0:91cc5a03f0ca 73 NVIC_SetPriority(ADC_IRQn, 0); // AD変換終了割り込みの優先度が最高
MikamiUitOpen 0:91cc5a03f0ca 74 NVIC_SetPriority(USART2_IRQn, 1);
MikamiUitOpen 0:91cc5a03f0ca 75
MikamiUitOpen 0:91cc5a03f0ca 76 bool ready = false; // スペクトルの計算終了で true
MikamiUitOpen 0:91cc5a03f0ca 77 bool okGo = false; // "GO" を受信したら true
MikamiUitOpen 0:91cc5a03f0ca 78 float magn = 1; // 転送する際の倍率
MikamiUitOpen 0:91cc5a03f0ca 79
MikamiUitOpen 0:91cc5a03f0ca 80 myAdc_.SetIntrVec(&AdcIsr); // AD変換終了割り込みの割り当て
MikamiUitOpen 0:91cc5a03f0ca 81 while (true)
MikamiUitOpen 0:91cc5a03f0ca 82 {
MikamiUitOpen 0:91cc5a03f0ca 83 // PC からのコマンドの解析
MikamiUitOpen 0:91cc5a03f0ca 84 if (rxTx.IsEol()) // 受信バッファのデータが有効になった場合の処理
MikamiUitOpen 0:91cc5a03f0ca 85 {
MikamiUitOpen 0:91cc5a03f0ca 86 string str = rxTx.GetBuffer();
MikamiUitOpen 0:91cc5a03f0ca 87 if (str == "FFTAnalyzer")
MikamiUitOpen 0:91cc5a03f0ca 88 rxTx.TxString("ACK\n"); // PC からの "FFTAnalyzer" に対して "ACK" を送信
MikamiUitOpen 0:91cc5a03f0ca 89 if (str.substr(0, 2) == "GO")
MikamiUitOpen 0:91cc5a03f0ca 90 {
MikamiUitOpen 0:91cc5a03f0ca 91 okGo = true; // データの転送要求あり
MikamiUitOpen 0:91cc5a03f0ca 92 float x = (float)atoi(str.erase(0, 2).c_str());
MikamiUitOpen 0:91cc5a03f0ca 93 magn = powf(10, x/20.0f);
MikamiUitOpen 0:91cc5a03f0ca 94 }
MikamiUitOpen 0:91cc5a03f0ca 95 }
MikamiUitOpen 0:91cc5a03f0ca 96
MikamiUitOpen 0:91cc5a03f0ca 97 if (buf_.IsFull()) // 入力データが満杯の場合,以下の処理を行う
MikamiUitOpen 0:91cc5a03f0ca 98 {
MikamiUitOpen 0:91cc5a03f0ca 99 for (int n=0; n<N_FRAME_; n++) sn[n] = buf_.Get(n);
MikamiUitOpen 0:91cc5a03f0ca 100 analyzer.Execute(sn, absFt); // スペクトル解析の実行
MikamiUitOpen 0:91cc5a03f0ca 101 tx.Convert(absFt, magn); // スペクトル解析の結果を転送する形式に変換
MikamiUitOpen 0:91cc5a03f0ca 102 ready = true; // スペクトル解析終了
MikamiUitOpen 0:91cc5a03f0ca 103 }
MikamiUitOpen 0:91cc5a03f0ca 104
MikamiUitOpen 0:91cc5a03f0ca 105 // 転送要求がありスペクトル解析が終了している場合にデータを PC へ転送する
MikamiUitOpen 0:91cc5a03f0ca 106 if (okGo && ready)
MikamiUitOpen 0:91cc5a03f0ca 107 {
MikamiUitOpen 0:91cc5a03f0ca 108 tx.ToPC(); // データを PC へ転送
MikamiUitOpen 0:91cc5a03f0ca 109 ready = false;
MikamiUitOpen 0:91cc5a03f0ca 110 okGo = false;
MikamiUitOpen 0:91cc5a03f0ca 111 }
MikamiUitOpen 0:91cc5a03f0ca 112 }
MikamiUitOpen 0:91cc5a03f0ca 113 }