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

Dependencies:   Array_Matrix mbed SerialTxRxIntr DSP_ADDA UIT_FFT_Real Window

Committer:
MikamiUitOpen
Date:
Thu Apr 21 05:45:48 2022 +0000
Revision:
2:2ca9f8a0f6ef
Parent:
1:d4e3f39ce206
3

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 1:d4e3f39ce206 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 2:2ca9f8a0f6ef 13 // 2022/04/21, Copyright (c) 2022 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 1:d4e3f39ce206 19 #include "FFT_Spectrogram.hpp"
MikamiUitOpen 1:d4e3f39ce206 20 #include "DoubleBuffer.hpp"
MikamiUitOpen 0:3bf11d2ab6ad 21 #include "Coefs_IIR_LP.hpp" // 縦続形 IIR フィルタの係数
MikamiUitOpen 0:3bf11d2ab6ad 22 #include "IirCascade.hpp" // 縦続形 IIR フィルタ
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 1:d4e3f39ce206 31 const int N_SMPL_ = N_FFT_/2; // 1度に標本化するデータ数
MikamiUitOpen 1:d4e3f39ce206 32 const int N_SPC_ = N_FFT_/2 + 1; // 有効なスペクトルの点数
MikamiUitOpen 1:d4e3f39ce206 33 const int RATIO_ = 10; // ダウンサンプリングの倍率:1/10
MikamiUitOpen 0:3bf11d2ab6ad 34 const int N_TX_ = 251; // PC に転送するデータ数
MikamiUitOpen 0:3bf11d2ab6ad 35
MikamiUitOpen 2:2ca9f8a0f6ef 36 DspAdcIntr myAdc_(10.24f*RATIO_, A1); // 標本化周波数: 102.4 kHz
MikamiUitOpen 0:3bf11d2ab6ad 37 IirCascade aaf_(ORDER1_, CK1_, G01_); // ダウンサンプリング用 Anti-alias フィルタ
MikamiUitOpen 1:d4e3f39ce206 38 DoubleBuffer buf_(N_SMPL_); // ダウンサンプリングの結果を保存するダブル・バッファ
MikamiUitOpen 0:3bf11d2ab6ad 39
MikamiUitOpen 0:3bf11d2ab6ad 40 // ADC 変換終了割り込みに対する割り込みサービス・ルーチン
MikamiUitOpen 0:3bf11d2ab6ad 41 void AdcIsr()
MikamiUitOpen 0:3bf11d2ab6ad 42 {
MikamiUitOpen 0:3bf11d2ab6ad 43 static int count = 0;
MikamiUitOpen 0:3bf11d2ab6ad 44
MikamiUitOpen 0:3bf11d2ab6ad 45 float xn = myAdc_.Read();
MikamiUitOpen 0:3bf11d2ab6ad 46 float yn = aaf_.Execute(xn); // ダウンサンプリング用 Anti-alias フィルタの実行
MikamiUitOpen 0:3bf11d2ab6ad 47
MikamiUitOpen 0:3bf11d2ab6ad 48 if (++count >= RATIO_)
MikamiUitOpen 0:3bf11d2ab6ad 49 {
MikamiUitOpen 0:3bf11d2ab6ad 50 buf_.Store(yn); // ダウンサンプリングされたデータをバッファへ格納
MikamiUitOpen 0:3bf11d2ab6ad 51 count = 0;
MikamiUitOpen 0:3bf11d2ab6ad 52 buf_.IsFullSwitch(); // バッファが満杯であればバッファを切り替える
MikamiUitOpen 0:3bf11d2ab6ad 53 }
MikamiUitOpen 0:3bf11d2ab6ad 54 }
MikamiUitOpen 0:3bf11d2ab6ad 55
MikamiUitOpen 0:3bf11d2ab6ad 56 int main()
MikamiUitOpen 0:3bf11d2ab6ad 57 {
MikamiUitOpen 1:d4e3f39ce206 58 SerialRxTxIntr rxTx; // PC との通信用
MikamiUitOpen 1:d4e3f39ce206 59 XferSpectrum tx(rxTx, N_TX_); // PC に転送するためのオブジェクトの生成
MikamiUitOpen 1:d4e3f39ce206 60 FftSpectropgram analyzer(N_FFT_); // スペクトログラムで使うオブジェクトの生成
MikamiUitOpen 0:3bf11d2ab6ad 61
MikamiUitOpen 1:d4e3f39ce206 62 Array<float> sn(N_FFT_, 0.0f); // スペクトル解析の対象となるデータ
MikamiUitOpen 1:d4e3f39ce206 63 Array<float> absFt(N_SPC_); // 解析結果:スペクトルの絶対値
MikamiUitOpen 0:3bf11d2ab6ad 64
MikamiUitOpen 0:3bf11d2ab6ad 65 NVIC_SetPriority(ADC_IRQn, 0); // AD変換終了割り込みの優先度が最高
MikamiUitOpen 0:3bf11d2ab6ad 66 NVIC_SetPriority(USART2_IRQn, 1);
MikamiUitOpen 0:3bf11d2ab6ad 67
MikamiUitOpen 0:3bf11d2ab6ad 68 bool ready = false; // スペクトルの計算終了で true
MikamiUitOpen 0:3bf11d2ab6ad 69 bool okGo = false; // "GO" を受信したら true
MikamiUitOpen 0:3bf11d2ab6ad 70
MikamiUitOpen 0:3bf11d2ab6ad 71 myAdc_.SetIntrVec(&AdcIsr); // AD変換終了割り込みの割り当て
MikamiUitOpen 0:3bf11d2ab6ad 72 while (true)
MikamiUitOpen 0:3bf11d2ab6ad 73 {
MikamiUitOpen 0:3bf11d2ab6ad 74 // PC からのコマンドの解析
MikamiUitOpen 0:3bf11d2ab6ad 75 if (rxTx.IsEol()) // 受信バッファのデータが有効になった場合の処理
MikamiUitOpen 0:3bf11d2ab6ad 76 {
MikamiUitOpen 0:3bf11d2ab6ad 77 string str = rxTx.GetBuffer();
MikamiUitOpen 0:3bf11d2ab6ad 78 if (str == "Spectrogram")
MikamiUitOpen 0:3bf11d2ab6ad 79 {
MikamiUitOpen 0:3bf11d2ab6ad 80 rxTx.TxString("ACK\n"); // PC からの "Spectrogram" に対して "ACK" を送信する
MikamiUitOpen 0:3bf11d2ab6ad 81 wait_ms(10);
MikamiUitOpen 0:3bf11d2ab6ad 82 rxTx.Baud(460800); // 以降は 460,800 baud
MikamiUitOpen 0:3bf11d2ab6ad 83 }
MikamiUitOpen 1:d4e3f39ce206 84 if (str.substr(0, 2) == "GO")
MikamiUitOpen 0:3bf11d2ab6ad 85 {
MikamiUitOpen 1:d4e3f39ce206 86 analyzer.SwEmphasis(str[2] == 'Y');
MikamiUitOpen 0:3bf11d2ab6ad 87 okGo = true; // データの転送要求あり
MikamiUitOpen 0:3bf11d2ab6ad 88 }
MikamiUitOpen 0:3bf11d2ab6ad 89 }
MikamiUitOpen 0:3bf11d2ab6ad 90
MikamiUitOpen 0:3bf11d2ab6ad 91 if (buf_.IsFull()) // 入力データが満杯の場合,以下の処理を行う
MikamiUitOpen 0:3bf11d2ab6ad 92 {
MikamiUitOpen 0:3bf11d2ab6ad 93 // フレームの後半のデータを前半に移動する
MikamiUitOpen 1:d4e3f39ce206 94 for (int n=0; n<N_SMPL_; n++)
MikamiUitOpen 1:d4e3f39ce206 95 sn[n] = sn[n+N_SMPL_];
MikamiUitOpen 0:3bf11d2ab6ad 96 // フレームの後半には新しいデータを格納する
MikamiUitOpen 1:d4e3f39ce206 97 for (int n=0; n<N_SMPL_; n++)
MikamiUitOpen 1:d4e3f39ce206 98 sn[n+N_SMPL_] = buf_.Get(n);
MikamiUitOpen 0:3bf11d2ab6ad 99
MikamiUitOpen 1:d4e3f39ce206 100 analyzer.Execute(sn, absFt); // スペクトル解析の実行
MikamiUitOpen 1:d4e3f39ce206 101 ready = true; // スペクトル解析終了
MikamiUitOpen 0:3bf11d2ab6ad 102 }
MikamiUitOpen 0:3bf11d2ab6ad 103
MikamiUitOpen 0:3bf11d2ab6ad 104 // 転送要求がありスペクトル解析が終了している場合にデータを PC へ転送する
MikamiUitOpen 0:3bf11d2ab6ad 105 if (okGo && ready)
MikamiUitOpen 0:3bf11d2ab6ad 106 {
MikamiUitOpen 0:3bf11d2ab6ad 107 tx.ToPC(absFt); // データを PC へ転送
MikamiUitOpen 0:3bf11d2ab6ad 108 ready = false;
MikamiUitOpen 0:3bf11d2ab6ad 109 okGo = false;
MikamiUitOpen 0:3bf11d2ab6ad 110 }
MikamiUitOpen 0:3bf11d2ab6ad 111 }
MikamiUitOpen 0:3bf11d2ab6ad 112 }