Go Down

Topic: Hat hier jemand einen Uno und ein DCF77 Modul? (Read 5367 times) previous topic - next topic

udoklein

Wie einige hier sicher schon mitbekommen haben entwickle ich seit ~9  Monaten eine rauschresistente DCF77 Uhr. Aktueller Stand ist hier: http://blog.blinkenlight.net/experiments/dcf77/the-clock/. Jetzt packe ich das gerade in eine Library um es einfacher für Projekte anderer Leute verfügbar zu machen. So weit so gut. Nur der Code ist im Moment auf Arduinos mit Quarz optimiert und der Uno hat einen Resonator. Da ich mit Blinkenlighties eingedeckt bin habe ich bisher keinen Uno gekauft. Wozu auch, der Blinkenlighty kann ja mehr und hat einen Quarz ;)

Deshalb kann ich nicht testen wie schlecht die Resonatoren wirklich sind. Um das auszuprobieren haben ich folgenden kleinen Sketch geschrieben:

Code: [Select]

//
//  www.blinkenlight.net
//
//  Copyright 2013 Udo Klein
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program. If not, see http://www.gnu.org/licenses/


const uint8_t dcf77_analog_sample_pin = 5;
const uint8_t dcf77_sample_pin = A5;  // == D19 for standard Arduinos
const uint8_t dcf77_inverted_samples = 1;
const uint8_t dcf77_analog_samples = 1;

const uint8_t dcf77_monitor_pin = A4; // == D18 for standard Arduinos

const uint8_t lower_output_pin = 2;
const uint8_t upper_output_pin = 17;


void stopTimer0() {
   // ensure that the standard timer interrupts will not
   // mess with msTimer2
   TIMSK0 = 0;
}

ISR(TIMER2_COMPA_vect) {
   process_one_sample();
}

void initTimer2() {
   // Timer 2 CTC mode, prescaler 64
   TCCR2B = (1<<WGM22) | (1<<CS22);
   TCCR2A = (1<<WGM21);
   
   // 249 + 1 == 250 == 250 000 / 1000 =  (16 000 000 / 64) / 1000
   OCR2A = 249;
   
   // enable Timer 2 interrupts
   TIMSK2 = (1<<OCIE2A);
}

uint8_t sample_input_pin() {
   const uint8_t sampled_data = dcf77_inverted_samples ^
       (dcf77_analog_samples? (analogRead(dcf77_analog_sample_pin) > 200):
                               digitalRead(dcf77_sample_pin));

   digitalWrite(dcf77_monitor_pin, sampled_data);
   return sampled_data;
}

void led_display_signal(const uint8_t sample) {
   static uint8_t ticks_per_cycle = 12;
   static uint8_t rolling_pin = lower_output_pin;
   static uint8_t counter = 0;

   digitalWrite(rolling_pin, sample);
       
   if (counter < ticks_per_cycle) {
       ++counter;
   } else {
       rolling_pin = rolling_pin < upper_output_pin? rolling_pin + 1: lower_output_pin;
       counter = 1;
       // toggle between 12 and 13 to get 12.5 on average
       ticks_per_cycle = 25-ticks_per_cycle;
   }
}

const uint16_t samples_per_second = 1000;
const uint8_t bins                = 100;
const uint8_t samples_per_bin     = samples_per_second / bins;

volatile uint8_t gbin[bins];
boolean samples_pending = false;

void process_one_sample() {
   static uint8_t sbin[bins];
   
   const uint8_t sample = sample_input_pin();
   led_display_signal(sample);

   static uint16_t ticks = 999;  // first pass will init the bins    
   ++ticks;

   if (ticks == 1000) {
       ticks = 0;
       memcpy((void *)gbin, sbin, bins);
       memset(sbin, 0, bins);
       samples_pending = true;    
   }

   sbin[ticks/samples_per_bin] += sample;    
}

void setup() {
   Serial.begin(115200);
   Serial.println();

   pinMode(dcf77_sample_pin, INPUT);
   digitalWrite(dcf77_sample_pin, HIGH);

   pinMode(dcf77_monitor_pin, OUTPUT);
   
   for (uint8_t pin = lower_output_pin; pin <= upper_output_pin; ++pin) {
       pinMode(pin, OUTPUT);
       digitalWrite(pin, LOW);
   }

   initTimer2();
   stopTimer0();
}


int32_t sign(int32_t value) {
   return (value>0) - (value<0);
}

void loop() {
   static int64_t count = 0;
   uint8_t lbin[bins];    
   
   if (samples_pending) {      
       cli();
       memcpy(lbin, (void *)gbin, bins);
       samples_pending = false;
       sei();
     
       ++count;
       // ensure the count values will be aligned to the right
       for (int32_t val=count; val < 100000000; val *= 10) {
           Serial.print(' ');
       }
       Serial.print((int32_t)count);
       Serial.print(", ");      
       for (uint8_t bin=0; bin<bins; ++bin) {
           switch (lbin[bin]) {
               case  0: Serial.print(bin%10? '-': '+'); break;
               case 10: Serial.print('X'); break;
               default: Serial.print(lbin[bin]);
           }
       }
       Serial.println();
    }  
}


Mit einem Blinkenlighty sieht der Output an einem DCF77 Module dann etwa wie angehängt aus. Das Log wird erzeugt, daß pro Minute 1000 Samples gezogen werden und je 10 Samples zusammengefasst werden. Von einem + Zeichen zum nächsten sind also genau 100 Millisekunden. Wenn man in den angehängten Log schaut, dann sieht man, danß nach 346s die Phase bei etwas +200ms ist und nach 6511s bei etwa +400ms ist. Ergebnis: innerhalb von 6511s-346s = 6516s ist der Blinkenlighty 0,2s zu schnell. Oder 0.2s/6516s = 0.000030694 = 30.7 ppm zu schnell.

Jetzt die eigentliche Frage: wer hat hier einen Uno und ein DCF77 Modul und würde den Sketch mal auf dem Uno für 2 Stunden laufen lassen und mir das Log zur Verfügung stellen?

Code: [Select]

     340, +---------+---------3XXXXXXXXXXXXXXXXXXX6---------+---------+---------+---------+---------+---------
     341, +---------+---------3XXXXXXXXXX2--------+---------+---------+---------+---------+---------+---------
     342, +---------+---------4XXXXXXXXXXXXXXXXXXXX3--------+---------+---------+---------+---------+---------
     343, +---------+---------3XXXXXXXXXX1--------+---------+---------+---------+---------+---------+---------
     344, +---------+---------2XXXXXXXXXXXXXXXXXXXX2--------+---------+---------+---------+---------+---------
     345, +---------+---------5XXXXXXXXXXXXXXXXXXXX2--------+---------+---------+---------+---------+---------
     346, +---------+---------+XXXXXXXXXX2--------+---------+---------+---------+---------+---------+---------
     347, +---------+---------3XXXXXXXXXX---------+---------+---------+---------+---------+---------+---------
     348, +---------+---------+XXXXXXXXXX2--------+---------+---------+---------+---------+---------+---------
     349, +---------+---------3XXXXXXXXXX8--------+---------+---------+---------+---------+---------+---------
     350,


Code: [Select]

    6500, +---------+---------+---------+---------4XXXXXXXXXX3--------+---------+---------+---------+---------
    6501, +---------+---------+---------+---------4XXXXXXXXXX2--------+---------+---------+---------+---------
    6502, +---------+---------+---------+---------4XXXXXXXXXXXXXXXXXXXX---------+---------+---------+---------
    6503, +---------+---------+---------+---------2XXXXXXXXXXXXXXXXXXXX---------+---------+---------+---------
    6504, +---------+---------+---------+---------3XXXXXXXXXXXXXXXXXXX8---------+---------+---------+---------
    6505, +---------+---------+---------+---------2XXXXXXXXXXXXXXXXXXXX2--------+---------+---------+---------
    6506, +---------+---------+---------+---------3XXXXXXXXXX1--------+---------+---------+---------+---------
    6507, +---------+---------+---------+---------3XXXXXXXXXXXXXXXXXXX9---------+---------+---------+---------
    6508, +---------+---------+---------+---------2XXXXXXXXXX2--------+---------+---------+---------+---------
    6509, +---------+---------+---------+---------2XXXXXXXXXXXXXXXXXXX9---------+---------+---------+---------
    6510, +---------+---------+---------+---------4XXXXXXXXXXXXXXXXXXX9---------+---------+---------+---------
    6511, +---------+---------+---------+---------+XXXXXXXXXXXXXXXXXXXX---------+---------+---------+---------
    6512, +---------+---------+---------+---------1XXXXXXXXX9---------+---------+---------+---------+---------
    6513, +---------+---------+---------+---------2XXXXXXXXX8---------+---------+---------+---------+---------
    6514, +---------+---------+---------+---------2XXXXXXXXXXXXXXXXXXXX---------+---------+---------+---------
    6515, +---------+---------+---------+---------4XXXXXXXXXXXXXXXXXXXX---------+---------+---------+---------
    6516, +---------+---------+---------+---------2XXXXXXXXXX4--------+---------+---------+---------+---------
    6517, +---------+---------+---------+---------4XXXXXXXXXXXXXXXXXXXX1--------+---------+---------+---------
    6518, +---------+---------+---------+---------2XXXXXXXXXX2--------+---------+---------+---------+---------
    6519, +---------+---------+---------+---------2XXXXXXXXXX2--------+---------+---------+---------+---------
    6520, +---------+---------+---------+---------1XXXXXXXXXXXXXXXXXXX9---------+---------+---------+---------
Check out my experiments http://blog.blinkenlight.net

udoklein

Nachtrag: ich kenne den Beitrag hier http://forum.arduino.cc/index.php?topic=60662.0. Und selbstverständlich - wenn jemand einen Uno und einen Frequenzzähler oder ein Oszi hat, dann nehme ich auch direkt die gemessenen Frequenzen :)
Check out my experiments http://blog.blinkenlight.net

sth77

#2
Aug 14, 2013, 08:58 pm Last Edit: Aug 14, 2013, 09:12 pm by sth77 Reason: 1
Habe hier einen Uno der ersten Revision und mein Oszilloskop gibt gemessen am Resonator 15,93 MHz aus.

[edit] Der 16MHz-Quarz des Atmega8U2 hingegen steht wie festgenagelt auf glatten 16 MHz. ;) Gemessen mit einem UNI-T 2052 (nur 50MHz, 1 GS/s).

[edit]² Vergleichsmessung zum Arduino Leonardo hinzugefügt.
Mein verwaister Arduino-Blog: http://www.sth77.de/ - letzter Eintrag: Diamex-ISP in der irgendwann mal aktuellen Arduino-IDE 1.6.4

sth77

Code: [Select]

150, XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX3------+---4XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      151, XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX9-------+---------+--6XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      152, XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX6------+---------+--6XXXXXXXXXXXXXXXXXXXXXXXXXXXXX5XXXXXX
      153, XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX7-------+--49XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      154, XXXXXXXXXXXXXXXX987XXXXXXXXXXXXXXXXXXXXXXXX-------+--5XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      155, XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX4-------+-1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      156, XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX8-------+--6XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX9XXXXXXXXX7XXXXX
      157, XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX2-------+--3XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      158, XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX7-------+---------+-1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      159, XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX9XXXXX4------+---------+-5XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      160, XXXXXXXXXXXXXXXXXXX8XXXXXXXXXXXXXXXXXXXXXX4-------+-8XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      161, XXXXXXXXXXX7-9XXXXXXXXXXXXXXXXXXXXXXXXXXX7--------+--8XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      162, XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX8--------+---------+-2XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      163, XXXXXXXXXXXXXXXXXXX69XXXXXXXXXXXXXXXXXXXX4--------+-4XXXXXXXXX7XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      164, XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX2-------+-5XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      165, XXXXXXXXXXXXXXXXXXXXXX3XXXXXXXXXXXXXXXXXX7--------+---------+1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      166, XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX---------+---------+4XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      167, XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX7--------+---------+7XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      168, XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX7---------+-9XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      169, XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1--------1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      170, XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX97XXXXXX5---------+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX


Das ist wohl nicht das, was du haben möchtest, die X und die - sind bei mir invertiert. Ist ein Pollin-Modul, kannst du dein Programm dafür umschreiben? Wollte ungern noch einen Negator zusammenbasteln.
Mein verwaister Arduino-Blog: http://www.sth77.de/ - letzter Eintrag: Diamex-ISP in der irgendwann mal aktuellen Arduino-IDE 1.6.4

jurs


Deshalb kann ich nicht testen wie schlecht die Resonatoren wirklich sind.
Um das auszuprobieren haben ich folgenden kleinen Sketch geschrieben:


Ganz unterschiedlich. Bei Zimmertemperatur gibt es gewaltige Streuungen.


Jetzt die eigentliche Frage: wer hat hier einen Uno und ein DCF77 Modul und würde den Sketch mal auf dem Uno für 2 Stunden laufen lassen und mir das Log zur Verfügung stellen?


Ich habe irgendwann schon mal meine Resonator-Boards im Vergleich mit einer DS1307 getestet. Anbei habe ich mal ein Logfile mit dem (bei weitem!) am weitesten abweichenden Board erstellt. Sind deutlich unter 2 Stunden, aber bei der großen Frequenzabweichung dürftest Du auch so schon was sehen.

Das DCF-Modul ist wohl ca. 20 Jahre alt von Conrad.

Meine übrigen Resonator-Boards liegen bei ungefähr einem viertel bis einem drittel der Abweichung von dem Board, dessen Logfile ich drangehängt habe.

sth77


Das DCF-Modul ist wohl ca. 20 Jahre alt von Conrad.

Meine übrigen Resonator-Boards liegen bei ungefähr einem viertel bis einem drittel der Abweichung von dem Board, dessen Logfile ich drangehängt habe.


Sieht ja meinem Ergebnis recht ähnlich, also auch mit getauschten "X" und "-". Soweit ich weiß, hat das DCF-Modul zwei Ausgänge. Wenn du den anderen nimmst, hast du die Datenstruktur, die analog zu Udos ist.
Mein verwaister Arduino-Blog: http://www.sth77.de/ - letzter Eintrag: Diamex-ISP in der irgendwann mal aktuellen Arduino-IDE 1.6.4

udoklein

@Jurs: Super! Danke. Ich dachte ja schon, daß die Resonatoren schwach sind. Aber das so im Log zu sehen ist schon was anderes.

@STH77, entweder Du setzt const uint8_t dcf77_inverted_samples = 1; von 1 auf 0 oder Du schickst mir den Log so. Die Drift kann man auch an einem invertierten Log sehen. Nur mal so zum vergleich wie das bei Dir aussieht würde mich schon interessieren.
Check out my experiments http://blog.blinkenlight.net

sth77

Ach Mensch, da gibt es ja die passende Änderungsmöglichkeit. Habe ich gestern gar nicht mehr wahrgenommen. Werde ich nachher mal testen.
Mein verwaister Arduino-Blog: http://www.sth77.de/ - letzter Eintrag: Diamex-ISP in der irgendwann mal aktuellen Arduino-IDE 1.6.4

da_user

Hätte ich.

An welchen Pin muss ich das DCF-77 Modul hängen? A5?

jurs


An welchen Pin muss ich das DCF-77 Modul hängen? A5?


Ja.

Ich habe hier nochmal eine zweite Messreihe, allerdings nicht mit einem UNO-kompatiblen Board, sondern mit einem Sainsmart MEGA2560 R3 gemacht und mit einem DCF-Modul von Pollin.

Irgendwie sieht das so aus, als wenn der noch mehr Zeit verliert, obwohl ich eigentlich im Gedächtnis hatte (per DS1307-Vergleich), dass dieser eigentlich genauer ticken sollte als der TinyOS UNO, dessen Logfile ich heute Vormittag gepostet hatte.

Ob mir da wohl mein Gedächtnis einen Streich spielt, sich das Timing durch Temperaturänderung oder Bauteilealterung stark verändert hat, meine damalige Methode zum Ausmessen des Board-Timings inkorrekt war, oder ist Dein Test-Sketch so auf den UNO optimiert, dass auf einem MEGA prinzipbedingt eine höhere Abweichung vom Solltakt festgestellt wird als auf einem UNO Board?


sth77

So, habe dann auch noch ein paar Aufzeichnungen mit dem Arduino Uno gemacht, siehe Dateianhang.
Mein verwaister Arduino-Blog: http://www.sth77.de/ - letzter Eintrag: Diamex-ISP in der irgendwann mal aktuellen Arduino-IDE 1.6.4

udoklein

Danke Jurs + STH für die Messungen.

@Jurs: was die Genauigkeit angeht: es kann schon sein, daß der Uno mal genauer und mal ungenauer als Dein Mega läuft. Der Punkt ist, daß Oszillatoren abhängig von Alterung, Temperatur, Vibrationen, Lage, Spannung und sonst noch alles mal so mal so schneller oder langsamer laufen. Bei Resonatoren ist der Effekt stärker. Mein Messsketch ist auf genau 16 MHz Zieltakt eingestellt und die Zeitreferenz ist DCF77. Wenn da was wegläuft, dann ist das der Systemtakt. Was man daraus lernt ist, daß man Resonatoren nicht mit einem konstanten Offset kompensieren kann :(


Check out my experiments http://blog.blinkenlight.net

da_user

Ich hab mal für ein paar Stunden gemessen. Datei im Anhang (hoffe ich).

Quote
und die Zeitreferenz ist DCF77.


Laut Wikipedia liegt die Ungenauigkeit bei klassischen DCF77-Empfängern bei 100ms,...?

udoklein

Erst einmal Danke für den Log.

Du meinst den Absatz:

Quote

Auch mit optimierten Dekodieralgorithmen und keiner zu starken Bandbegrenzung im Empfangsfilter liegt die zeitliche Unsicherheit, mit der der exakte Beginn der amplitudenmodulierten Sekundenmarken erkannt werden kann, bei wenigstens etwa 100 Mikrosekunden. Haushaltsübliche Funkuhren setzen schmalbandige Empfänger ein (mit 10 Hz Bandbreite) und können daher den Sekundenbeginn nur auf 0,1 s genau feststellen.


Das stimmt so nur bedingt. Erstens hat jede Uhr zunächst das Problem der Laufzeit des Zeitsignals vom Empfänger. Je nach Abstand zur Antenne kommen da selbst in Deutschland auch mal mehr als 1ms zusammen.

Der Witz beim DCF77 ist aber vor allem die Langzeitkonstanz

Quote

Das Trägersignal von 77,5 kHz ist in Frequenz und Phasenlage mit der steuernden primären Atomuhr synchronisiert und besitzt deshalb nur geringe Abweichungen von der Sollfrequenz. Über einen Tag sind dies weniger als relativ 2 · 10?12, im Mittel über 100 Tage um weniger als relativ 2 · 10?13. Es kann somit auch ohne Auswertung der Zeitinformation als Eichfrequenz für sehr genaue Hoch- und Niederfrequenzgeneratoren benutzt werden.

Check out my experiments http://blog.blinkenlight.net

da_user

Achso... kurz gesagt:

Wenn die Zeit wirklich um -100ms abweicht, dann weicht sie die nächsten 100 Tagen auch ziemlich genau die gleichen 100ms ab.


Alles klar.

Go Up