์๋ ํ๋ธ๋ฅด.
์๋ง๋ ์๊ณ๋ ๊ธฐ์ ๊ด์ธก์๋ฅผ ๊ตฌ์
ํ๋ ๋ง์ ์ฌ๋๋ค์ด ํฌ์ฅ์์ ๋ฌด์ ์ ์ด ์๊ณ๋ ์ฌ์ง์ด ์์ ์๊ณ ๋ก๊ณ ๋ฅผ ๋ณธ ์ ์ด ์์ ๊ฒ์
๋๋ค. ์๊ณ๋ฅผ ํ
์ด๋ธ ์์ ์ฌ๋ ค๋๊ธฐ๋ง ํ๋ฉด ์ ์ ํ ์๋์ผ๋ก ์ ํํ ์๊ฐ์ ๋ง์ถฐ ์กฐ์ ๋๊ธฐ ๋๋ฌธ์ ๋งค์ฐ ํธ๋ฆฌํฉ๋๋ค.
์ด๋ป๊ฒ ์๋ํ๋์ง ์์๋ณด๊ณ Python์ผ๋ก ๋์ฝ๋๋ฅผ ์์ฑํด ๋ณด๊ฒ ์ต๋๋ค.
๋ค์ํ ์๊ฐ ๋๊ธฐํ ์์คํ
์ด ์์ต๋๋ค. ์ ๋ฝ์์ ๊ฐ์ฅ ์ธ๊ธฐ ์๋ ์์คํ
์ ๋
์ผ ์์คํ
์
๋๋ค.
์๋์ ์ฐ์ฌ์ง ๋ชจ๋ ๋ด์ฉ์ DCF77์ ๊ดํ ๊ฒ์ ๋๋ค.
์ ํธ ์์
DCF77์ 77.5kHz์ ์ฃผํ์์์ ์๋ํ๊ณ ์งํญ ๋ณ์กฐ๋ก ์ ํธ๋ฅผ ์ ์กํ๋ ์ฅํ ๋ฐฉ์ก๊ตญ์
๋๋ค. 50KW ์ญ์ ํ๋ํฌํธ๋ฅดํธ์์ 25km ๋จ์ด์ง ๊ณณ์ ์์นํด ์์ผ๋ฉฐ, 1959๋
์ ์ด์์ ์์ํ๊ณ , 1973๋
์ ์ ํํ ์๊ฐ์ ๋ ์ง ์ ๋ณด๊ฐ ์ถ๊ฐ๋์์ต๋๋ค. 77KHz ์ฃผํ์์ ํ์ฅ์ ๋งค์ฐ ๊ธธ๊ธฐ ๋๋ฌธ์ ์ํ
๋ ํ๋์ ํฌ๊ธฐ๋ ๊ฝค ๊ด์ฐฎ์ต๋๋ค(์ฌ์ง: Wikipedia).
์ด๋ฌํ ์ํ
๋ ๋ฐ ์ ์ ์
๋ ฅ์ ํตํด ์์ ์์ญ์ ๊ฑฐ์ ๋ชจ๋ ์ ๋ฝ, ๋ฒจ๋ก๋ฃจ์, ์ฐํฌ๋ผ์ด๋ ๋ฐ ๋ฌ์์ ์ผ๋ถ๋ฅผ ํฌ๊ดํฉ๋๋ค.
๋๊ตฌ๋ ์ ํธ๋ฅผ ๋
น์ํ ์ ์์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ ค๋ฉด ์จ๋ผ์ธ ์์ ๊ธฐ๋ก ์ด๋ํ์ธ์.
๊ฑฐ๊ธฐ์ ๋ค์ด๋ก๋ ๋ฒํผ์ ๋๋ฅด๊ณ ๋ช ๋ถ ๊ธธ์ด์ ์กฐ๊ฐ์ ๋
น์ํฉ๋๋ค. ๋ฌผ๋ก , 77.5KHz ์ฃผํ์๋ฅผ ๋
น์ํ ์ ์๋ "์ค์ " ์์ ๊ธฐ๊ฐ ์๋ค๋ฉด ๊ทธ๊ฒ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ฌผ๋ก ์ธํฐ๋ท์ ํตํด ์ ํ ์๊ฐ ์ ํธ๋ฅผ ์์ ํ๋ฉด ์ค์ ๋ก ์ ํํ ์๊ฐ์ ์์ ํ ์ ์์ต๋๋ค. ์ ํธ๊ฐ ์ง์ฐ๋์ด ์ ์ก๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ์ฐ๋ฆฌ์ ๋ชฉํ๋ ์ ํธ์ ๊ตฌ์กฐ๋ฅผ ์ดํดํ๋ ๊ฒ๋ฟ์ด๋ฏ๋ก ์ด๋ฅผ ์ํด์๋ ์ธํฐ๋ท ๋ น์๋ง์ผ๋ก ์ถฉ๋ถํฉ๋๋ค. ๋ฌผ๋ก ์ค์ ์ํ์์๋ ์์ ๋ฐ ๋์ฝ๋ฉ์ ์ํด ํน์ ์ฅ์น๊ฐ ์ฌ์ฉ๋๋ฉฐ ์ด์ ๋ํด์๋ ์๋์์ ์ค๋ช ํฉ๋๋ค.
์ด์ ๋ น์์ ๋ฐ์์ผ๋ ์ฒ๋ฆฌ๋ฅผ ์์ํ๊ฒ ์ต๋๋ค.
์ ํธ ๋์ฝ๋ฉ
Python์ ์ฌ์ฉํ์ฌ ํ์ผ์ ๋ก๋ํ๊ณ ํด๋น ๊ตฌ์กฐ๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
from scipy.io import wavfile
from scipy import signal
import matplotlib.pyplot as plt
import numpy as np
sample_rate, data = wavfile.read("dcf_websdr_2019-03-26T20_25_34Z_76.6kHz.wav")
plt.plot(data[:100000])
plt.show()
์ผ๋ฐ์ ์ธ ์งํญ ๋ณ์กฐ๋ฅผ ๋ณผ ์ ์์ต๋๋ค.
๋์ฝ๋ฉ์ ๋จ์ํํ๊ธฐ ์ํด ํ๋ฒ ๋ฅดํธ ๋ณํ์ ์ฌ์ฉํ์ฌ ์ ํธ ํฌ๋ฝ์ ์ ์ทจํ๊ฒ ์ต๋๋ค.
analytic_signal = signal.hilbert(data)
A = np.abs(analytic_signal)
plt.plot(A[:100000])
ํ๋๋ ๊ฒฐ๊ณผ:
์ ์ญ ํต๊ณผ ํํฐ๋ฅผ ์ฌ์ฉํ์ฌ ์์ ๋ฐฉ์ถ์ ํํํํ๋ ๋์์ ํ๊ท ๊ฐ์ ๊ณ์ฐํด ๋ณด๊ฒ ์ต๋๋ค. ์ด๋ ๋์ค์ ๊ตฌ๋ฌธ ๋ถ์์ ์ ์ฉํฉ๋๋ค.
b, a = signal.butter(2, 20.0/sample_rate)
zi = signal.lfilter_zi(b, a)
A, _ = signal.lfilter(b, a, A, zi=zi*A[0])
avg = (np.amax(A) + np.amin(A))/2
๊ฒฐ๊ณผ(๋
ธ๋์ ์ ): ๋ถ์ํ๊ธฐ ๋งค์ฐ ์ฌ์ด ๊ตฌํํ์ ๊ฐ๊น์ด ์ ํธ์
๋๋ค.
ํ์ฑ
๋จผ์ ๋นํธ ์ํ์ค๋ฅผ ๊ฐ์ ธ์์ผ ํฉ๋๋ค. ์ ํธ ๊ตฌ์กฐ ์์ฒด๋ ๋งค์ฐ ๊ฐ๋จํฉ๋๋ค.
ํ์ค๋ ๋ ๋ฒ์งธ ๊ฐ๊ฒฉ์ผ๋ก ๋๋์ด์ง๋๋ค. ํ์ค ์ฌ์ด์ ๊ฑฐ๋ฆฌ๊ฐ 0.1์ด(์ฆ, ํ์ค ์์ฒด์ ๊ธธ์ด๊ฐ 0.9์ด)์ด๋ฉด ๋นํธ ์ํ์ค์ "0"์ ์ถ๊ฐํ๊ณ , ๊ฑฐ๋ฆฌ๊ฐ 0.2์ด(์ฆ, ๊ธธ์ด๊ฐ 0.8์ด)์ด๋ฉด "1"์ ์ถ๊ฐํฉ๋๋ค. ๋งค ๋ถ์ ๋์ 2์ด ๊ธธ์ด์ "๊ธด" ํ์ค๋ก ํ์๋๋ฉฐ ๋นํธ ์ํ์ค๋ XNUMX์ผ๋ก ์ฌ์ค์ ๋๊ณ ์ฑ์ฐ๊ธฐ๊ฐ ๋ค์ ์์๋ฉ๋๋ค.
์์ ๋ด์ฉ์ Python์ผ๋ก ์์ฑํ๊ธฐ ์ฝ์ต๋๋ค.
sig_start, sig_stop = 0, 0
pos = 0
bits_str = ""
while pos < cnt - 4:
if A[pos] < avg and A[pos+1] > avg:
# Signal begin
sig_start = pos
if A[pos] > avg and A[pos+1] < avg:
# Signal end
sig_stop = pos
diff = sig_stop - sig_start
if diff < 0.85*sample_rate:
bits_str += "1"
if diff > 0.85*sample_rate and diff < 1.25*sample_rate:
bits_str += "0"
if diff > 1.5*sample_rate:
print(bits_str)
bits_str = ""
pos += 1
๊ฒฐ๊ณผ์ ์ผ๋ก ์ฐ๋ฆฌ๋ ์ผ๋ จ์ ๋นํธ๋ฅผ ์ป์ต๋๋ค. ์ด ์์์๋ XNUMX์ด ๋์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
0011110110111000001011000001010000100110010101100010011000
0001111100110110001010100001010000100110010101100010011000
๊ทธ๋ฐ๋ฐ ์ ํธ์ ๋ฐ์ดํฐ์ "๋ ๋ฒ์งธ ๊ณ์ธต"๋ ์๋ค๋ ์ ์ด ํฅ๋ฏธ๋กญ์ต๋๋ค. ๋นํธ ์ํ์ค๋ ๋ค์์ ์ฌ์ฉํ์ฌ ์ธ์ฝ๋ฉ๋ฉ๋๋ค.
๋ง์ง๋ง ๋จ๊ณ: ์ค์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ต๋๋ค. ๋นํธ๋ ์ด๋น ํ ๋ฒ ์ ์ก๋๋ฏ๋ก ์ด 59๋นํธ๊ฐ ๋๋ฉฐ ์ฌ๊ธฐ์๋ ์๋นํ ๋ง์ ์ ๋ณด๊ฐ ์ธ์ฝ๋ฉ๋ฉ๋๋ค.
๋นํธ๋ ๋ค์์ ์ค๋ช
๋์ด ์์ต๋๋ค.
์ค์ค๋ก ์คํํด๋ณด๊ณ ์ถ์ ๋ถ๋ค์ ์ํด ์คํฌ์ผ๋ฌ ์๋์ ๋์ฝ๋ฉ ์ฝ๋๊ฐ ์ ๊ณต๋ฉ๋๋ค.
์์ค ์ฝ๋
def decode(bits):
if bits[0] != '0' or bits[20] != '1':
return
minutes, hours, day_of_month, weekday, month, year = map(convert_block,
(bits[21:28], bits[29:35], bits[36:42], bits[42:45],
bits[45:50], bits[50:58]))
days = ('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday')
print('{dow}, {dom:02}.{mon:02}.{y}, {h:02}:{m:02}'.format(h=hours, m=minutes, dow=days[weekday],
dom=day_of_month, mon=month, y=year))
def convert_ones(bits):
return sum(2**i for i, bit in enumerate(bits) if bit == '1')
def convert_tens(bits):
return 10*convert_ones(bits)
def right_parity(bits, parity_bit):
num_of_ones = sum(int(bit) for bit in bits)
return num_of_ones % 2 == int(parity_bit)
def convert_block(bits, parity=False):
if parity and not right_parity(bits[:-1], bits[-1]):
return -1
ones = bits[:4]
tens = bits[4:]
return convert_tens(tens) + convert_ones(ones)
ํ๋ก๊ทธ๋จ์ ์คํํ๋ฉด ๋ค์๊ณผ ์ ์ฌํ ์ถ๋ ฅ์ด ํ์๋ฉ๋๋ค.
0011110110111000001011000001010000100110010101100010011000
Tuesday, 26.03.19, 21:41
0001111100110110001010100001010000100110010101100010011000
Tuesday, 26.03.19, 21:42
์ฌ์ค ๊ทธ๊ฒ ์ ๋ถ ๋ง๋ฒ์ด์์. ์ด๋ฌํ ์์คํ ์ ์ฅ์ ์ ๋์ฝ๋ฉ์ด ๋งค์ฐ ๊ฐ๋จํ๊ณ ๊ฐ์ฅ ๊ฐ๋จํ ๋ง์ดํฌ๋ก ์ปจํธ๋กค๋ฌ์์๋ ์ํํ ์ ์๋ค๋ ๊ฒ์ ๋๋ค. ์ฐ๋ฆฌ๋ ๋จ์ํ ํ์ค์ ๊ธธ์ด๋ฅผ ์ธ๊ณ 60๋นํธ๋ฅผ ์ถ์ ํ๋ฉฐ ๋งค ๋ถ์ด ๋๋ ๋๋ง๋ค ์ ํํ ์๊ฐ์ ์ป์ต๋๋ค. ๋ค๋ฅธ ์๊ฐ ๋๊ธฐํ ๋ฐฉ๋ฒ(์: GPS ๋๋ ์ธํฐ๋ท ๊ธ์ง)๊ณผ ๋น๊ตํ ๋ ์ด๋ฌํ ๋ฌด์ ๋๊ธฐํ์๋ ์ฌ์ค์ ์ ๊ธฐ๊ฐ ํ์ํ์ง ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ์ผ๋ฐ ๊ฐ์ ์ฉ ๊ธฐ์ ๊ด์ธก์๋ AA ๋ฐฐํฐ๋ฆฌ 2๊ฐ๋ก ์ฝ XNUMX๋ ๋์ ์๋ํฉ๋๋ค. ๋ฐ๋ผ์ ๋ฒฝ์๊ณ๋ ๊ฑฐ๋ฆฌ ๊ด์ธก์ ์๊ณ๋ ๋ฌผ๋ก ์๋ชฉ์๊ณ๋ ๋ฌด์ ๋๊ธฐํ ๊ธฐ๋ฅ์ผ๋ก ์ ์๋ฉ๋๋ค.
DCF์ ํธ๋ฆฌํจ๊ณผ ๋จ์ํจ๋ DIY ๋ง๋์๋ค์ ๋งค๋ฃ์ํต๋๋ค. ๋จ 10~20๋ฌ๋ฌ์ Arduino ๋๋ ๊ธฐํ ์ปจํธ๋กค๋ฌ์ ์ฐ๊ฒฐํ ์ ์๋ ๊ธฐ์ฑ ์์ ๊ธฐ ๋ฐ TTL ์ถ๋ ฅ์ด ํฌํจ๋ ๊ธฐ์ฑ ์ํ
๋ ๋ชจ๋์ ๊ตฌ์
ํ ์ ์์ต๋๋ค.
์ด๋ฏธ Arduino์ฉ์ผ๋ก ์์ฑ๋์์ต๋๋ค.
์ํ๋ ์ฌ๋์ ๋ฌด์ ๋๊ธฐํ ๊ธฐ๋ฅ์ด ์๋ ์๋ก์ด ๋ฉ์ปค๋์ฆ์ ์ค์นํ์ฌ ์ค๋๋ ํ ๋จธ๋์ ์๊ณ๋ฅผ ์ ๊ทธ๋ ์ด๋ํ ์๋ ์์ต๋๋ค.
eBay์์ "Radio Controlled Movement"๋ผ๋ ํค์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ฐพ์ ์ ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋ง์ง๋ง์ผ๋ก ์ฌ๊ธฐ๊น์ง ์ฝ์ผ์ ๋ถ๋ค์ ์ํ ์ธ์ ๊ฟํ์ ๋๋ค. ์์ผ๋ก ๋ช ์ฒ ํฌ๋ก๋ฏธํฐ ๋์ ๋จ์ผ ๋ฌด์ ์ ํธ ์ก์ ๊ธฐ๊ฐ ์๋๋ผ๋ ๊ทธ๋ฌํ ์ ํธ๋ฅผ ์ง์ ์์ฑํ๋ ๊ฒ์ ์ด๋ ต์ง ์์ต๋๋ค. Google Play์๋ ์ ํธ๋ฅผ ํค๋ํฐ์ผ๋ก ์ถ๋ ฅํ๋ "DCF77 Emulator"๋ผ๋ ํ๋ก๊ทธ๋จ์ด ์์ต๋๋ค. ์ ์์ ๋ฐ๋ฅด๋ฉด ์๊ณ ์ฃผ์์ ํค๋ํฐ ์์ด์ด๋ฅผ ๊ฐ์ผ๋ฉด ์ ํธ๊ฐ ์์ ๋ฉ๋๋ค(์ผ๋ฐ ํค๋ํฐ์ 77KHz ์ ํธ๋ฅผ ์์ฑํ์ง ์์ง๋ง ์์ ์ ์๋ง๋ ๊ณ ์กฐํ๋ก ์ธํด ๋ฐ์ํ๊ธฐ ๋๋ฌธ์ ํฅ๋ฏธ๋ก์ด ์ ์ ๋๋ค). Android 9์์๋ ํ๋ก๊ทธ๋จ์ด ์ ํ ์๋ํ์ง ์์์ต๋๋ค. ๋จ์ํ ์๋ฆฌ๊ฐ ๋์ง ์์์ง๋ง (๋๋ ๋ฃ์ง ๋ชปํ์ ์๋ ์์ต๋๋ค. ๊ฒฐ๊ตญ 77KHz์ ๋๋ค :) ์ด์ฉ๋ฉด ๋๊ตฐ๊ฐ๊ฐ ๋ ๋์ ํ์ด์ ๋๋ฆด ์๋ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ผ๋ถ๋ ๋์ผํ Arduino ๋๋ ESP32์์ ์ฝ๊ฒ ๋ง๋ค ์ ์๋ ์์ ํ DCF ์ ํธ ์์ฑ๊ธฐ๋ฅผ ๋ง๋ญ๋๋ค.
(์ถ์ฒ
๊ฒฐ๋ก
DCF ์์คํ
์ ์ ๋ง ๊ฐ๋จํ๊ณ ํธ๋ฆฌํ ๊ฒ์ผ๋ก ๋ํ๋ฌ์ต๋๋ค. ๊ฐ๋จํ๊ณ ์ ๋ ดํ ์์ ๊ธฐ๋ฅผ ์ฌ์ฉํ๋ฉด ์์ ๊ตฌ์ญ์ ๋ฌผ๋ก ์ธ์ ์ด๋์๋ ์ ํํ ์๊ฐ์ ํ์ธํ ์ ์์ต๋๋ค. ๊ด๋ฒ์ํ ๋์งํธํ์ ์ฌ๋ฌผ ์ธํฐ๋ท์๋ ๋ถ๊ตฌํ๊ณ ์ด๋ฌํ ๊ฐ๋จํ ์๋ฃจ์
์ ์ค๋ซ๋์ ์์๊ฐ ์์ ๊ฒ์ผ๋ก ๋ณด์
๋๋ค.
์ถ์ฒ : habr.com