ESP32의 내부 ADC 값을 i2s로 취득한 경우의 샘플링 레이트 확인

10685 단어 adcESP32I2S

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창을 걸었습니다.

취득한 파형(방형파)


파워 스펙트럼 (방형파)


스펙트럼의 피크 부근 확대


피크 위치 $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로 읽는 모드에 대해서는 나 자신이 아직 이해할 수 없습니다. 하나씩 확인하면서 진행해 나가는 것이 중요하다고 이번 결과에서 통감했습니다.

참고



확인에 사용한 파이썬 스크립트

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')

좋은 웹페이지 즐겨찾기