Binäre DCF77 Uhr mit exponentiellem Filter und Blinkenlighty

Interessanter Beitrag! Bin aber leider ebenfalls aus Zeitgründen noch nicht zum Testen gekommen. Hoffentlich schaffe ich das noch vor den nächsten Semesterferien :fearful:

Aber eine Frage kommt mir doch auf:
Du tastest mit einer Frequenz von 1 kHz ab. Fehlt da nicht noch irgendeine Form von analogem Tiefpass vor der digitalisierung, damit höherfrequente Störungen nicht in den niederfrequenten Teil des Spektrums rutschen?
Soetwas haben wir jedenfalls zum Thema Analog-Digitalwandlung in Verbindung mit digitaler Regelung in einer Vorlesung gehört...

Ich habe am Wochenende auch mal den DCF-Empfänger aus dem Conrad-Wecker ausgeschnitten. Die beiden Leiterbahnen die zum MC des Weckers gingen habe ich auf zwei digitale Eingänge gelegt. Einer liefert eine 1, der andere eine 0, daher vermute ich mal Signal und invertiertes Signal. Allerdings habe ich bisher noch keinerlei Änderungen an den Ausgängen feststellen können, ich muss mir noch eine bessere Position für den Aufbau suchen, zur Zeit sind da zu viele Netzteile und Monitore in der näheren Umgebung.

mkl0815:
Die beiden Leiterbahnen die zum MC des Weckers gingen habe ich auf zwei digitale Eingänge gelegt. Einer liefert eine 1, der andere eine 0, daher vermute ich mal Signal und invertiertes Signal. Allerdings habe ich bisher noch keinerlei Änderungen an den Ausgängen feststellen können, ich muss mir noch eine bessere Position für den Aufbau suchen, zur Zeit sind da zu viele Netzteile und Monitore in der näheren Umgebung.

Es ist zwar richtig, dass die DCF-Module von Conrad auch einen invertierten ausgang haben, so recht kann ich mir das bei einer Funkuhr jedoch nicht vorstellen. Da halte ich es eher für einen Eingang, um das Modul zu Stromsparzwecken ein- und ausschalten zu können.
Die Wikipedia schreibt im Funkuhr-Artikel dazu:

Obwohl das Zeitsignal kontinuierlich gesendet wird, wird es aus Stromspargründen oft nur ab und zu zum Nachstellen abgefragt. Bei Uhren, die mit größeren Zellen betrieben werden, ist ein Empfang jede volle Stunde üblich, bei Armbanduhren mit Knopfzellen oder mit Solarzellen nur einmal pro Tag, meistens zwischen 2:00 und 4:00 Uhr morgens.

Einen entsprechenden Eingang haben bspw. auch die Pollin-Module.

Hmm, guter Tipp. Bei den Pollin-Modulen wird der ON/OFF Eingang glaub ich auf Masse gezogen, um das Modul zu aktivieren. Ich werde das heute Abend mal testen.

Du tastest mit einer Frequenz von 1 kHz ab. Fehlt da nicht noch irgendeine Form von analogem Tiefpass vor der digitalisierung, damit höherfrequente Störungen nicht in den niederfrequenten Teil des Spektrums rutschen?

Wieso sollte es einen analogen Tiefpass brauchen? Der exponentielle Filter ist doch ein Tiefpass. "Analoge" Filter sind nicht auf magische Weise besser.

Kann der Digitale Filter denn die Aliaseffekte ausgleichen, die BEIM Abtasten entstehen?

And1G: ich dachte Du hast eine Vorlesung zu dem Thema gehört. Wieso fragst Du dann mich? Und vor allem wieso stellst Du Dich dumm? Selbstverständlich kann überhaupt kein Filter Alias Effekte ausgleichen die ins Passband rutschen. Die Frage ist nur: treten die tatsächlich auf? in meinem Fall also: gibt es Überlagerungen die nahe bei 500 Hz oder einer Oberwelle davon sind? Bei einem Empfänger der eine Bandbreite von wohel eher <300 Hz hat? Ich würde sagen nein. Wenn Du aber anderer Meinung bist, dann belege das doch bitte etwas genauer. Auf die Begründung bin ich mal gespannt.

Warum ich frage? Na weil meine bisherigen Kenntnisse etwas anderes sagen als das was du realisiert hast. Da wundert man sich und stellt dann halt eine Frage, ganz normaler Vorgang. Es hätte ja durchaus sein können, dass irgendetwas da zwischendurch eingekoppelt wird.
Kein Grund sich gleich angegriffen zu fühlen oder so genervt zu reagieren.

Dir ist aber schon klar, daß meine Implementation funktioniert? Von daher ist die Frage

Kann der Digitale Filter denn die Aliaseffekte ausgleichen, die BEIM Abtasten entstehen?

schon etwas offensiv. Dass dich das wundert war aus der Frage nicht zu ersehen. Die hat sich vom Ton eher angehört wie: "Du hast nur Glück und weisst vermutlich nicht was Du tust". Hast Du Dir die Quellen auf meiner Seite angesehen. Ich habe die gelesen und ausreichend weit verstanden.

Ich habe mal eine blöde Frage.
Ich experimentiere gerade mit dem Filter rum und hätte aber gerne den I2C frei.
Deshalb wollte ich den Eingangspin für das DCF77-Modul ändern.
Ich dachte dies geht hier:

const uint8_t dcf77_sample_pin = 19; // A5

19 = Analog 5
Wenn ich, sagen wir mal Analog 1 haben will:

const uint8_t dcf77_sample_pin = 15; // A1

Aber dann macht er nichts mehr.

Wo denke ich falsch?

MueThoS:
Aber dann macht er nichts mehr.

Wo denke ich falsch?

Wenn Du Dich auf den Original-Code beziehst:

const uint8_t dcf77_sample_pin = 19; // A5
const uint8_t dcf77_analog_sample_pin = 5;
...
//const uint32_t input = digitalRead(dcf77_sample_pin) * decimal_offset;
const uint32_t input = analogRead(dcf77_analog_sample_pin)>200? decimal_offset: 0;

Deklariert sind sowohl dcf77_sample_pin als auch dcf77_analog_sample_pin.

Die auskommentierte Codezeile bezieht sich auf dcf77_sample_pin und die ausgeführte Codezeile aber auf dcf77_analog_sample_pin.

Wenn Du den Code so verwendest, mußt Du entweder

  • die Deklaration für dcf77_analog_sample_pin ändern.
    oder
  • die Codezeile verwenden, in der dcf77_sample_pin verwendet wird und die andere auskommentieren.

Jetzt wo Du es sagst. :astonished:

Hab ich nicht gesehen.

Danke!

Ich glaube ich werde das nie lernen mit den Variablen Typen.
Ich versuche gerade das Funkuhrsignal in eine RTC zu schreiben.
von der Funkuhr bzw der Time.h bekomme ich ja :

sekund() minute() hour() year() month() day()

Das sind int wenn ich mich nicht irre. Diese werden mir auch schön im seriellen Monitor angezeigt:

17.12.2012 16:31:02

So die RTC (ich habe hier eine softI2C) nimmt die Daten richtig an wenn ich sie so schreibe:

uint8_t d[4];
d[3]=0x12; // Jahr
d[2]=0x12; // Monat
d[1]=0x16; // Tag
d[0]=0x01; // Wochentag

Das ist HEX-Schreibweise wenn ich mich nicht irre.
Wenn ich jetzt einfach die ints versuche zu übergeben sieht meine ausgelesene RTC so aus;

RTC: 11.0C.2001 01:1F:01

Das ist irgendwie falsch!
Gehe ich recht in der Annahme das ich aus dem int ein HEX machen muss?
Und wenn ja, wie?

MueThoS:
Gehe ich recht in der Annahme das ich aus dem int ein HEX machen muss?
Und wenn ja, wie?

Nein, Du mußt nur Deine RTC-Library korrekt anwenden!

Dazu schaust Du nach, welche RTC-Library Du installiert hast (da gibt es wohl viel mehr als nur eine).
Dann lädst Du Dir das Beispielprogramm zu dieser RTC-Library in Deine Arduino-Software.
Dann studierst Du das Beispielprogramm.

Beispielprogramme sind kommentiert und in den Programmkommentaren stehen die notwendigen Hinweise, wie die Library angewendet wird.

Mit 0x beginnende Zahlen sind unter C die Hex-Schreibweise im 16er System
0x12 = 116 + 2 = 18
0x16 = 1
16 + 6 = 22
0x01 = 0*16 + 1 = 1

Dies versuche ich ja!

Ich habe, wie gesagt, die softi2c nennt sich i2cMaster.
Das Beispiel Programm habe ich offen.

Und dort ist folgendes interessant:
wenn ich die Zeit stellen will wird dies aufgerufen:

uint8_t bcdRead(uint8_t min, uint8_t max, uint8_t &n) {
  uint16_t v;
  if (!hexRead(v)) return false;
  uint8_t d = 10 * (v >> 4) + (v & 0XF);
  if ((v >> 4) > 9 || (v & 0XF) > 9 || d < min || d > max) {
    PgmPrintln("Invalid");
    return false;
  }
  n = v;
  return true;
}

Was ich hier noch verstehe ist das hexRead aufgerufen wird.
dann kommt etwas was ich nicht verstehe. (uint8_t d = 10 * (v >> 4) + (v & 0XF):wink:
Und dann wird geschaut ob die Werte gültig sind.

hexRead:

uint8_t hexRead(uint16_t &v) {
  uint16_t n = 0;
  while (!Serial.available());
  while (Serial.available()) {
    uint8_t c = Serial.read();
    n <<= 4;
    if ('a' <= c && c <= 'f') {
      n += c - ('a' - 10);
    }
    else if ('A' <= c && c <= 'F') {
      n += c - ('A' - 10);
    }
    else if ('0' <= c && c <= '9') {
      n +=  c - '0';
    }
    else {
      PgmPrintln("Invalid entry");
      return false;
    }
    delay(10);
  }
  v = n;
  return true;
}

es wird gewartet bis was über Seriell rein kommt.
Dann werden die kommenden Daten in c gelesen
dann wird geschaut ob die Werte Zahlen sind (so denke ich)
und der rest ist wieder Bahnhof.

Hier wird die RTC beschrieben:

uint8_t writeDS1307(uint8_t address, uint8_t *buf, uint8_t count) {
  // issue a start condition, send device address and write direction bit
  if (!rtc.start(DS1307ADDR | I2C_WRITE)) return false;

  // send the DS1307 address
  if (!rtc.write(address)) return false;

  // send data to the DS1307
  for (uint8_t i = 0; i < count; i++) {
    if (!rtc.write(buf[i])) return false;
  }

  // issue a stop condition
  rtc.stop();
  return true;
}

Und wenn ich mir das anschaue würde ich sagen uint8_t *buf sollte mein Wert sein.
Also ein INT würde ich vermuten. Aber meine sekund() usw sind doch INTs

Und weil ich das nicht verstehe komme ich nicht weiter.

MueThoS:
Und weil ich das nicht verstehe komme ich nicht weiter.

Ich glaube, Du verhedderst Dich da in den Untiefen von Umrechnungen mit Zahlensystemen, von denen Du weder etwas verstehst noch dass Du sie benötigst.

BCD Zahlen sind Binary Coded Dezimals, binärcodierte Dezimalzahlen:

Damit kann man jede dezimale Ziffer von 0 bis 9 mit vier Bits darstellen.

Das wirst Du mit Sicherheit alles gar nicht benötigen.

Was Du immer benötigst, wenn es um Zeiten geht, das ist die Unix-Zeit.

Das ist ein long integer (32-Bit) Ganzzahlenwert mit der Anzahl der Sekunden seit dem 01.01.1970.

DAS ist es, womit Programmierer ihre Uhrzeiten handeln. Und wenn Du irgendeine Zeit-Library hast, dann gibt es einerseits bequeme Funktionen, um Tag, Monat, Jahr, Stunde, Minute, Sekunde in Unixzeit umzurechnen. Und umgekehrt genauso.

Und für Deine RTC-Library gibt es mit ziemlicher Sicherheit sowohl eine Schreibfunktion, der Du die Unixzeit übergeben kannst und auch eine Lesefunktion, von der Du die Unixzeit aus der Uhr geliefert bekommst.

Du hast es also im Endeffekt nur mit vier Funktionen zu tun, und die fressen allesamt Dezimalzahlen:

  1. Eine Umrechenfunktion von Tag, Monat, Jahr, Stunde, Minute, Sekunde in Unixzeit
  2. Eine Umrechenfunktion von Unixzeit in Tag, Monat, Jahr, Stunde, Minute, Sekunde
  3. Eine Uhr-Stellen Funktion, die eine Unixzeit zum Stellen der RTC übergeben bekommt
  4. Eine Uhr-Abfragen Funktion, die eine Unixzeit von der RTC geliefert bekommt

Wenn Du diese vier Funktionen bei Dir nicht findest, schreib mal genau, welche Time- und Realtime-Libraries Du installiert hast, dann schau ich mal in die Library rein!

Und Zahlensysteme wie Binärsystem, Hexadezimalsystem, und BCD-Zahlen kannst Du sicher getrost auf Lücke setzen, wenn Du nur eine Uhr stellen oder abfragen oder mit Zeiten rechnen möchtest, das sollte alles mit Dezimalzahlen zu erschlagen sein.

Unter "i2cmaster" finde ich nur eine Library, die was mit LCD-Displays zu tun hat, nicht mit RTC Uhren.

Also,
ich habe folgende Libraries die ich nutze:
softi2c von folgender Seite: (erster Beitrag)
http://forums.adafruit.com/viewtopic.php?f=25&t=13722
die Heißt dann I2cMaster

Time.h (Standard)

Hier aus diesem Fred:
DCF77.h
MsTimer2.h

Ich habe auch schon versucht die Libraries zu analysieren aber ich komme eben nicht weiter, deshalb frag ich.

MueThoS:
Also,
ich habe folgende Libraries die ich nutze:
softi2c von folgender Seite: (erster Beitrag)
http://forums.adafruit.com/viewtopic.php?f=25&t=13722
die Heißt dann I2cMaster

Time.h (Standard)

Hier aus diesem Fred:
DCF77.h
MsTimer2.h

Ich habe auch schon versucht die Libraries zu analysieren aber ich komme eben nicht weiter, deshalb frag ich.

Das ist jetzt aber nicht Dein Ernst, oder?

Du hast keine RTC-Library für Deine RTC in Verwendung?
Warum denn das nicht?

Als normaler Arduino-Anfänger macht man es so:

  1. Man schaut nach, was für ein Uhrenbaustein auf der RTC verbaut ist, z.B. ein Dallas 1307
  2. Dann sucht man eine Arduino-Library zur Ansteuerung, z.B. für einen Dallas 1307
  3. Dann verwendet man die Funktionen der Library zum Auslesen und Einstellen der Uhr

Was Du da vorhast, die Bit-Schubsereien über den I2C-Bus selbst zu codieren, ist absolut NICHT anfängergeeignet.

Anfängergeeignet zum Stellen und Auslesen einer RTC mit dem gängigen Dallas 1307 Chip wäre beispielsweise so eine Library:

Vielleicht passt's ja und Du hast eine RTC mit 1307, dann schau da mal rein!

Vielleicht drücke ich mich nur nicht richtig aus.

Die RTClib, die Du verlinkt hast, habe ich. Würde auch funktionieren. Möchte ich für meinen Anwendungsfall aber nicht nutzen.
Es sei denn ich kann sie auf andere PINs legen.

Die Lib die ich hier nutze (I2cMaster) Funktioniert mit dem Beispiel auch.
In meiner Umsetzung funktioniert es auch wenn ich die Daten mal zum Testen hard code:

...
d[1]=0x17;
...
writeDS1307(3, d, 4)

Für Heute den 17ten.

Nur leider ist zwischen day() der Time-Lib und 0x17 ein unterschied.

Das ist BCD :wink:
Binär Codierte Dezimal - Zahlen: 4 Bit Einerstelle, 2 bis 4 Bit Zehnerstelle.

pups-einfach: Schau auf Seite 5 dieses Datenblatts, http://www.sparkfun.com/datasheets/Components/DS1307.pdf
Da ist jedes Bit der 7 Datenbytes einer 1307 beschrieben.
(jedenfalls einfacher als auf einem Arduino mit Unix-Zeit rumzumachen)

Nur leider ist zwischen day() der Time-Lib und 0x17 ein unterschied.

byte day() {
byte ram = readDS1307Byte(3); // offset des DS1307 Bytes mit dem Kalendertag.
return (ram>>4)*10 + ram&0x0f;
}

Dafür brauchst du wirklich keine Library :wink:

Es sei denn ich kann sie auf andere PINs legen.

I2C sollte man nicht auf andere Pins legen...