18

Ich habe mein Open-Source-DCF77-Decoder-Projekt fast abgeschlossen. Alles begann, als ich bemerkte, dass die DCF77-Standardbibliotheken (Arduino) bei verrauschten Signalen sehr schlecht arbeiten. Insbesondere konnte ich die Zeit nicht aus den Decodern herausholen, wenn die Antenne in der Nähe des Computers war oder wenn meine Waschmaschine lief.DCF77-Decoder vs. verrauschtes Signal

Meine erste Herangehensweise bestand darin, dem eingehenden Signal einen (digitalen) exponentiellen Filter + Trigger hinzuzufügen.

Obwohl dies die Situation deutlich verbesserte, war es immer noch nicht wirklich gut. Dann begann ich einige Standardbücher über digitale Signalverarbeitung zu lesen und vor allem die Originalwerke von Claude Elwood Shannon. Meine Schlussfolgerung war, dass der richtige Ansatz wäre, das Signal überhaupt nicht "zu decodieren", weil es a priori (außer für Schaltsekunden) vollständig bekannt ist. Stattdessen wäre es passender, die empfangenen Daten an ein lokal synthetisiertes Signal anzupassen und einfach die richtige Phase zu bestimmen. Dies wiederum würde die effektive Bandbreite um einige Größenordnungen reduzieren und somit das Rauschen signifikant reduzieren.

Die Phasendetektion erfordert eine schnelle Faltung. Der Standardansatz für effiziente Faltung ist natürlich die schnelle Fourier-Transformation. Allerdings implementiere ich für den Arduino/Atmega 328. Damit habe ich nur 2k RAM. Statt der direkten Annäherung mit FFT habe ich begonnen, phasenstarre Filter zu stapeln. Ich dokumentiert die verschiedenen Projektphasen hier:

Ich suchte das Internet ziemlich ausgiebig und fand keinen ähnlichen Ansatz. Dennoch frage ich mich, ob es ähnliche (und vielleicht bessere) Implementierungen gibt. Oder wenn Forschung zu dieser Art von Signalrekonstruktion existiert.

Wonach ich nicht suche: Entwurf optimierter Codes für die Annäherung an die Shannon-Grenze. Ich suche auch nicht nach Informationen über den überlagerten PRNG-Code auf DCF77. Ich brauche auch keine Hinweise auf "Matched-Filter", da meine aktuelle Implementierung eine Annäherung an einen Matched-Filter ist. Spezielle Hinweise zu Viterbi-Decodern oder Trellis-Ansätzen sind nicht das, wonach ich suche - es sei denn, sie befassen sich mit engen CPU- und RAM-Einschränkungen.

Was ich suche: gibt es irgendwelche Beschreibungen/Implementierungen anderer nicht-trivialer Algorithmen zur Decodierung von Signalen wie DCF77, mit begrenzten CPU und RAM in Anwesenheit von erheblichem Rauschen? Vielleicht in einigen Büchern oder Zeitungen aus der Zeit vor dem Internet?

+0

Dies ist nicht mein Spezialgebiet, aber haben Sie erwogen, den Tiefpassfilter und Trigger mit dem [Viterbi-Algorithmus] (http://en.wikipedia.org/wiki/Viterbi_algorithm) auf einem Zwei-Zustand zu ersetzen Markov Kette? –

+0

Dies scheint die am meisten überarbeitete Uhr zu sein, die ich je gesehen habe, aber ich mag sie sehr. Muss ein lustiges Projekt gewesen sein. Müssen Sie alle Ihre Blogeinträge lesen, wenn ich mehr Zeit habe. Die Art der Faltung mit einer vorhergesagten Wellenform scheint nahe bei einer optimalen Lösung zu liegen. Haben Sie [Kalman filtering] (http://en.wikipedia.org/wiki/Kalman_filter) gelesen? Dies hat einige Ähnlichkeiten mit dem, was Sie getan haben. Die Idee ist, das beobachtete System grob zu simulieren und dann die simulierten Messungen mit den realen Messungen zu vergleichen, um den Zustand Ihres Modells basierend auf dem Unterschied zu aktualisieren. –

+0

In Bezug auf den Viterbi-Algorithmus und Kamlman-Filter haben Sie recht. Dies sind mögliche Untersuchungsmethoden. Allerdings habe ich sie aufgrund der engen Speicher- und CPU-Beschränkungen nicht getestet. Wenn jemand dies auf einer so schwachen CPU versucht hat, würde ich gerne etwas über die Implementierungen erfahren. In Bezug auf die Übertechnik: Es ist eine seltsame Befriedigung darin. "Alles, was sich lohnt, ist es wert, übertrieben zu werden;)" Der Faltungsansatz mit dem vollständig bekannten Signal wird auch als "optimaler Filter" bezeichnet. Das einzige Problem ist, dass ich aufgrund der Speicherbeschränkungen nur annähern kann. –

Antwort

1

Der Verweis auf angepasste Filter von Ollie B. ist nicht das, wonach ich gefragt habe. Ich habe dies bereits in meinem Blog behandelt.

Aber inzwischen habe ich einen sehr guten Hinweis per Privatpost erhalten. Es gibt ein Papier "Performance Analysis and Receiver Architectures of DCF77 Radio-Controlled Clocks" von Daniel Engeler. Das ist die Art von Sachen, nach denen ich suche.

Mit weiteren Recherchen ausgehend vom Engeler-Papier fand ich die folgenden deutschen Patente DE3733966A1 - Anordnung zum Empfang stark gestoerter Signale des Senders dcf-77 und DE4219417C2 - Schmalbandempfänger für Datensignale.

2

Haben Sie in Betracht gezogen, einen angepassten Chip zu verwenden, um Ihre Faltung durchzuführen?

http://en.wikipedia.org/wiki/Matched_filter

Sie sind fast trivialerweise einfach zu implementieren, da jeder Chip/Bitperiode als Add subtrahieren Verzögerungsleitung (mit einem Ringpuffer) umgesetzt werden können

ein einfaches für eine Rechteckwelle (wird auch so etwas wie dies umgesetzt werden kann, aber weniger optimal mit anderen Wellenformen) unbekannter Sequenz (aber bekannter Frequenz) arbeiten:

// Filter class 
template <int samples_per_bit> 
class matchedFilter(
    public: 
     // constructor 
     matchedFilter() : acc(0) {}; 

     // destructor 
     ~matchedFilter() {}; 

     int filterInput(int next_sample){ 
     int temp; 
     temp = sample_buffer.insert(nextSample); 
     temp -= next_sample; 
     temp -= result_buffer.insert(temp); 
     return temp; 
     }; 

    private: 
    int acc; 
    CircularBuffer<samples_per_bit> sample_buffer; 
    CircularBuffer<samples_per_bit> result_buffer; 
); 

// Circular buffer 
template <int length> 
class CircularBuffer(
    public: 
     // constructor 
     CircularBuffer() : element(0) { 
     buffer.fill(0); 
     }; 
     // destructor 
     ~CircularBuffer(){}; 

     int insert(int new_element){ 
     int temp; 
     temp = array[element_pos]; 
     array[element_pos] = new_element; 
     element_pos += 1; 
     if (element_pos == length){ 
      element_pos = 0; 
     }; 
     return temp; 
     } 

    private: 
     std::array<int, length> buffer; 
     int element_pos; 
); 

wie Sie sehen können, Ressourcen klug, das ist relativ trivial. Ist eine bestimmte Wellenform gewünscht, können Sie diese zusammen kaskadieren, um eine längere Korrelation zu erhalten.

+0

Ich implementiere bereits einen rekursiven Stapel angepasster Filter. Ich bin mir dieser Vorgehensweise bewusst. Der direkte Ansatz, den Sie vorschlagen, scheitert jedoch an den engen Speicherbedingungen. Mit 2k würde Ihr Ansatz eine Abtastung von höchstens 1000s ermöglichen, was schlimmer wäre als das, was ich derzeit tun kann. –

+0

Ich interessiere mich dafür, wie Sie einen Matched-Filter für mehr als 1000s erstellen würden, ohne Tausende von Daten zu speichern. Auch Ihr SNR muss schrecklich sein, wenn Sie 1000s benötigen. Das ist ein 40dB Gewinn, oder? – OllieB

+0

Der springende Punkt des Experiments war, SNR so weit wie möglich zu drücken. Für die Details lesen Sie meinen Blog. Ich habe alles dokumentiert. Der Schlüssel ist, dass der Beginn der Daten immer am Anfang der Sekunde liegt. Also kann ich das und rekursiv den Rest abgleichen. Allerdings würde ich sagen, dass 1000s eine digitale Verstärkung von 30 dB statt 40 ist. –