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

Dependencies:   Array_Matrix mbed SerialTxRxIntr UIT_FFT_Real DSP_ADDA

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 //---------------------------------------------------------------------
00002 //  FFT によるスペクトルアナライザ,白色雑音発生器付き (Nucleo-F446RE 用)
00003 //
00004 //      ● ST-Link Firmware の V2.J37.M26 で動作確認
00005 //
00006 //      ● ST-Link Firmware のアップグレードには stsw-link007_V2-37-26.zip
00007 //        に含まれている "ST-LinkUpgrade.exe" を使う 
00008 //
00009 //      ● PC 側のプログラム: "F446_FFT_Analyzer"
00010 //      ● ボーレート: 460800 baud
00011 //      ● 受信データの文字列の終了マーク: "\r"
00012 //
00013 //      ● 入力:  A1
00014 //      ● 白色雑音の出力:A2
00015 //
00016 //  2021/01/08, Copyright (c) 2021 MIKAMI, Naoki
00017 //---------------------------------------------------------------------
00018 
00019 #include "mbed.h"
00020 #include <string>
00021 #include "Array.hpp"
00022 #include "DSP_AdcIntr.hpp"
00023 #include "DSP_Dac.hpp"
00024 #include "FFT_Analyzer.hpp"
00025 #include "DoubleBuffer.hpp"
00026 #include "Coefs_IIR_LP.hpp" // 縦続形 IIR フィルタの係数
00027 #include "IirCascade.hpp"   // 縦続形 IIR フィルタ
00028 #include "MSeq16.hpp"       // M 系列発生器
00029 #include "Xfer.hpp"
00030 using namespace Mikami;
00031 
00032 const int N_FFT_ = 1024;            // FFT の点数
00033 const int N_FRAME_ = N_FFT_;        // 1フレーム当たり標本化するデータ数
00034 const int N_SPC_ = N_FFT_/2 + 1;    // 有効なスペクトルの点数
00035 const int RATIO_ = 10;              // オーバーサンプリングの倍率
00036 
00037 DoubleBuffer<float, N_FRAME_> buf_(0);  // AD の結果を保存するバッファ
00038 DspAdcIntr myAdc_(10*RATIO_, A1);       // 標本化周波数: 100 kHz
00039 DspDac myDac;
00040 IirCascade df1_(ORDER1_, CK1_, G01_);   // ダウンサンプリング用 Anti-alias フィルタ
00041 IirCascade df2_(ORDER2_, CK2_, G02_);   // 白色雑音発生用
00042 MSeq16 mSeq_;
00043 
00044 // ADC 変換終了割り込みに対する割り込みサービス・ルーチン
00045 void AdcIsr()
00046 {
00047     static int count = 0;
00048 
00049     float xn = myAdc_.Read();
00050 
00051     float noise = df2_.Execute(mSeq_.Execute());
00052     myDac.Write(0.8f*noise);    // 白色雑音出力
00053 
00054     float yn = df1_.Execute(xn);    // ダウンサンプリング用 Anti-alias フィルタの実行
00055 
00056     if (++count >= RATIO_)
00057     {
00058         buf_.Store(yn);         // ダウンサンプリングされたデータをバッファへ格納
00059         count = 0;
00060         buf_.IfFullSwitch();    // バッファが満杯であればバッファを切り替える
00061     }
00062 }
00063 
00064 int main()
00065 {
00066     SerialRxTxIntr rxTx(32, 460800);    // PC との通信用
00067     Xfer tx(rxTx, N_SPC_);              // PC に転送するためのオブジェクトの生成
00068     FftAnalyzer analyzer(N_FFT_);       // FFT によるスペクトル解析オブジェクトの生成
00069 
00070     Array<float> sn(N_FFT_, 0.0f);      // スペクトル解析の対象となるデータ
00071     Array<float> absFt(N_SPC_);         // 解析結果:スペクトルの絶対値
00072 
00073     NVIC_SetPriority(ADC_IRQn, 0);      // AD変換終了割り込みの優先度が最高
00074     NVIC_SetPriority(USART2_IRQn, 1);
00075 
00076     bool ready = false; // スペクトルの計算終了で true
00077     bool okGo = false;  // "GO" を受信したら true
00078     float magn = 1;     // 転送する際の倍率
00079 
00080     myAdc_.SetIntrVec(&AdcIsr); // AD変換終了割り込みの割り当て
00081     while (true)
00082     {
00083         // PC からのコマンドの解析
00084         if (rxTx.IsEol())      // 受信バッファのデータが有効になった場合の処理
00085         {
00086             string str = rxTx.GetBuffer();
00087             if (str == "FFTAnalyzer")
00088                 rxTx.TxString("ACK\n"); // PC からの "FFTAnalyzer" に対して "ACK" を送信
00089             if (str.substr(0, 2) == "GO")
00090             {
00091                 okGo = true;  // データの転送要求あり
00092                 float x = (float)atoi(str.erase(0, 2).c_str());
00093                 magn = powf(10, x/20.0f);
00094             }
00095         }
00096 
00097         if (buf_.IsFull())  // 入力データが満杯の場合,以下の処理を行う
00098         {
00099             for (int n=0; n<N_FRAME_; n++) sn[n] = buf_.Get(n);
00100             analyzer.Execute(sn, absFt);    // スペクトル解析の実行
00101             tx.Convert(absFt, magn);        // スペクトル解析の結果を転送する形式に変換
00102             ready = true;                   // スペクトル解析終了
00103         }
00104 
00105         // 転送要求がありスペクトル解析が終了している場合にデータを PC へ転送する
00106         if (okGo && ready)
00107         {
00108             tx.ToPC();      // データを PC へ転送
00109             ready = false;
00110             okGo = false;
00111         }
00112     }
00113 }