スペクトログラム このプログラムの説明は,CQ出版社「トランジスタ技術」の2021年10月号から開始された連載記事「STM32マイコンではじめるPC計測」の中にあります.このプログラムといっしょに使うPC側のプログラムについても同誌を参照してください.

Dependencies:   Array_Matrix mbed SerialTxRxIntr DSP_ADDA UIT_FFT_Real Window

Committer:
MikamiUitOpen
Date:
Thu Sep 09 08:55:42 2021 +0000
Revision:
0:3bf11d2ab6ad
Child:
1:d4e3f39ce206
1

Who changed what in which revision?

UserRevisionLine numberNew 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 }