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