dcf77
DCF77 Signal Decoding
MRL Alphanumeric
i2c AlphaNumeric display

European Time/Date/Year/DayLightSaving/Leap Year/Second-Syncing alternative, by the reception of a 77.5khz signal from a German Transmitter station referred to as DCF77 (which is located at Mainflingen DE). It sends a 50kW signal  (range 2000km) with 59bits of data , a DCF77 controlled external clock should be able to synchronize to within one half of the period of the transmitted 77.5 kHz carrier frequency (lookout internet latencies !!!).

These modules can operate at very low voltages (1.5V) and consume very little power (<100uA).

(N.B. GPS Time modules systems are only good for outdoors, whilst the DCF77's low frequency permeates deep into the "Zombie-Bunker").

dcf77
DCF77 Decoder.
dcf77 coil
3D "Dog-Dick" antenna mount, to protect Ferrit core and thin coil windings.

The Modules are easy to come by, This one is for Europe - there are others available in different countries so be aware whilst ordering as there are other frequency bands used.

The RX signal example is show below :-

osc

The decoding software just needs to detect  100ms / 200ms and 2000ms sync pulses.

......(well the logic 1 and 0 pulses .........and the sync "anti-Pulse", its easier to detect the inverse sync-pulse width.).

dcf
Bit-Pattern inc parity control

For display purposes in this case an AlphaNumeric Display is used, as it is then possible to display extra text data.

Its using the Adafruit Library, however the library simply overlooks the decimal point, to which its an easy task to double the Library LED bitmap file (numeric) adding extra decimal point to each number and copy paste them to the end of the character bitmap.

This then allows Number with decimal point or not.....

 alpha0x70.writeDigitAscii(1, Tuffer[1]);         Number only

 alpha0x70.writeDigitAscii(1, Tuffer[1]+80);  Number with Decimal point.

This becomes useful as it flashes in sync with the RX signal so you can monitor the incoming bit stream (and signal quality/noise).

alpha
Good time_ing.... Decimal point courtesy of Library Hack.

-------------------------------------------------------------------------------------

ESP32 (S2) Get you going code (no parity checking)  :-

-------------------------------------------------------------------------------------

#include <Adafruit_GFX.h>
#include "Adafruit_LEDBackpack.h"
Adafruit_AlphaNum4 alpha0x70 = Adafruit_AlphaNum4();
#include <SPI.h>
#include <Wire.h>
String Puffer = "GeneralPuffer.........................................................................";
String Tuffer = "formatPuffer..........................................................................";
static char dtoPuffer[256];
int dcf77New; int dcf77Old;
int startTime;int stopTime;
int lowPulse;int highPulse;
int count=0;
int dcf77[60];
int Mins=0;int Hours=0;int Dom=0;int Dow=0;int Moy=0;int Cent=0;bool Up = false;
void setup(void) {
 alpha0x70.begin(0x70); delay(50);
 uint16_t time = millis(); time = millis() - time;
 alpha0x70.writeDigitAscii(0, 'A');  alpha0x70.writeDisplay();delay(50);// wakeup display
 pinMode(15, OUTPUT); // Debug LED RX signal
 }
void loop() {  
    timeBaseInc(); delay(20);
}
void timeBaseInc(){
  dcf77New=digitalRead(40);
  if (dcf77New==HIGH) {digitalWrite(15,HIGH);} else {digitalWrite(15,LOW);} // blink LED as debug , detects incoming RX
  if ( dcf77New > dcf77Old) {startTime=millis();  lowPulse=startTime-stopTime;
  if ( lowPulse>1500) {out0x70();count=0;}}   //dcf77 detects sync
  if ( dcf77New < dcf77Old) {stopTime=millis() ; highPulse=stopTime-startTime;
  if ((highPulse>10 )&&(highPulse<150)) { dcf77[count]=0;count++;} //dcf77 detects 100ms signal Logic 0
  if ((highPulse>150)&&(highPulse<250)) { dcf77[count]=1;count++;} //dcf77 detects 200ms signal Logic 1
  }   
dcf77Old=dcf77New;
}
void out0x70(){
  if (count==59){    //This is basic error detect if not 59 then data is missing
  prepareDisplay();
 alpha0x70.writeDigitAscii(0, Tuffer[0]);
 alpha0x70.writeDigitAscii(1, Tuffer[1]+80); // show number with decimal point
 alpha0x70.writeDigitAscii(2, Tuffer[2]);
 alpha0x70.writeDigitAscii(3, Tuffer[3]);
 alpha0x70.writeDisplay();
  }
}

void prepareDisplay(){
      Mins= (dcf77[21]*1)+(dcf77[22]*2)+(dcf77[23]*4)+(dcf77[24]*8)+(dcf77[25]*10)+(dcf77[26]*20)+(dcf77[27]*40);
      Hours=(dcf77[29]*1)+(dcf77[30]*2)+(dcf77[31]*4)+(dcf77[32]*8)+(dcf77[33]*10)+(dcf77[34]*20);
      Dom  =(dcf77[36]*1)+(dcf77[37]*2)+(dcf77[38]*4)+(dcf77[39]*8)+(dcf77[40]*10)+(dcf77[41]*20);
      Dow  =(dcf77[42]*1)+(dcf77[43]*2)+(dcf77[44]*4);
      Moy  =(dcf77[45]*1)+(dcf77[46]*2)+(dcf77[47]*4)+(dcf77[48]*8)+(dcf77[49]*10);
      Cent =(dcf77[50]*1)+(dcf77[51]*2)+(dcf77[52]*4)+(dcf77[53]*8)+(dcf77[54]*10)+(dcf77[55]*20)+(dcf77[56]*40)+(dcf77[56]*80);
Puffer=String((100*Hours)+Mins); dtostrf(atof(Puffer.c_str()),4,0, dtoPuffer); Tuffer = dtoPuffer;

}