STM32 Nucleoでデジタル信号処理を試してみた(2)
前回はADC-DACを素通りさせるだけの動作をさせましたが、今回はDSPライブラリを用いて信号処理を行うところまで設定します。STM32ではCMSIS-DSP Libraryを使用することができます。フィルタの演算自体は、バッファ配列の更新、配列の内積と単純ですが、DSPライブラリを用いることで高速な処理が実現されます。DSPライブラリの設定
設定はこちらのページの内容を参考にしています。(1)ライブラリの追加
ファイル名 arm_cortexM4lf_math.lib
from: C:\Users\(ユーザー名)\STM32Cube\Repository\STM32Cube_FW_F4_V1.26.1\Drivers\CMSIS\Lib\ARM
to: (プロジェクトのフォルダ)
ファイル名 libarm_cortexM4lf_math.a
from: C:\Users\(ユーザー名)\STM32Cube\Repository\STM32Cube_FW_F4_V1.26.1\Drivers\CMSIS\Lib\GCC
to: (プロジェクトのフォルダ)
(2)ヘッダファイルの追加
ファイル名
・arm_common_tables.h
・arm_const_structs.h
・arm_math.h
from: C:\Users\(ユーザー名)\STM32Cube\Repository\STM32Cube_FW_F4_V1.26.1\Drivers\CMSIS\DSP\Include
to: (プロジェクトのフォルダ)\Core\Inc
(3)ライブラリの設定
プロジェクトを右クリックしsettingウィンドウを開きます
・C/C++Build --> Setting --> ToolSettings --> MCU GCC Linker --> Libraries(右上) --> Add..
arm_cortexM4lf_mathと入力
・Library search path(右下) --> Add.. --> Workspace --> 現在のプロジェクトを選択
${workspace_loc:/${ProjName}}が追加されるのを確認
ソースコードの設定・編集
(4)ソースコードの編集前回のコードに以下の赤色部分を追加・変更します
(4-1) ヘッダファイルのインクルード
/* USER CODE BEGIN Includes */
#define ARM_MATH_CM4
#include "arm_math.h"
#include "arm_const_structs.h"
#define LEN 11 // タップ数
/* USER CODE END Includes */
(4-2)変数の宣言
DSPライブラリではq15型などが規定の型となっているので、今回q15型として宣言します。 さらにDSPライブラリの関数を使用するため、追加でいくつかの変数(**(a)~(c))を定義する必要があります。 (これらの変数がどのように使用されているのか私も理解できていません...) こちらのページに日本語の説明がありますのでご参照ください。
フィルタの係数は計算ツール(例えばこちらのページ)で計算します。得られた定数は、(215/タップ数)を乗じます。今回は正規化周波数0.2にカットオフを持つ11タップLPFとします。 ただし、今回の設定ではサンプリング間隔を明に指定していないため正規化周波数が環境依存してしまうことにご留意ください。
/* USER CODE BEGIN 1 */
q15_t val;// 入力値を格納
q15_t val_out;// 出力値を格納
q15_t Coeff[LEN] = {0, -378, -739, 1901, 8224, 11913, 8224, 1901, -739, -378, 0}; // **(a)フィルタ定数
q15_t State[LEN];// **(b)
arm_fir_instance_q15 Instance;// **(c)
arm_fir_init_q15(&Instance, LEN, Coeff, State, 1);//フィルタの初期化
/* USER CODE END 1 */
(4-3)while(1)ループ内の編集
入力信号にLPFを演算し出力するものとします。
/* USER CODE BEGIN 3 */
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 0);
val = HAL_ADC_GetValue(&hadc1)-2048;//値の中心を2048から0に変更
arm_fir_fast_q15(&Instance, &val, &val_out, 1);//FIRフィルタの演算を実行
HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, val_out_r+2048);//値の中心を2048から0に変更
/* USER CODE END 3 */
動作確認
PA1に1kHz正弦波+8kHz正弦波のアナログ信号を入力し、PA4から出力される信号を観察してみます。 黄色が入力、赤色が出力です。入力信号に対し出力信号では8kHzの成分が減衰し、LPF特性を有していることが分かります。ここまでくると様々なフィルタ定数を試して楽しむことができます。