信号発生ソフトWaveGene→PCM1808モジュール(ADC入力)→FIR・IIRフイルタ→PCM5102モジュール(DAC出力)→WaveSpectraでFIR・IIRフイルタ周波数特性を確認。
①FIR・IIRフイルタ(カットオフ3KHz)の周波数特性測定【ESP32 FFT - FIRフィルタ 特性確認】【ESP32 FFT - IIRフィルタ 特性確認】
②FIR Filter Design使いカットオフ3KHzの係数を使ったFIRフィルタの周波数特性。
参考サイト
回路図
ESP32-S3 開発ボード
5Vピン → 5V出ない(入力ピン)?
(赤い線材)三端子レギュレータから直接5Vを取出しPCM1808のアナログ電圧(5V)に供給。(自己責任で)
PCM5102A - 32ビットDAC
アマゾン購入
【SCK】ブリッジ(内部クロック)【H1L】(FLT) L側 ブリッジ
【H2L】(DEMP) L側 ブリッジ
【H3L】(XSMT) H側 ブリッジ
【H4L】(FMT) L側 ブリッジ
PCM1808 - 24ビットADC
アマゾン購入
回路不明
IC周辺にコンデンサー・抵抗がついているので外付け必要ない?
SCK ー MCLK(マスタークロック)プログラムで変更可能
WaveSpectra - フィルタ無
WaveSpectra - FIRフィルタ①
WaveSpectra - FIRフィルタ②
FIR Filter Design【https://www.arc.id.au/FilterDesign.html】
ボードマネージャ
追加ボードマネージャーURLを変更
【https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json】
【esp 32】
【バージョン3.2.0】インストール
ライブラリマネージャー
●ESP32-audioI2S-master
所定のlibrariesに貼付
【i2s】
【バージョン3.2.1】インストール
プログラム Arduino IDE【ボード:ESP32S3 Dev Module】
#include <driver/i2s.h>
#define fsample 48000
#define BLOCK_SAMPLES 64
//buffers
int rxbuf[BLOCK_SAMPLES*2], txbuf[BLOCK_SAMPLES*2];
float Lch_in[BLOCK_SAMPLES], Rch_in[BLOCK_SAMPLES];
float Lch_out[BLOCK_SAMPLES], Rch_out[BLOCK_SAMPLES];
#define MUTE 40 // MUTE control (LOW: Mute)
//FIR Cutoff-3KHz LPF
// https://github.com/JR3XNW/pico-Program-Lab/blob/main/Filter_sweep_test_SpectrumDisplay_FIR.inoD
const int filterLength = 31; // Number of filter taps.
float filterBuffer[filterLength] = {0.0};
/* float firCoeffs[filterLength] = { // Put the FIR filter coefficients here.
0.001695,0.001201,-0.000905,-0.004228,-0.005427,0.0,
0.011365,0.018584,0.00825,-0.021236,-0.048939,-0.03959,
0.029858,0.145107,0.254511,0.299507,0.254511,0.145107,
0.029858,-0.03959,-0.048939,-0.021236,0.00825,0.018584,
0.011365,0.0,-0.005427,-0.004228,-0.000905,0.001201,0.001695 */
float firCoeffs[filterLength] = { //FIR Filter Design
0.000055,
-0.000318,
-0.001401,
-0.003333,
-0.005827,
-0.007995,
-0.008335,
-0.004991,
0.003764,
0.018906,
0.040112,
0.065486,
0.091722,
0.114710,
0.130454,
0.136054,
0.130454,
0.114710,
0.091722,
0.065486,
0.040112,
0.018906,
0.003764,
-0.004991,
-0.008335,
-0.007995,
-0.005827,
-0.003333,
-0.001401,
-0.000318,
0.000055
};
int bufferIndex = 0;
// Update to FIR filter function
float firFilter(float input) {
filterBuffer[bufferIndex] = input;
bufferIndex = (bufferIndex + 1) % filterLength;
float sum = 0.0;
for (int i = 0; i < filterLength; i++) {
int index = (bufferIndex - i + filterLength) % filterLength;
sum += filterBuffer[index] * firCoeffs[i];
}
return sum;
}
//IIR Cutoff-3KHz LPF
//https://github.com/JR3XNW/pico-Program-Lab/blob/main/Filter_sweep_test_SpectrumDisplay_IIR.ino
// フィルターの係数 (2次のバターワースフィルター)
const int filterOrder = 2;
double b[filterOrder + 1] = { 0.03478604, 0.06957207, 0.03478604 }; // 係数b
double a[filterOrder + 1] = { 1.0, -1.40750534, 0.54664949 }; // 係数a
double filterBufferX[filterOrder + 1] = {0.0};
double filterBufferY[filterOrder + 1] = {0.0};
// IIRフィルターの実装
double iirFilter(double input) {
// 入力をバッファに追加
for (int i = filterOrder; i > 0; i--) {
filterBufferX[i] = filterBufferX[i - 1];
filterBufferY[i] = filterBufferY[i - 1];
}
filterBufferX[0] = input;
// フィルター出力の計算
double output = 0.0;
for (int i = 0; i <= filterOrder; i++) {
output += b[i] * filterBufferX[i];
if (i > 0) {
output -= a[i] * filterBufferY[i];
}
}
filterBufferY[0] = output;
return output;
}
/*-----------------------------------------------------------------------------------------------
Setup
-------------------------------------------------------------------------------------------------*/
void setup(void) {
Serial.begin(115200);
delay(50);
pinMode(MUTE, OUTPUT);
digitalWrite(MUTE, HIGH); // unmute
// I2S setup ------------------------------------------------------------
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_RX), //I2S作業モード
.sample_rate = fsample, //I2Sサンプルレート
.bits_per_sample = (i2s_bits_per_sample_t)32, //サンプルあたりのI2Sビット
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //I2Sチャネルフォーマット
.communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_STAND_I2S), //I2S通信フォーマット
.intr_alloc_flags = 0, //割り込みを割り当てるために使用されるフラグ
.dma_buf_count = 6, //I2S DMAバッファ数
.dma_buf_len = BLOCK_SAMPLES*4, //I2S DMAバッファ長
.use_apll = false, //2SはAPLLをメインI2Sクロックとして使用し、正確なクロックを取得
.tx_desc_auto_clear = true, //データが利用できない場合にノイズを回避
.fixed_mclk = 0, //固定MCLK出力を使用するI2S
};
i2s_driver_install( I2S_NUM_0, &i2s_config, 0, NULL); //I2S ドライバーをインストールして起動
i2s_pin_config_t pin_config = {
.bck_io_num = 42, //BCK
.ws_io_num = 2, //LRC,LCK
.data_out_num = 41, //DIN
.data_in_num = 1 //OUT
};
i2s_set_pin( I2S_NUM_0, &pin_config);
}
/*-----------------------------------------------------------------------------------------------
Signal Process Loop
-------------------------------------------------------------------------------------------------*/
void loop(void) {
size_t readsize = 0;
//Input I2S DMA 受信バッファからデータを読み取り
esp_err_t res = i2s_read(I2S_NUM_0, &rxbuf[0], BLOCK_SAMPLES*2*4, &readsize, portMAX_DELAY);
if (res == ESP_OK && readsize==BLOCK_SAMPLES*2*4) {
int j=0;
for (int i=0; i<BLOCK_SAMPLES; i++) {
Lch_in[i] = (float) rxbuf[j];
Rch_in[i] = (float) rxbuf[j+1];
j+=2;
}
//-------Signal process -------------------------------
for (int i=0; i<BLOCK_SAMPLES; i++) {
Lch_in[i] = firFilter( Lch_in[i]); //firフィルタ
//Lch_in[i] = iirFilter( Lch_in[i]); //iirフィルタ
Lch_out[i] = Lch_in[i];
Rch_out[i] = Rch_in[i];
}
//------------------------------------------------------
//Output
j=0;
for (int i=0; i<BLOCK_SAMPLES; i++) {
txbuf[j] = (int) Lch_out[i];
txbuf[j+1] = (int) Rch_out[i];
j+=2;
}
//I2S DMA送信バッファにデータを書き込み
i2s_write( I2S_NUM_0, &txbuf[0], BLOCK_SAMPLES*2*4, &readsize, portMAX_DELAY);
}
}
.png)

.png)
.png)
.png)
.png)
.png)
.png)
.png)
.png)
.png)
0 件のコメント:
コメントを投稿