DCF77 decoder

I'm programming for arduino for quite a while now and since there's not that much information about the DCF77 Signal from Mainflingen, Germany, I thought I open a topic for it.

I've wrote a decoder for the signal wich works perfect (at least, for me ;))
I'm from holland, so excuse me for my translation work :stuck_out_tongue:

void setup()
{
  attachInterrupt(0, DCF, CHANGE);
  Serial.begin(9600);
}

void loop()
{
}

void DCF()
{
  static volatile unsigned long timeLastRun;
  volatile unsigned long timeDifference;
  
  static volatile byte bitNr, check;
  static volatile byte minuteSecondary, minutePrimary, ourSecondary, ourPrimary;
  volatile boolean value;
  volatile byte temp, temp2;
  
  timeDifference = millis() - timeLastRun;
  timeLastRun = millis();
  
  if(timeDifference > 40){ //ivm af en toe een timeDifference van 0...
    //Signal Decoder:
    if (timeDifference < 160){
      value = false;
      check++;
    } else if (timeDifference < 270){    //a 0 has a duration of 100ms and a 1 200ms
      value = true;
      check++;
    } else if (timeDifference < 1200){
      bitNr++;
      check = 0;
    } else{             //marker end of minute
      bitNr = 0;
      check = 0;
    }
    
    //Start decoding signal:
    if(bitNr >= 21 && bitNr <= 35 && check == 1){ //bitnumbers in wich to operate to extract time
      
      //minute second digit:
      if(bitNr <= 24){
        minuteSecondary >>= 1;
        if(value) minuteSecondary |= 0x80;
      
      //minute first digit: 
      } else if(bitNr <= 27){
        minutePrimary >>= 1;
        if(value) minutePrimary |= 0x80;
      
      //Parity bit:  
      } else if(bitNr == 28){
        //Put the values gotten into the right place
        minuteSecondary >>= 4;
        minutePrimary >>= 5;
        temp = minuteSecondary ^ minutePrimary;
        temp2 = 0;
        
        //count the amount of 1's:
        for(int i=0; i<8; i++){
          if(bitRead(temp, i)) temp2++;
        }
        //and add the parity bit:
        if(value) temp2++;
             
        if(temp2 % 2 == 0){
          //the DCF77 signal was probably good, unless there were 2 or more failures
          Serial.print("Minutes: ");
          Serial.println(minutePrimary*10 + minuteSecondary);
        }
      
      //our second digit:  
      } else if(bitNr <= 32){
        ourSecondary >>= 1;
        if(value) ourSecondary |= 0x80;
      
      //our primary digit:  
      } else if(bitNr <= 34){
        ourPrimary >>= 1;
        if(value) ourPrimary |= 0x80;
      
      //Parity bit:  
      } else if(bitNr == 35){
        //Put the values gotten into the right place
        ourSecondary >>= 4;
        ourPrimary >>= 6;
        temp = ourPrimary ^ ourSecondary;
        temp2 = 0;
        
        //count the amount of 1's:
        for(int i=0; i<8; i++){
          if(bitRead(temp, i)) temp2++;
        }
        //and add the parity bit:
        if(value) temp2++;
 
        if(temp2 % 2 == 0){
          //the DCF77 signal was probably good, unless there were 2 or more failures
          Serial.print("Our: ");
          Serial.println(ourPrimary*10+ourSecondary);
        }
      }
    }
  }  
}

DCF77 spits out the LSB first, MSB last.
This code is also easially adaptable to get the current date

Hope I've helped some of you guys! If some want to have a library, I don't exactly know how to build one, though it should be not that hard :slight_smile:

Untitled.png

Thanks for sharing, does it work well ??
as I see an interrupt function that does take a lot of time to execute Serial prints in it and no serial.begin ... it raises so many questions.....

How do you connect the DCF module ? PIN2?
What does the output looks like?

If some want to have a library, I don't exactly know how to build one, though it should be not that hard

As the DCF uses quite some CPU time before it has fetched its time (> 40 seconds ), it might be interesting to use it to sync an RTC once per day.

This code works very well (at least, for me).

Must have lost the Serial.begin somewere... going to add it right away!

If you're going to use this function, you've got to get rid of the Serial prints because they take like 5ms to execute (wich is ofcourse far to long...)

It's pin 2 indeed. http://arduino.cc/en/Reference/AttachInterrupt

In this code, the output should look like this:

Minutes: XX
Our: XX

wich should be repeated every minute (XX depends on value). But, because the sender is (from here) 500KM away, there will sometimes be an error. Wich means it will return a false value or skip one of the serial prints. Therefor I recommend to make an array or something wich stores the values and checks if there're valid.

My code actually doesn't take that much CPU time, because it will run through it in less then a ms or something. It checks the difference between the last call for the function and the current call, based on that it looks for what it should do with that data. The code doesn't use while loops or anything, so your code in loop() will not be interrupted for that long.

I'm going to use the DCF77 indeed to sync a RTC (DS1307) once a day at 3:00AM or something like that, because the signal reception is best at night (no electronics powered etc wich could distort the signal)

Thanks for your feedback :slight_smile:

I hope you don't mind me hijacking this thread but i'm getting a bit stuck and you might be able to help.

I have very little arduino experience and want to make a clock that uses a MSF60 receiver instead of a DCF77 receiver. Is your code compatible or do I need to alter it to suit the different serial data?

Again sorry for hijacking the thread

Alex