dcf77_gps for nodemcu

This is a lua program intended to be run on an ESP8266 loaded with nodemcu. It will parse pulses from a pollin DCF77 receiver module. It's output on the serial port (usually available over USB) will be NMEA GPZDA sentences which can be understood by ntpd.

Why this program?

First of all i wanted to learn more about DCF77 and gain experience programming in lua. I also wanted to connect DCF77 to my (Raspberry Pi 2B based) ntp server without compromising the accuracy of it's already available PPS signal. When the receiver module looses it's signal it can easily generate hunderds or thousands of interrupts a second which will definately harm the PPS accuracy. By moving the processing to an ESP8266 the ESP will take the hit and just output valid data when it has a decent signal.

What does it do?

It receives data from a DCF77 module and outputs the same data as a GPS would do. To do that, it has some (IMHO) neat tricks. Usually it will run in an interrupt driven way, with a clean signal this will trigger twice a second (one for the rising edge, one for the falling edge). When it detects way more interrupts than expected, it switches to polling mode. It will use polling to detect a clean signal, and only when it's clean enough it will change back to interrupt mode again.

To improve accuracy and reduce the time from the rising edge of the radio signal to the delivery of the GPS sentence over the serial port it partially calculates the required checksum for the sentences every minute. Doing so only leaves the second characters to be added to the checksum.

When a clean signal is received it will blink a led to let you know it's working. Because LED's can be very bright when it gets dark you can set a minimum ambient light which will be read from the adc. When the ambient light is lower it will stop blinking.

How can i use this?

Of course you'll need an ESP8266. The ESP32 might actually be compatible, but i don't know and haven't tested. And of course you'll need a DCF77 receiver module. The pollin one i have is pretty cheap (around EUR 10, ignore the image on the site, it's the conrad module, but you'll get the pollin one when you order), the popular conrad module might also work but again: I haven't tested it.

The nodemcu firmware can be build using their build service. This program requires the adc, bit, gpio and timer modules. If you want to use nodemcu-uploader to upload the program, be aware that you will also need the file, node and uart modules.

To use the program upload it to your ESP8266 and if you want it to start automatically when the ESP is started also upload the init.lua file. Restart the ESP3288 and then wait :-)

If you look at the code you'll see quite some print statements commented out, those are there to help debugging. Unfortunately memory on the ESP8266 is too constrained to be able to uncomment them all at the same time, so use with caution.

What can do with this?

With this you can make ntpd think it's receiving from a GPS while it's actually using your DCF77 receiver. To do that, first you'll have to instruct udev to create a gps symlink. I use the following rules in /etc/udev/rules.d/99-gps.rules:

KERNEL=="ttyUSB0", SYMLINK+="gps0"

After that configure ntpd to use it with a server and fudge line in /etc/ntp.conf:

server 127.127.20.0 mode 0x58 minpoll 3 maxpoll 3 prefer
fudge 127.127.20.0 stratum 0 flag1 0 flag2 0 flag3 0 flag4 0 time1 0.0 time2 0.0292 refid DCF0

Especially time2 should be tuned to your own setup. The command ntpq -pn should now show something like this:

     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*127.127.20.0    .DCF0.           0 l    4    8  377    0.000   -0.214   0.567

Have fun!