Programm zur Uhrzeitdekodierung

Testaufbau:

Zur Anzeige der Uhrzeit wird der Testaufbau DCF77-Empfänger um eine 7-Segmentanzeige mit I2C-Schnittstelle erweitert.

Zusätzliche verwendete Bauteile:

  • 1 7-Segmentanzeige mit I2C-Schnittstelle von Sparkfun
  • 2 Widerstände 10 kOhm


Programm:

Das nachfolgende Programm zeigt die gesendete Uhrzeit (hh:mm) auf der 7-Segmentanzeige an.

Die Ermittlung des Zustands des Signalpins vom DCF77-Empfängers erfolgt durch "Polling", d.h. der Zustand des Signalpins wird im Programmteil Loop ständig abgefragt. Bei jedem Zustandswechsel wird die aktuelle Systemzeit mit "millis()" gespeichert und daraus werden dann die Impulszeiten ermittelt.


Verwendete Libraries

Neben der Standard-Library Wire verwende ich zur Ansteuerung der 7-Segmentanzeige noch meine Library MySparkfun7SegI2C (siehe 7-Segm.anz. Sparkfun) und nutze dabei die Funktion "sendTime(dcf77Stunde, dcf77Minute)", wo also zwei Bytewerte für Stunde und Minute an die Funktion zur Anzeige übergeben werden. Eine Anpassung an eine andere Anzeige wäre also nur hier erforderlich.

Das Programm dekodiert die Uhrzeit (Stunde und Minute) aus dem empfangenen Signal und führt einen Paritäts-Check durch. Ist dieser in Ordnung, wird die Uhrzeit am Display ausgegeben.


Nachträglich eingefügte Überprüfungen (Verison 1.1)

Da es trotz positiver Paritäts-Check zu falschen Zeitangaben gekommen ist (so wurde z.B. einmal die Stunde "30" angezeigt), habe ich das Programm um folgende Überprüfungen erweitert:

  • Vor der Telegrammauswertung wird die Anzahl der zu empfangenen Zeitmarken auf Richtigkeit überprüft
  • Die dekodierten Werte für Stunde und Minute werden nun auf Plausibilität überprüft. Eine Stunde "30" oder eine Minute "62 kann so nicht mehr als richtig interpretiert werden, auch wenn der Paritäts-Check positiv ist.


//DCF77_03.ino
//Code fuer Arduino
//Author Retian
//Version 1.1

#include <MySparkfun7SegI2C.h>
#include <Wire.h>

MySparkfun7SegI2C My7Seg(0x71);

#define signalPin 2
#define ledPin 3

char dcf77Signal;
char buffer;

unsigned long nowTime, lastTime;
int diffTime;

byte impulsLevel; // Impulsdauer 100ms => logisch 0, 200 ms => logisch 1
byte Impuls[59]; // eingehende Impulse
byte impulsWert[8] = {1, 2, 4, 8, 10, 20, 40, 80}; //Impulswertigkeit für Level logisch 1
byte impulsZaehler = 0; //Anzahl eingehende Impulse

byte dcf77Stunde = 0;
byte dcf77Minute = 0;

void setup() {
  pinMode(signalPin, INPUT);
  pinMode(ledPin, OUTPUT);
  My7Seg.test7Seg();

}

void loop() {
  dcf77Signal = digitalRead(signalPin);
  if (dcf77Signal != buffer)
  {
    nowTime = millis();
    delay(5); //Wartezeit bis eingeschwungener Zustand
    diffTime = nowTime - lastTime;
    lastTime = nowTime;
    if (diffTime < 150) impulsLevel = 0;
    else if (diffTime < 250) impulsLevel = 1;
    else if (diffTime > 1000)
    {
      if (impulsZaehler == 59 || impulsZaehler == 60) dekodiereZeit();
      impulsZaehler = 0;
    }
    if (dcf77Signal == 0) // Abfrage auf "1", wenn das invertierte Signal verwendet wird
    {
      Impuls[impulsZaehler] = impulsLevel;
      impulsZaehler++;
    }
    digitalWrite(ledPin, dcf77Signal);
    buffer = dcf77Signal;
  }
}

void dekodiereZeit()
{
  bool dateTimeOk = true;
  byte paritaetStunde = 0;
  byte paritaetMinute = 0;

  dcf77Stunde = 0;
  dcf77Minute = 0;

  //Ueberpruefen der Stundenparitaet
  for (byte i = 29; i < 35; i++) paritaetStunde ^= Impuls[i];

  if (Impuls[35] != paritaetStunde) dateTimeOk = false;

  //Ueberpruefen der Minutenparitaet
  for (byte i = 21; i < 28; i++) paritaetMinute ^= Impuls[i];
  if (Impuls[28] != paritaetMinute) dateTimeOk = false;

  //Zuweisen der Impulswertigkeit
  for (byte i = 29; i < 35; i++) (Impuls[i] == 1 ? dcf77Stunde += impulsWert[i - 29] : 0);
  for (byte i = 21; i < 28; i++) (Impuls[i] == 1 ? dcf77Minute += impulsWert[i - 21] : 0);

  //Ueberpruefen des Wertebereiches
  if (dcf77Stunde > 23 || dcf77Minute > 59) dateTimeOk = false;

  if (dateTimeOk)
  {
    My7Seg.sendTime(dcf77Stunde, dcf77Minute);
  }
}


Weiter zu RTC synchronisieren