FFT アナライザ このプログラムの説明は,CQ出版社「トランジスタ技術」の2021年10月号から開始された連載記事「STM32マイコンではじめるPC計測」の中にあります.このプログラムといっしょに使うPC側のプログラムについても同誌を参照してください.
Dependencies: Array_Matrix mbed SerialTxRxIntr DSP_ADDA UIT_FFT_Real Window
main.cpp@0:e5fc70976c00, 2021-09-09 (annotated)
- Committer:
- MikamiUitOpen
- Date:
- Thu Sep 09 08:52:33 2021 +0000
- Revision:
- 0:e5fc70976c00
- Child:
- 1:d9dbfbe95c8d
1
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
MikamiUitOpen | 0:e5fc70976c00 | 1 | //--------------------------------------------------------------------- |
MikamiUitOpen | 0:e5fc70976c00 | 2 | // FFT によるスペクトルアナライザ,白色雑音発生器付き (Nucleo-F446RE 用) |
MikamiUitOpen | 0:e5fc70976c00 | 3 | // ● PC 側のプログラム: "CQ_FFT_Analyzer" |
MikamiUitOpen | 0:e5fc70976c00 | 4 | // ● ボーレート |
MikamiUitOpen | 0:e5fc70976c00 | 5 | // ポートの検索時: 9,600 baud |
MikamiUitOpen | 0:e5fc70976c00 | 6 | // ポートの検索後: 460,800 baud |
MikamiUitOpen | 0:e5fc70976c00 | 7 | // |
MikamiUitOpen | 0:e5fc70976c00 | 8 | // ● 入力: A1 |
MikamiUitOpen | 0:e5fc70976c00 | 9 | // ● 白色雑音の出力:A2 |
MikamiUitOpen | 0:e5fc70976c00 | 10 | // |
MikamiUitOpen | 0:e5fc70976c00 | 11 | // 2021/07/11, Copyright (c) 2021 MIKAMI, Naoki |
MikamiUitOpen | 0:e5fc70976c00 | 12 | //--------------------------------------------------------------------- |
MikamiUitOpen | 0:e5fc70976c00 | 13 | |
MikamiUitOpen | 0:e5fc70976c00 | 14 | #include <string> |
MikamiUitOpen | 0:e5fc70976c00 | 15 | #include "Array.hpp" |
MikamiUitOpen | 0:e5fc70976c00 | 16 | #include "DSP_AdcIntr.hpp" |
MikamiUitOpen | 0:e5fc70976c00 | 17 | #include "DSP_Dac.hpp" |
MikamiUitOpen | 0:e5fc70976c00 | 18 | #include "FFT_Analyzer.hpp" |
MikamiUitOpen | 0:e5fc70976c00 | 19 | #include "DoubleBuffer.hpp" |
MikamiUitOpen | 0:e5fc70976c00 | 20 | #include "Coefs_IIR_LP.hpp" // 縦続形 IIR フィルタの係数 |
MikamiUitOpen | 0:e5fc70976c00 | 21 | #include "IirCascade.hpp" // 縦続形 IIR フィルタ |
MikamiUitOpen | 0:e5fc70976c00 | 22 | #include "MSeq16.hpp" // M 系列発生器 |
MikamiUitOpen | 0:e5fc70976c00 | 23 | #include "XferSpectrum.hpp" |
MikamiUitOpen | 0:e5fc70976c00 | 24 | using namespace Mikami; |
MikamiUitOpen | 0:e5fc70976c00 | 25 | |
MikamiUitOpen | 0:e5fc70976c00 | 26 | #ifndef __STM32F446xx_H |
MikamiUitOpen | 0:e5fc70976c00 | 27 | #error "Use Nucleo-F446RE" |
MikamiUitOpen | 0:e5fc70976c00 | 28 | #endif |
MikamiUitOpen | 0:e5fc70976c00 | 29 | |
MikamiUitOpen | 0:e5fc70976c00 | 30 | const int N_FFT_ = 1024; // FFT の点数 |
MikamiUitOpen | 0:e5fc70976c00 | 31 | const int N_FRAME_ = N_FFT_; // 1フレーム当たり標本化するデータ数 |
MikamiUitOpen | 0:e5fc70976c00 | 32 | const int N_SPC_ = N_FFT_/2 + 1; // 有効なスペクトルの点数 |
MikamiUitOpen | 0:e5fc70976c00 | 33 | const int RATIO_ = 10; // オーバーサンプリングの倍率 |
MikamiUitOpen | 0:e5fc70976c00 | 34 | const int N_TX_ = 501; // PC に転送するデータ数 |
MikamiUitOpen | 0:e5fc70976c00 | 35 | |
MikamiUitOpen | 0:e5fc70976c00 | 36 | DoubleBuffer<float> buf_(N_FRAME_); // AD の結果を保存するバッファ |
MikamiUitOpen | 0:e5fc70976c00 | 37 | DspAdcIntr myAdc_(10.24f*RATIO_, A1); // 標本化周波数: 102.4 kHz |
MikamiUitOpen | 0:e5fc70976c00 | 38 | DspDac myDac; |
MikamiUitOpen | 0:e5fc70976c00 | 39 | IirCascade df1_(ORDER1_, CK1_, G01_); // ダウンサンプリング用 Anti-alias フィルタ |
MikamiUitOpen | 0:e5fc70976c00 | 40 | IirCascade df2_(ORDER2_, CK2_, G02_); // 白色雑音発生用低域通貨フィルタ |
MikamiUitOpen | 0:e5fc70976c00 | 41 | MSeq16 mSeq_; // M 系列信号発生器(N = 16) |
MikamiUitOpen | 0:e5fc70976c00 | 42 | |
MikamiUitOpen | 0:e5fc70976c00 | 43 | // ADC 変換終了割り込みに対する割り込みサービス・ルーチン |
MikamiUitOpen | 0:e5fc70976c00 | 44 | void AdcIsr() |
MikamiUitOpen | 0:e5fc70976c00 | 45 | { |
MikamiUitOpen | 0:e5fc70976c00 | 46 | static int count = 0; |
MikamiUitOpen | 0:e5fc70976c00 | 47 | |
MikamiUitOpen | 0:e5fc70976c00 | 48 | float xn = myAdc_.Read(); // AD 変換された値を取得 |
MikamiUitOpen | 0:e5fc70976c00 | 49 | |
MikamiUitOpen | 0:e5fc70976c00 | 50 | float noise = df2_.Execute(mSeq_.Execute()); |
MikamiUitOpen | 0:e5fc70976c00 | 51 | myDac.Write(0.8f*noise); // 白色雑音出力 |
MikamiUitOpen | 0:e5fc70976c00 | 52 | |
MikamiUitOpen | 0:e5fc70976c00 | 53 | float yn = df1_.Execute(xn); // ダウンサンプリング用 Anti-alias フィルタの実行 |
MikamiUitOpen | 0:e5fc70976c00 | 54 | |
MikamiUitOpen | 0:e5fc70976c00 | 55 | if (++count >= RATIO_) |
MikamiUitOpen | 0:e5fc70976c00 | 56 | { |
MikamiUitOpen | 0:e5fc70976c00 | 57 | buf_.Store(yn); // ダウンサンプリングされたデータをバッファへ格納 |
MikamiUitOpen | 0:e5fc70976c00 | 58 | count = 0; |
MikamiUitOpen | 0:e5fc70976c00 | 59 | buf_.IsFullSwitch(); // バッファが満杯であればバッファを切り替える |
MikamiUitOpen | 0:e5fc70976c00 | 60 | } |
MikamiUitOpen | 0:e5fc70976c00 | 61 | } |
MikamiUitOpen | 0:e5fc70976c00 | 62 | |
MikamiUitOpen | 0:e5fc70976c00 | 63 | int main() |
MikamiUitOpen | 0:e5fc70976c00 | 64 | { |
MikamiUitOpen | 0:e5fc70976c00 | 65 | SerialRxTxIntr rxTx; // PC との通信用,最初は 9600 baud |
MikamiUitOpen | 0:e5fc70976c00 | 66 | XferSpectrum tx(rxTx, N_TX_); // PC に転送するためのオブジェクトの生成 |
MikamiUitOpen | 0:e5fc70976c00 | 67 | FftAnalyzer analyzer(N_FFT_); // FFT によるスペクトル解析オブジェクトの生成 |
MikamiUitOpen | 0:e5fc70976c00 | 68 | |
MikamiUitOpen | 0:e5fc70976c00 | 69 | Array<float> sn(N_FFT_, 0.0f); // スペクトル解析の対象となるデータ |
MikamiUitOpen | 0:e5fc70976c00 | 70 | Array<float> absFt(N_SPC_); // 解析結果:スペクトルの絶対値 |
MikamiUitOpen | 0:e5fc70976c00 | 71 | |
MikamiUitOpen | 0:e5fc70976c00 | 72 | NVIC_SetPriority(ADC_IRQn, 0); // AD変換終了割り込みの優先度が最高 |
MikamiUitOpen | 0:e5fc70976c00 | 73 | NVIC_SetPriority(USART2_IRQn, 1); |
MikamiUitOpen | 0:e5fc70976c00 | 74 | |
MikamiUitOpen | 0:e5fc70976c00 | 75 | bool ready = false; // スペクトルの計算終了で true |
MikamiUitOpen | 0:e5fc70976c00 | 76 | bool okGo = false; // "GO" を受信したら true |
MikamiUitOpen | 0:e5fc70976c00 | 77 | |
MikamiUitOpen | 0:e5fc70976c00 | 78 | myAdc_.SetIntrVec(&AdcIsr); // AD変換終了割り込みの割り当て |
MikamiUitOpen | 0:e5fc70976c00 | 79 | while (true) |
MikamiUitOpen | 0:e5fc70976c00 | 80 | { |
MikamiUitOpen | 0:e5fc70976c00 | 81 | // PC からのコマンドの解析 |
MikamiUitOpen | 0:e5fc70976c00 | 82 | if (rxTx.IsEol()) // 受信バッファのデータが有効になった場合の処理 |
MikamiUitOpen | 0:e5fc70976c00 | 83 | { |
MikamiUitOpen | 0:e5fc70976c00 | 84 | string str = rxTx.GetBuffer(); |
MikamiUitOpen | 0:e5fc70976c00 | 85 | if (str == "FFTAnalyzer") |
MikamiUitOpen | 0:e5fc70976c00 | 86 | { |
MikamiUitOpen | 0:e5fc70976c00 | 87 | rxTx.TxString("ACK\n"); // PC からの "FFTAnalyzer" に対して "ACK" を送信 |
MikamiUitOpen | 0:e5fc70976c00 | 88 | wait_ms(10); |
MikamiUitOpen | 0:e5fc70976c00 | 89 | rxTx.Baud(460800); // 以降は 460,800 baud |
MikamiUitOpen | 0:e5fc70976c00 | 90 | } |
MikamiUitOpen | 0:e5fc70976c00 | 91 | if (str.substr(0, 2) == "GO") |
MikamiUitOpen | 0:e5fc70976c00 | 92 | okGo = true; // データの転送要求あり |
MikamiUitOpen | 0:e5fc70976c00 | 93 | } |
MikamiUitOpen | 0:e5fc70976c00 | 94 | |
MikamiUitOpen | 0:e5fc70976c00 | 95 | if (buf_.IsFull()) // 入力データが満杯の場合,以下の処理を行う |
MikamiUitOpen | 0:e5fc70976c00 | 96 | { |
MikamiUitOpen | 0:e5fc70976c00 | 97 | for (int n=0; n<N_FRAME_; n++) sn[n] = buf_.Get(n); |
MikamiUitOpen | 0:e5fc70976c00 | 98 | analyzer.Execute(sn, absFt); // スペクトル解析の実行 |
MikamiUitOpen | 0:e5fc70976c00 | 99 | ready = true; // スペクトル解析終了 |
MikamiUitOpen | 0:e5fc70976c00 | 100 | } |
MikamiUitOpen | 0:e5fc70976c00 | 101 | |
MikamiUitOpen | 0:e5fc70976c00 | 102 | // 転送要求がありスペクトル解析が終了している場合にデータを PC へ転送する |
MikamiUitOpen | 0:e5fc70976c00 | 103 | if (okGo && ready) |
MikamiUitOpen | 0:e5fc70976c00 | 104 | { |
MikamiUitOpen | 0:e5fc70976c00 | 105 | tx.ToPC(absFt); // データを PC へ転送 |
MikamiUitOpen | 0:e5fc70976c00 | 106 | ready = false; |
MikamiUitOpen | 0:e5fc70976c00 | 107 | okGo = false; |
MikamiUitOpen | 0:e5fc70976c00 | 108 | } |
MikamiUitOpen | 0:e5fc70976c00 | 109 | } |
MikamiUitOpen | 0:e5fc70976c00 | 110 | } |