DCF77: Hvordan fungerer tidssignalsystemet?

Hej Habr.

Sandsynligvis har mange, der køber et ur eller vejrstation, set det radiostyrede ur eller endda Atomic Clock-logoet på emballagen. Dette er meget praktisk, fordi du blot skal lægge uret på bordet, og efter et stykke tid vil det automatisk tilpasse sig det nøjagtige tidspunkt.
DCF77: Hvordan fungerer tidssignalsystemet?

Lad os finde ud af, hvordan det virker, og skrive en dekoder i Python.

Der er forskellige tidssynkroniseringssystemer. Det mest populære i Europa er det tyske system DCF-77, Japan har sit eget system JJY, i USA er der et system wwvb, og så videre. Dernæst vil historien handle om DCF77, som den mest relevante og tilgængelige for modtagelse nogle steder i den europæiske del af Rusland og nabolandene (beboere i Fjernøsten kan have den modsatte mening, men de kan til gengæld modtage og analyser det japanske signal ;).

Alt skrevet nedenfor vil handle om DCF77.

Signalmodtagelse

DCF77 er en langbølgestation, der opererer ved en frekvens på 77.5 kHz og sender signaler i amplitudemodulation. 50KW-stationen ligger 25 km fra Frankfurt, den startede i drift i 1959, og i 1973 blev datooplysninger tilføjet til det nøjagtige tidspunkt. Bølgelængden ved en frekvens på 77 KHz er meget lang, så dimensionerne af antennefeltet er også ganske anstændige (foto fra Wikipedia):
DCF77: Hvordan fungerer tidssignalsystemet?

Med sådan en antenne og strømindgang dækker modtageområdet næsten hele Europa, Hviderusland, Ukraine og en del af Rusland.

DCF77: Hvordan fungerer tidssignalsystemet?

Alle kan optage et signal. For at gøre dette skal du blot gå til onlinemodtageren http://websdr.ewi.utwente.nl:8901/, vælg frekvensen 76.5KHz og USB-modulation der. Der skulle åbnes et billede, der ser sådan ud:

DCF77: Hvordan fungerer tidssignalsystemet?

Der trykker vi på download-knappen og optager et fragment på flere minutter. Selvfølgelig, hvis du har en "rigtig" modtager, der er i stand til at optage 77.5KHz-frekvensen, kan du bruge den.

Ved at modtage radiotidssignaler via internettet vil vi naturligvis ikke modtage rigtig nøjagtig tid - signalet transmitteres med en forsinkelse. Men vores mål er kun at forstå strukturen af ​​signalet; til dette er internetoptagelsen mere end nok. I det virkelige liv bruges naturligvis specialiserede enheder til modtagelse og afkodning; de vil blive diskuteret nedenfor.

Så vi har modtaget optagelsen, lad os begynde at behandle den.

Signalafkodning

Lad os indlæse filen ved hjælp af Python og se dens struktur:

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

Vi ser typisk amplitudemodulation:
DCF77: Hvordan fungerer tidssignalsystemet?

For at forenkle afkodningen, lad os tage signalkonvolutten ved hjælp af Hilbert-transformationen:

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

Forstørret resultat:
DCF77: Hvordan fungerer tidssignalsystemet?

Lad os udglatte støjemissioner ved hjælp af et lavpasfilter, og samtidig beregne gennemsnitsværdien, som vil være nyttig senere til parsing.

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

Resultat (gul linje): et næsten firkantet signal, der er ret nemt at analysere.
DCF77: Hvordan fungerer tidssignalsystemet?

Parsing

Først skal du hente bitsekvensen. Selve signalstrukturen er meget enkel.
DCF77: Hvordan fungerer tidssignalsystemet?

Impulserne er opdelt i sekundintervaller. Hvis afstanden mellem pulser er 0.1 s (dvs. længden af ​​selve pulsen er 0.9 s), skal du tilføje "0" til bitsekvensen; hvis afstanden er 0.2 s (dvs. længden er 0.8 s), tilføjes "1". Slutningen af ​​hvert minut indikeres med en "lang" puls, 2 sek. lang, bitsekvensen nulstilles, og påfyldningen begynder igen.

Ovenstående er let at skrive i 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

Som et resultat får vi en sekvens af bits, i vores eksempel i to sekunder ser det sådan ud:

0011110110111000001011000001010000100110010101100010011000
0001111100110110001010100001010000100110010101100010011000

Det er i øvrigt interessant, at signalet også har et "andet lag" af data. Bitsekvensen kodes også vha fasemodulation. I teorien skulle dette give mere robust afkodning selv i tilfælde af et svækket signal.

Vores sidste skridt: at få de faktiske data. Bits transmitteres en gang i sekundet, så vi har i alt 59 bits, hvori der er kodet ret meget information:
DCF77: Hvordan fungerer tidssignalsystemet?

Bitsene er beskrevet i Википедии, og de er ret nysgerrige. De første 15 bits bliver ikke brugt, selvom der var planer om at bruge dem til varslingssystemer og civilforsvar. Bit A1 angiver, at uret vil skifte til sommertid i den næste time. Bit A2 angiver, at en yderligere spring sekund, som nogle gange bruges til at justere tiden efter Jordens rotation. De resterende bits koder timer, minutter, sekunder og dato.

DCF77: Hvordan fungerer tidssignalsystemet?

For dem, der ønsker at eksperimentere på egen hånd, er afkodningskoden givet under spoileren.
Kildekode

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)

Når vi kører programmet, vil vi se output svarende til dette:

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

Faktisk er det hele magien. Fordelen ved et sådant system er, at afkodningen er ekstremt enkel og kan udføres på enhver, selv den enkleste mikrocontroller. Vi tæller simpelthen længden af ​​pulserne, akkumulerer 60 bits, og i slutningen af ​​hvert minut får vi den nøjagtige tid. Sammenlignet med andre metoder til tidssynkronisering (f.eks. GPS, eller Gud forbyde det, internettet:) kræver sådan radiosynkronisering stort set ingen strøm - for eksempel kører en almindelig hjemmevejrstation i omkring et år på 2 AA-batterier. Derfor er selv armbåndsure lavet med radiosynkronisering, for ikke at tale om selvfølgelig vægure eller street station ure.

Bekvemmeligheden og enkeltheden ved DCF tiltrækker også gør-det-selv-entusiaster. For kun $10-20 kan du købe et færdiglavet antennemodul med en færdiglavet modtager og TTL-udgang, som kan tilsluttes en Arduino eller anden controller.
DCF77: Hvordan fungerer tidssignalsystemet?

Allerede skrevet til Arduino færdige biblioteker. Det er dog allerede kendt, at uanset hvad du laver på en mikrocontroller, så ender du med enten et ur eller en vejrstation. Med sådan en enhed er det virkelig nemt at få det nøjagtige tidspunkt, selvfølgelig forudsat at du er i receptionen. Nå, du kan hænge inskriptionen "Atomic Clock" på dit ur, og samtidig forklare alle, at enheden virkelig er synkroniseret ved hjælp af et atomur.

De, der ønsker det, kan endda opgradere deres gamle bedstemors ur ved at installere en ny mekanisme med radiosynkronisering:

DCF77: Hvordan fungerer tidssignalsystemet?

Du kan finde en på ebay ved hjælp af nøgleordene "Radio Controlled Movement".

Og endelig et life hack for dem, der har læst så langt. Selvom der ikke er en eneste radiosignalsender inden for de næste par tusinde km, er det ikke svært selv at generere et sådant signal. Der er et program på Google Play kaldet "DCF77 Emulator", der udsender signalet til hovedtelefoner. Ifølge forfatteren, hvis du vikler hovedtelefonernes ledning rundt om uret, vil de opfange signalet (det er interessant hvordan, fordi almindelige hovedtelefoner ikke producerer et 77KHz-signal, men modtagelse skyldes sandsynligvis harmoniske). På Android 9 virkede programmet slet ikke for mig - der var simpelthen ingen lyd (eller måske hørte jeg det ikke - det er trods alt 77KHz:), men måske er der nogen, der har bedre held. Nogle gør sig dog til en fuldgyldig DCF-signalgenerator, som er nem at lave på den samme Arduino eller ESP32:

DCF77: Hvordan fungerer tidssignalsystemet?
(kilde sgfantasytoys.wordpress.com/2015/05/13/synchronize-radio-controlled-watch-without-access)

Konklusion

DCF-systemet viste sig egentlig at være ganske enkelt og praktisk. Ved hjælp af en simpel og billig modtager kan du altid og alle steder have den nøjagtige tid, selvfølgelig i receptionen. Det ser ud til, at selv på trods af udbredt digitalisering og Internet of Things, vil sådanne simple løsninger være efterspurgte i lang tid.

Kilde: www.habr.com

Tilføj en kommentar