2
0

More than 3 years have passed since last update.

ESP32の内部ADC値をi2sで取得した場合のサンプリングレート確認

Posted at

1. はじめに

ESP32の内部ADCをi2s経由で取得すると、(Arduino-IDEで)割り込みとanalogReadを使った場合よりも高いサンプリングレートを設定できます。そのサンプリングレートを確認しました。

2. 結論

このコードを使った場合は、.sample_rateに設定した値の約2倍のレートでサンプリングが行われている。ただし、正確な2倍ではなく、この点の原因は不明。

3. 検証

このコード(#define I2S_SAMPLE_RATE 38000*2 つまり、76000 にしています)を書き込んだESP32のピン33番に、agilent (現 Keysight Technologies) 33500Bから1Vオフセット開放端1.5Vppで、1kHzの方形波や正弦波を入力しました。入力信号の確認はTektronix MDO-4104を用いて目視および信号解析機能で行いました。 シリアルモニタから取得した波形データは87040点。これをDFTし、パワースペクトラムのピーク位置を確認しました。なお、DFT前の波形には、DCオフセットを除去しblackmam窓をかけました。

取得した波形(方形波)
waveform.png

パワースペクトラム(方形波)
spctrumall.png

スペクトラムのピーク付近を拡大
spctrum.png

ピーク位置$P_{peak}$、サンプリング周波数$f_s$、参照信号の周波数$f_c$、全データ数$N_{dat}$の関係は、次になります。
$$
f_s = f_c \cdot \frac{N_{dat}}{P_{peak}}
$$

ピークは方形波、正弦波共に575でした。データ点は87040で、ピークは1kHzを指しているので、サンプリングレートは
151374 Sa/s
となります。

念のため、時間波形の時間間隔は目視で約150サンプルでした。1kHzの周期1msが150サンプルということで、ここからも約150kSa/sとなることが判ります。

.sample_rateに設定した値は、76000なので、この値の約2倍のサンプルレートになっていることになります。
ただし、152000に対して差がある理由についてはまだ判ってません。(ピークが1サンプルずれた場合の結果の差は263Hz程度なので、計算上の誤差よりも大きい)

4. 感想

ESP32に基準信号を入力して、内部ADCをi2sで取得する際のサンプリングレートを確認しました。ESP32の内部ADCをi2sで読み込むモードについては、私自身、まだ理解しきれていません。1つずつ確認しながら進めていくことが重要だと、今回の結果から痛感しました。

参考

確認で利用したpythonスクリプト

analyFreq.py
import numpy as np

fname='squar1kHz0.txt'
org = np.loadtxt(fname)
strm = org - org.mean()
Ndat=len(strm)
spc = np.fft.fft(strm * np.blackman(Ndat))
sps = np.real(spc)**2 + np.imag(spc)**2
psp = 10*np.log10(sps)
vmax=np.max(psp)
pmax=np.argmax(psp)
nfc = pmax/Ndat

fs = 38000*4
cfc=nfc*fs
fc=1000
cfs=fc/nfc

print(pmax)
print(cfs)
print(cfc)


import matplotlib.pyplot as plt

plt.figure(1)
plt.plot(psp[1:1000])
plt.axis([0,1000,60,np.max(psp)*1.01])
plt.xlabel('freq [*1/87040*fs Hz]')
plt.ylabel('relative power [dB]')
plt.show(block=False)
plt.savefig('spctrum.png')

plt.figure(2)
plt.plot(org[1:500])
plt.axis([0,500,0,np.max(org)*1.01])
plt.xlabel('time [*1/fs s]')
plt.ylabel('voltage [*3.3/4096 V]')
plt.show(block=False)
plt.savefig('waveform.png')

plt.figure(3)
plt.plot(np.arange(-1*Ndat/2,Ndat/2,1)/Ndat ,np.fft.fftshift(psp))
#plt.axis([0,1000,60,np.max(psp)*1.01])
plt.xlabel('normalized frequency')
plt.ylabel('relative power [dB]')
plt.show(block=False)
plt.savefig('spctrumall.png')

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0