1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
<h1>dcf77_gps for nodemcu</h1>
<p>
This is a lua program intended to be run on an ESP8266 loaded with
<a href="https://www.nodemcu.com/">nodemcu</a>. It will parse pulses from a
<a href="https://www.pollin.de/p/dcf-77-empfangsmodul-dcf1-810054">pollin</a>
<a href="https://en.wikipedia.org/wiki/DCF77">DCF77</a> receiver module. It's
output on the serial port (usually available over USB) will be
<a href="https://en.wikipedia.org/wiki/NMEA_0183">NMEA GPZDA</a> sentences
which can be understood by <a href="https://ntp.org">ntpd</a>.
</p>
<h2>Why this program?</h2>
<p>
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.
</p>
<h2>What does it do?</h2>
<p>
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.
</p>
<p>
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.
</p>
<p>
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.
</p>
<h2>How can i use this?</h2>
<p>
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
<a href="https://www.vandijkenelektronica.nl/product/dcf77-moduul-met-ferrietantenne-voor-de-dcf-77-uitlezing/">EUR 10</a>,
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.
</p>
<p>
The nodemcu firmware can be build using
<a href="https://nodemcu-build.com/">their build service</a>. This program
requires the <b>adc</b>, <b>bit</b>, <b>gpio</b> and <b>timer</b> modules. If
you want to use
<a href="https://github.com/kmpm/nodemcu-uploader">nodemcu-uploader</a> to
upload the program, be aware that you will also need the <b>file</b>,
<b>node</b> and <b>uart</b> modules.
</p>
<p>
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 :-)
</p>
<p>
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.
</p>
<h2>What can do with this?</h2>
<p>
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:
</p>
<pre>
KERNEL=="ttyUSB0", SYMLINK+="gps0"
</pre>
<p>
After that configure ntpd to use it with a server and fudge line in
/etc/ntp.conf:
</p>
<pre>
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
</pre>
<p>
Especially time2 should be tuned to your own setup. The command <b>ntpq
-pn</b> should now show something like this:
</p>
<pre>
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
</pre>
<p>
Have fun!
</p>
|