카테고리 없음

아이패턴, 정합필터, BER, Eb/N0, CNR

아마추어맨 2025. 4. 20. 12:21

여러분~ 안녕하세요!

조기대선 국면으로 정국이 안정이 되고 있는 와중이라 참으로 다행입니다!

개인적으로는 최근 4번째 코로나를 껶으며, 무기력과 두통, 몸살(특히 허리통증)과 치열한 전투를 치렀던 것 같아요. 점점 코로나는 독해지고, 나의 면역력은 약해지는 것 같아,,, 항상 규칙적인 운동과 체중조절을 해야겠다는 다짐을 절실히 했어요!

 

그럼,,, 이제 오랜만에 포스팅을 시작해 보겠습니다. ㄱㄱ

오래전부터 생각해왔던 숙제같은 주제인데, 밀린 숙제를 오늘 다 해치워버리고 진도 좀 빼겠습니다.ㅎㅎㅎ

먼저 용어정리는 아래 위키피디아를  참고해주시고, 아래 파이썬 예제(BPSK)를 가지고 구체적으로 살펴볼게요.

 

전체적인 절차는 아래 그림과 같고,,, 여기서는 1만 비트를 랜덤생성하여, BPSK 신호로 변조하고, RRC(Root Raised Cosine) 필터로 파일성형된 펄스열 신호와 스펙트럼, 아이패턴를 관찰합니다. 그리고 노이즈가 추가된 무선채널을 통과한 신호에 동일한 RRC 정합필터 출력을 검출하고, 판별한 결과 BER을 계산해 보겠습니다!

Assume sample rate is 1 Hz, Applying 8 samples per symbol.

So f_sample = 1 Hz , R_symbol=1/8 [bps] , BPSK baseband 1/2 [bit/Hz]

import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import correlate, resample_poly
from scipy.special import erfc

# this part came from pulse shaping exercise
num_symbols = 10000
sps = 8
bits = np.random.randint(0, 2, num_symbols) # Our data to be transmitted, 1's and 0's
pulse_train = np.array([])
for bit in bits:
    pulse = np.zeros(sps)
    pulse[0] = bit*2-1 # set the first value to either a 1 or -1
    pulse_train = np.concatenate((pulse_train, pulse)) # add the 8 samples to the samples
# Create our raised-cosine filter
num_taps = 161   #101  
beta = 0  #0.35 #0
Ts = sps # symbol time, Assume sample rate is 1 Hz, so sample period is 1, so *symbol* period is 8
t = np.arange(-num_taps//2+1, num_taps//2+1) # remember it's not inclusive of final number
h = np.sinc(t/Ts) * np.cos(np.pi*beta*t/Ts) / (1 - (2*beta*t/Ts)**2)
rh = np.sqrt(1) * h/np.sqrt(sum(h**2))
sc = (np.sin(np.pi*t/Ts)/(np.pi*t/Ts))   # np.sinc(t/Ts)

# Filter our samples, in order to apply the pulse shaping
samples = np.convolve(pulse_train, rh)
fig2, (ax2, ax3) = plt.subplots(nrows=2, num=2)
fig2.suptitle('Pulse Shaping(8 samples per symbol)')
i=np.arange(0,len(samples))
x = samples[:sps*100]
p=np.arange(num_taps//2, num_symbols*sps + num_taps//2, sps)
ax2.plot(i[:sps*100], x, '.-', label='origin samaples')
ax2.plot(p[:100], samples[p][:100], '.', label='origin bit')
f = np.fft.fftfreq(len(x), 1)
Xf = 1/len(x) * np.fft.fft(x)
ax3.plot(f, 20*np.log10(abs(Xf)))
ax3.set_ylim([-70, -20])
plt.show(block=False)

plt.figure(num=3)
plt.title('Eye diagrams')  # Eye pattern
for j in p[::100] : plt.plot(range(2*sps+1), samples[j-8:j+9])
plt.ylim([-1, 1])
plt.axvline(8, -1, 1, color='red', linestyle=':')
plt.show(block=False)

n = (np.random.randn(samples.shape[0]) + 1j*np.random.randn(samples.shape[0]))/np.sqrt(2) # AWGN with unity power
n_ms = 0.2
n *= np.sqrt(n_ms)
samples = samples + n
print('samples power = ', sum(rh**2)/num_taps)
print('noise power = ', np.var(n))
my_EbN0 = sum(rh[rh.shape[0]//2-sps : rh.shape[0]//2+sps]**2)/(np.var(n))
print('Eb/N0 = ', my_EbN0)
BER = 1/2*erfc(np.sqrt(my_EbN0))
error = sum((samples[p]>0)!=bits)
print('BER = ', BER)

plt.figure(num=5)
plt.title('Matched Filter')
corr = correlate(samples.real, rh, mode='same')
plt.plot(p[bits==1], corr[p][bits==1], 'r.')
plt.plot(p[bits==0], corr[p][bits==0], 'k.')
error = sum((corr[p]>0)!=bits)
plt.text(0, 3, error)
print('my BER = ', error/num_symbols)
plt.show(block=False)

fig6, ax6 = plt.subplots(num=6)
fig6.suptitle('Bit-error rate(BER) vs Eb/N0 curves')
EbN0_dB = np.arange(0,10, 0.1)
EbN0 = 10**(EbN0_dB/10)
BER = 1/2*erfc(np.sqrt(EbN0))
ax6.semilogy(EbN0_dB, BER)
ax6.semilogy(10*np.log10(my_EbN0), error/num_symbols, 'x')
ax6.set_xlabel("Eb/N0_dB")
ax6.set_ylabel("BER")
plt.show(block=False)

 

1. 파일성형 심볼열, 스펙트럼(No AWGN)
2. 아이 다이어그램(아이패턴)
3. 정합필터 판별
4. BPSK/QPSK BER 표시

 

결과를 리뷰해 볼게요!

noise power =  0.200250

Eb/N0 =  4.554634                                                                           ※  N0는 1Hz 대역폭에서의 잡음 스펙트럼 밀도

은 1Hz 대역폭에서의 잡음 스펙트럼 밀도

Eb/N0_dB = 6.5845

BER =  0.0014   ( 이론값 BER =  0.001271 )

 

1. 부가백색가우시안( Additive White Gaussian Noise ) 잡음이 없는 순수 파일성형 펄스열이라 sps 마다 null 값이 됩니다.

2. 아이패턴은 순수 파일성형 펄스를 2 심볼값으로 누적해서 표시했습니다. 지터없이 정확하게 sps 마다 null값이 관찰됩니다.

3. 무선채널 신호와 정합필터의 상관을 구해서 비트를 판별합니다. 여기서는 14개 비트가 오판되었네요.

4. 거의 이론값에 근사한 BER 실험결과가 나왔습니다. 단 beta=0 일때만(sinc함수) 이론값을 추종하는데, 이는 채널 내 스펙트럼이 플랫하지 못하면 부가백색가우시안( Additive White Gaussian Noise ) 잡음 하에서 계산이 무의미 할 것 같습니다.

 

마지막으로 

반송파대잡음비 CNR_dB = Eb/N0 * R/B = 10*np.log10(4.554634 * 0.125/0.1225) = 6.672 dB 계산됩니다.

관찰할 수 있는 대충 이런 의미를 갖습니다. (CNR은 조금 바뀌었어요)

파일성형 심볼열의 스펙트럼(with AWGN)

 

도움된다면, 인사한번 부탁드립니다. 응원은 큰 힘이 되니까요.^^

 

 

<참고자료>

1. Eye pattern - Wikipedia

2. Matched filter - Wikipedia

3. Bit error rate - Wikipedia

4. Eb/N0 - Wikipedia

5. Carrier-to-noise ratio - Wikipedia  

6. Pulse Shaping | PySDR: A Guide to SDR and DSP using Python