DCF77: ¬ŅC√≥mo funciona el sistema preciso de transmisi√≥n de se√Īal horaria?

Hola habr

Probablemente, muchas personas que compran un reloj o estación meteorológica vieron el logotipo del Reloj Radio Controlado o incluso el Reloj Atómico en el paquete. Esto es muy conveniente, porque es suficiente para poner el reloj sobre la mesa, y después de un tiempo se ajustarán automáticamente a la hora exacta.



Veamos cómo funciona y escriba un decodificador en Python.

Existen diferentes sistemas de sincronizaci√≥n horaria. El m√°s popular en Europa es el sistema alem√°n DCF-77 , Jap√≥n tiene su propio sistema JJY , Estados Unidos tiene el sistema WWVB , y as√≠ sucesivamente. Adem√°s, la historia ser√° sobre DCF77, como el m√°s relevante y disponible para la recepci√≥n en algunos lugares de la parte europea de Rusia y los pa√≠ses vecinos (los residentes del Lejano Oriente pueden tener la opini√≥n opuesta, sin embargo, a su vez, pueden recibir y analizar la se√Īal japonesa;).

Todo lo escrito a continuación será sobre DCF77.

Recepci√≥n de la se√Īal


DCF77 es una estaci√≥n de onda larga que opera a una frecuencia de 77.5KHz y transmite se√Īales en modulaci√≥n de amplitud. La estaci√≥n con una capacidad de 50 kW se encuentra a 25 km de Frankfurt, comenz√≥ a funcionar en 1959, en 1973 la informaci√≥n de la fecha se agreg√≥ a la hora exacta. La longitud de onda a una frecuencia de 77KHz es muy grande, por lo que las dimensiones del campo de la antena tambi√©n son muy decentes (foto de Wikipedia):



Con dicha antena y entrada de energía, el área de recepción cubre casi toda Europa, Bielorrusia, Ucrania y parte de Rusia.



Todos pueden grabar una se√Īal. Para hacer esto, solo vaya al receptor en l√≠nea http://websdr.ewi.utwente.nl:8901/ , seleccione la frecuencia all√≠ 76.5KHz y la modulaci√≥n USB. Deber√≠a abrirse una imagen de algo como esto:



Allí presionamos el botón de descarga y grabamos un fragmento de varios minutos de duración. Por supuesto, si tiene un receptor "real" capaz de grabar una frecuencia de 77.5KHz, puede usarlo.

Por supuesto, cuando recibamos se√Īales de radio de la hora exacta a trav√©s de Internet, no obtendremos la hora exacta: la se√Īal se retrasa. Pero nuestro objetivo es solo entender la estructura de la se√Īal; para esto, la grabaci√≥n de Internet es m√°s que suficiente. En la vida real, por supuesto, se utilizan dispositivos especializados para recibir y decodificar, se discutir√°n a continuaci√≥n.

Entonces, tenemos el registro, comencemos a procesarlo.

Decodificaci√≥n de se√Īal


Descargue el archivo usando Python y vea su estructura:
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() 

Vemos una modulación de amplitud típica:



Para simplificar la decodificaci√≥n, tomamos la envolvente de la se√Īal usando la transformaci√≥n de Hilbert:

 analytic_signal = signal.hilbert(data) A = np.abs(analytic_signal) plt.plot(A[:100000]) 

Resultado en una vista ampliada:



Suavizamos las emisiones de la interferencia usando un filtro de paso bajo, al mismo tiempo que calculamos el valor promedio, ser√° √ļtil m√°s tarde para el an√°lisis.

 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 

Resultado (l√≠nea amarilla): una se√Īal casi rectangular que es bastante f√°cil de analizar.



Analizando


Primero necesitas obtener la secuencia de bits. La estructura de la se√Īal en s√≠ es muy simple.



Los pulsos se dividen en segundos intervalos. Si la distancia entre pulsos es 0.1 s (es decir, la longitud del pulso es 0.9 s), agregue "0" a la secuencia de bits, si la distancia es 0.2 s (es decir, 0.8 s de longitud), agregue "1". El final de cada minuto se indica mediante un pulso "largo", de 2 segundos de duración, la secuencia de bits se restablece a cero y el llenado comienza nuevamente.

Lo anterior es f√°cil de escribir en 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 

Como resultado, obtenemos una secuencia de bits, en nuestro ejemplo durante dos minutos se ve así:

0011110110111000001011000001010000100110010101100010011000
0001111100110110001010100001010000100110010101100010011000


Por cierto, es interesante que haya una "segunda capa" de datos en la se√Īal. La secuencia de bits tambi√©n se codifica mediante modulaci√≥n de fase . Te√≥ricamente, esto deber√≠a proporcionar una decodificaci√≥n m√°s estable incluso en el caso de una se√Īal debilitada.

Nuestro √ļltimo paso: obtener los datos reales. Los bits se transmiten una vez por segundo, por lo que solo tenemos 59 bits, en los que se codifica mucha informaci√≥n:



Los bits se describen en Wikipedia , y son bastante curiosos. Los primeros 15 bits no se usan, aunque había planes para usar en sistemas de advertencia y defensa civil . El bit A1 indica que en la próxima hora el reloj estará configurado para el horario de verano. El bit A2 indica que se agregará un segundo adicional en la próxima hora, que a veces se utiliza para corregir el tiempo de acuerdo con la rotación de la Tierra. Los bits restantes codifican horas, minutos y fecha.



Para aquellos que quieran experimentar por su cuenta, el código para la decodificación se proporciona bajo el spoiler.

Código fuente
 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) 


Al ejecutar el programa, veremos algo como esto:

0011110110111000001011000001010000100110010101100010011000
Tuesday, 26.03.19, 21:41
0001111100110110001010100001010000100110010101100010011000
Tuesday, 26.03.19, 21:42


En realidad, eso es todo magia. La ventaja de un sistema de este tipo es que la decodificaci√≥n es extremadamente simple y se puede realizar en cualquiera de los microcontroladores m√°s sencillos. Simplemente cuente la longitud de los pulsos, acumule 60 bits y al final de cada minuto obtengamos el tiempo exacto. En comparaci√≥n con otros m√©todos de sincronizaci√≥n horaria (GPS, por ejemplo, o Dios no lo quiera, Internet :), tal sincronizaci√≥n de radio pr√°cticamente no requiere electricidad; por ejemplo, una estaci√≥n meteorol√≥gica dom√©stica normal funciona durante aproximadamente un a√Īo con 2 bater√≠as AA. Por lo tanto, incluso un reloj de pulsera est√° hecho con sincronizaci√≥n de radio, sin mencionar, por supuesto, sobre una pared o estaci√≥n de calle.

La conveniencia y la simplicidad de DCF atraen a los amantes de los productos caseros. Por solo $ 10-20, puede comprar un módulo listo para usar de una antena con un receptor listo y salida TTL, que puede conectarse a un Arduino u otro controlador.



Para Arduino, las bibliotecas preparadas ya se han escrito. Sin embargo, ya se sabe que no importa lo que haga en el microcontrolador, obtendrá un reloj o una estación meteorológica. Con dicho dispositivo, obtener la hora exacta es realmente fácil, siempre que se encuentre en el área de recepción. Bueno, puede colgar la inscripción "Reloj atómico" en el reloj y, al mismo tiempo, explicar a todos los que lo deseen que el dispositivo está realmente sincronizado con un reloj atómico.

Aquellos que lo deseen pueden incluso actualizar los relojes de sus abuelas instalando un nuevo mecanismo con sincronización de radio en ellos:



Puede encontrar uno en eBay usando las palabras clave "Movimiento controlado por radio".

Y finalmente, un truco de vida para aquellos que han le√≠do aqu√≠. Incluso si no hay un solo transmisor de una se√Īal de radio en los pr√≥ximos dos mil kil√≥metros, dicha se√Īal es f√°cil de generar de forma independiente. Google Play tiene un programa llamado "Emulador DCF77" que emite una se√Īal a los auriculares. Seg√ļn el autor, si enrollas el cable de los auriculares alrededor del reloj, captar√°n una se√Īal (me pregunto c√≥mo, porque los auriculares normales no emitir√°n una se√Īal de 77KHz, pero probablemente la recepci√≥n provenga de los arm√≥nicos). Mi programa no funcionaba en Android 9, simplemente no hab√≠a sonido (o tal vez no lo escuch√©, 77KHz, despu√©s de todo :), pero tal vez alguien tenga m√°s suerte. Algunos, sin embargo, se convierten en un generador de se√Īal DCF completo, que es f√°cil de hacer en el mismo Arduino o ESP32:


(fuente sgfantasytoys.wordpress.com/2015/05/13/synchronize-radio-controlled-watch-without-access )

Conclusión


El sistema DCF resultó ser realmente bastante simple y conveniente. Con la ayuda de un receptor simple y barato, puede tener una hora precisa en cualquier momento, en cualquier lugar, por supuesto, en el área de recepción. Parece que incluso a pesar de la digitalización generalizada y el "Internet de las cosas", se necesitarán soluciones tan simples durante mucho tiempo.

Source: https://habr.com/ru/post/445470/


All Articles