• Stars
    star
    404
  • Rank 104,799 (Top 3 %)
  • Language
    C++
  • License
    GNU General Publi...
  • Created almost 6 years ago
  • Updated 11 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A DCF77, WWVB, JJY and MSF clock LF-band signal transmitter using the Raspberry Pi

Radio time station transmitter using the Raspberry Pi and Nvidia Jetson

I am living in a country where there is no DCF77 sender nearby for my European radio controlled wristwatch to get its time. This vintage Junghans Mega doesn't have any buttons to set the time, so to bring it back to life, I built my own 'transmitter', taking the NTP time of a Raspberry Pi and generating a modulated signal via GPIO pins to then magnetically couple it into the watch ferrite.

Since many other long-wave time stations around the world use similar concepts of sending amplitude modulated time, other time services have been added.

This program is useful if you have a clock that otherwise does not get any reception. This magnetical coupling is very low power and only works over a few centimeters, but before running this program, make sure you follow your local laws with regard to restrictions on radio transmissions.

Platform

txtempus supports Raspberry Pi series and Nvidia Jetson Series (experimental).

Raspberry Pi

So far, it has been tested on a Pi3 and a Pi Zero W. There has been a report of different frequencies generated with an older Pi (Bug #1), so until we have a definitive list of available clock sources inside these, check out that bug for a workaround.

Nvidia Jetson Series (experimental)

So far, it has been tested only on a Jetson Nano, but all Jetson devices except for TX1 and TX2 (there is no available pwm pin) are supported.

Supported Time Services

DCF77

The DCF77 (Germany) signal is a 77.5kHz carrier, that is amplitude modulated with attenuations every second of the minute except the 59th to synchronize. The length of the attenuation (100ms and 200ms) denotes bit values 0 and 1 respectively so in each minute, 59 bits can be transferred, containing date and time information.

The Raspberry Pi has ways to create frequencies by integer division and fractional jitter around that, which allows us to generate a frequency of 77500.003Hz, which is close enough. Can be chosen with -s DCF77 option.

WWVB

The WWVB (USA) is on a 60kHz carrier, and also transmits one bit per second with different attenuation times (200ms zero, 500ms one; 800ms sync) and multiple synchronization bits. Use -s WWVB option for this one.

MSF

The MSF (United Kingdom) has yet another encoding, transferring two bits per second. Carrier is 60kHz. Option is -s MSF.

JJY

The JJY (Japan) is similar to WWVB, with same timings of carrier switches, but reversed power levels. Some bits are different. Two senders exist in Japan with 40kHz and 60kHz carrier; their simulations can be chosen with command line options -s JJY40 and -s JJY60. If you're in/or want to display a different time-zone, issue #17 might be of interest to you.

Minimal External Hardware

Raspberry Pi

The external hardware is simple: we use the frequency output on one pin and another pin to pull the signal to a lower level for the regular attenuation.

To operate, you need three resistors: 2x4.7kΩ and one 560Ω (precision not critical), wired to GPIO4 and GPIO17 like so:

Schematic Real world

GPIO4 and 17 are on the inner row of the Header pin, three pins inwards on the Raspberry Pi GPIO-Header.

You don't need GPIO17 and the 560Ω resistor for MSF, as that works with switching the signal (on-off keying) instead of attenuating. In that case, you can replace the sequence of two 4.7kΩ resistors with a single 10kΩ.

Now, wire a loop of wire between the open end of the one 4.7kΩ and ground - this loop acts as coupling coil to the watch ferrite antenna. The signal is very weak, so bring this wire-loop close to your radio watch/clock.

In the following image, which was the first experiment, it is wrapped around the antenna, but it is not strictly needed: anything within a few centimeters should work.

Being too close to the clock can confuse a sensitive receiver, so you might need to experiment with the distance. If your clock/watch is not receiving, add more turns to your transmission coil. In the picture at the bottom of the page you see that I am using about 10-20 turns on the coil (reddish oval lying on the Pi).

This set-up should work for most watches if you have them in close vicinity.

The antenna set-up is intentionally not optimal to just be good enough for a local watch but hopefully not causing interference. Further improvements of course can be done to the antenna for increased transmission distance, such as using a ferrite, making it an LC circuit or adding an amplifier. Only go in this direction after familiarizing yourself with allowances of radio transmissions in your area on your frequency of interest.

Nvidia Jetson Series (experimental)

(*Please read the external hardware for the Raspberry Pi above first.) On Jetson, the external hardware setup is slightly different from the Raspberry Pi.

We need one "PWM Pin" for a frequency output, and one "Attenuation Pin" for modulating the signal. These pins vary by the Jetson model. Please check the following table.

Devices PWM pin (Board numbering) Attenuation pin (Board numbering)
Jetson TX1, Jetson TX2 Not supported Not supported
Jetson Xavier, Clara AGX Xavier, Jetson Orin 18 16
Other devices 33 35

To operate, you need three resistors: 2x4.7kΩ and one 560Ω (precision not critical) and one NPN transistor (nearly any NPN transistor should work. I'm using KTC3198).

Here's the full schematic of the external hardware for the Jetson Series:

Schematic Real world (Jetson Nano)

Like the Raspberry Pi, you don't need the Attenuation Pin and the 560Ω resistor for MSF, and a wire-loop between the 4.7kΩ register and the ground acts as coupling coil. Bring this wire-loop close to your radio watch/clock.

Build

 sudo apt-get install git build-essential cmake -y
 git clone https://github.com/hzeller/txtempus.git
 cd txtempus
 mkdir build && cd build

Rapberry Pi

 cmake ../ # or cmake ../ -DPLATFORM=rpi
 make

Nvidia Jetson Series (experimental)

Before you build txtempus on your Jetson:

  • You should install JetsonGPIO which is a library that enables the use of Jetson's GPIOs.
  • The system pinmux must be configured to connect the hardware PWM controlller(s) to the relevant pins. Read the L4T documentation for details on how to configure the pinmux.
 cmake ../ -DPLATFORM=jetson
 make

Transmit!

 sudo ./txtempus -v -s DCF77

With -s, you set the type of time signal you want to transmit.

There are a few options you can set. The -r option is useful to have the program run only for the few minutes it might take for a clock to synchronize.

By default, the current system time is transmitted. The -t option allows different times for testing.

usage: ./txtempus [options]
Options:
        -s <service>          : Service; one of 'DCF77', 'WWVB', 'JJY40', 'JJY60', 'MSF'
        -r <minutes>          : Run for limited number of minutes. (default: no limit)
        -t 'YYYY-MM-DD HH:MM' : Transmit the given local time (default: now)
        -z <minutes>          : Transmit the time offset from local (default: 0 minutes)
        -v                    : Verbose.
        -n                    : Dryrun, only showing modulation envelope.
        -h                    : This help.

Don't connect monitor (Raspberry Pi)

Don't connect a monitor to the Pi, just operate it headless.

The internal oscillator used is also used for HDMI in the Rasbperry Pi; it will be changing its frequency if a monitor is connected and the transmission will fail. There should probably be a flag added to generate the frequency from an alternative oscillator instead; but until that is implemented, just don't connect a monitor and it will work. See the very wrong frequency bug for details.

Action video - watch a watch synchronize

In the video below, you can see how a watch is set with this set-up. After it is manually reset, it waits until it sees the end-of-minute mark (which does not have any amplitude modulation) and then starts to count on from second 59, then gathering the data that is following.

An interesting observation: you see that the watch already gets into fully set mode after about 50 seconds, even though there is the year data after that. This particular watch never shows the year, so it just ignores that.

Showing the modulation envelope

Mostly for understanding the protocol, the -n option allows to observe how the amplitude modulation of each second looks like. Unlike the regular transmission, don't need to be root or run on the Raspberry Pi to use this option. Underscores (_) show low power carrier, hashes (#) high power:

$ ./txtempus -n -s wwvb
2018-08-17 13:22:00 -> tx-modulation
:00 [________##]
:01 [__########]
:02 [_____#####]
:03 [__########]
:04 [__########]
:05 [__########]
:06 [__########]
:07 [_____#####]
:08 [__########]
:09 [________##]
:10 [__########]
:11 [__########]
  ... and so on for the whole minute ...

Limitations

In some of these protocols, there are additional bits that contain information about upcoming daylight saving times, leap seconds or difference to astronomic time. These are currently not set, but usually clocks are fine with it.

Some time stations also phase-modulate their carrier, txtempus does not.

The frequency generation does not seem to work on a Raspberry Pi4. Please use older Pis for now until that is figured out (also pull requests accepted if you know details).

Installation

Software

After building, you can install the binary in some standard location

 sudo make install

Watch holder

Each set-up will be different. In my case, I need my DCF77 radio watch getting set over night. So I built this watch holder that presents the watch upright while the antenna (in the wristband) is close to the 'transmission coil' that is lying flat on the Pi. The bottom of the 3D printed case is filled with lead shot in epoxy to provide a stable base.

The Raspberry Pi Zero W runs ntpd, PLL locking the system time to various stratum 1 NTP servers keeping it at atomic time within ±50ms. This particular watch only checks the radio twice a day at 2am and 3am, so there is a cron-job that runs txtempus around these times for a few minutes.

Crontab

If you put the following line in your /etc/crontab txtempus will be started at 1:57 and 2:57 at night and runs for 10 minutes.

57 1,2    * * *   root    /usr/bin/txtempus -s DCF77 -r 10

(this requires that you have installed txtempus so that it can be found in /usr/bin : sudo make install).

watch holder ... with watch

tx common telecommunication abbreviation for 'transmit'
tempus, n Latin. Time; period; age

More Repositories

1

rpi-rgb-led-matrix

Controlling up to three chains of 64x64, 32x32, 16x32 or similar RGB LED displays using Raspberry Pi GPIO
C++
3,229
star
2

timg

A terminal image and video viewer.
C++
1,801
star
3

gmrender-resurrect

Resource efficient UPnP/DLNA renderer, optimal for Raspberry Pi, CuBox or a general MediaServer. Fork of GMediaRenderer to add some features to make it usable.
C
832
star
4

ldgraphy

Simple Laser Direct Lithography / Laser Direct Imaging for PCB manufacturing
PostScript
269
star
5

rpi-gpio-dma-demo

Performance writing to GPIO with CPU and DMA on the Raspberry Pi
C
196
star
6

flaschen-taschen

Noisebridge Flaschen Taschen display
C++
193
star
7

rpi-matrix-pixelpusher

PixelPusher protocol for LED matrix.
C++
160
star
8

beagleg

G-code interpreter and stepmotor controller for crazy fast coordinated moves of up to 8 steppers. Uses the Programmable Realtime Unit (PRU) of the Beaglebone.
C++
114
star
9

augenmass

Measure relative sizes on background image.
JavaScript
93
star
10

upnp-display

Display state of UPnP/DNLA renderer in the network with a 16x2 LCD display (or 24x2, 40x2 ..) connected to the Raspberry Pi. Unicode support (UTF-8).
C++
69
star
11

spixels

Spixels - 16-SPI LED Raspberry Pi adapter with library (SPI - Pixels).
C++
39
star
12

gcode-cli

Simple command line tool to send gcode to serial 3D printer/CNC machine.
C++
37
star
13

rpt2pnp

Solder paste dispensing and Pick'n Placing
C++
34
star
14

stuff-org

Organize electronic components. Or other stuff.
Go
33
star
15

postscript-hacks

A collection of some useful PostScript programs.
PostScript
31
star
16

folve

Folve - seamlessly FIR convolving audio file fuse filesystem with gapless support.
C++
30
star
17

trs80-100-schematic

A transcript of the TRS80 Model 100 schematic
Nix
26
star
18

rpt2paste

Convert KiCAD rpt files to G-Code to dispense solder paste
C++
24
star
19

bumps

BeagleBone Universal Multi Pololu Steppers
KiCad Layout
21
star
20

blisplay

A tactile display for the blind.
OpenSCAD
19
star
21

otp-image

Optical One-Time Pad XOR encoding of images
C++
17
star
22

pixelpusher-server

A simple library that allows to receive pixels via the PixelPusher protocol.
C++
16
star
23

digi-spherometer

A digital spherometer, reading data from digital dial indicator and converting it to radius, displaying on OLED display.
C++
14
star
24

RedPitaya-Case

A case for the Red Pitaya scope/function generator
OpenSCAD
12
star
25

joystick-gcode-jog

Jogging a machine such as a 3D printer or CNC machine with a gampad. Mostly proof of concept.
C
12
star
26

openscad-things

Things made with OpenSCAD. Mostly experimental right now.
OpenSCAD
9
star
27

quadrigotion

TMC2660 Four stepper motor drivers on a stick.
Python
9
star
28

tmc2660-breakout

Little breakout board to play with the TMC2660 stepper driver
Python
9
star
29

gds2vec

A simple program to convert gdsII files to vector output formats. Currently used to create laser-cut models of standard cells.
C++
9
star
30

precise-pitch

Instrument tuner app. Mostly my playground to learn Android development.
Java
8
star
31

symbiflow-simple-sample

Using Symbiflow arch defs to get BASYS3 board entertained with logic
Makefile
8
star
32

spixels-pixelpusher

A PixelPusher implementation using the Spixels hardware to control LED strips.
C++
6
star
33

bdfont.data

Generate C-structs from BDF fonts to be compiled into embedded programs.
C++
5
star
34

bare-lsp

A language server protocol implementation
C++
5
star
35

sound-cam

Simulation of using Microphones to pick up sound locations.
C++
5
star
36

jcxxgen

A schema compiler generating c++ structs with boilerplate to be serialized easily with nlohmann/json
C++
5
star
37

pi-registerplex

GPIO multiplexer for Raspberry Pi
Python
3
star
38

makerspace-tag

Simple app keeping track of makerspace users and their capabilities
Go
3
star
39

ziplain

A plain, no-frills ZIP file writer.
C++
3
star
40

DerKnopf

Simple IR remote control of a volume knob
KiCad Layout
3
star
41

hot-snipper

A Hot-Knife cutting machine
OpenSCAD
3
star
42

simple-fasm

A simple parser for the FPGA Assembly format
C++
3
star
43

eda-tools

Small useful tools I use while doing stuff with electronics.
3
star
44

pitch-hero

C++
2
star
45

air-filter-box

Quad AirFilter using standard box-fan and standard aircon/furnace filters
OpenSCAD
2
star
46

microorb

A USB controlled 2.5W RGB LED
C++
2
star
47

FlaschenTaschen-PixelPusher-bridge

Receives FlaschenTaschen protocol and sends to a PixelPusher installation.
C++
2
star
48

bant

Bazel/Build Analysis and Navigation Tool
C++
2
star
49

gaggia-pid

PID controller, useful for e.g. coffee machines.
C++
1
star
50

cogsworth-viz

Visualization of data generated from Project-COGSWORTH
C
1
star
51

simple-spherometer

A simple analog spherometer made from simple hardware-store materials, laser cut acrylic and 3D printed parts.
PostScript
1
star
52

golang-pgp-test

Experiments with the golang OpenPGP implementation.
Go
1
star
53

sneeze-guard

Sneeze-guard on working tables for reduced Viral spread.
G-code
1
star
54

flaschen-taschen-avr

Quick hack to make first FlaschenTaschen crates work.
C++
1
star
55

bidi-tee

A bidrectional `tee` program that passes through stdin/stdout/stderr and copies them colored coded to a file
C++
1
star
56

ear-saver

A laser-cuttable ear-saver for face masks.
OpenSCAD
1
star
57

gstreamer-gapless-test

Sample source code to demonstrate a gstreamer issue.
C
1
star
58

din-rail-clip-mount

3D printed Din-Rail mount for PCB and other components
OpenSCAD
1
star
59

threadless-server

select() event API experiment with c++11 closures.
C++
1
star
60

glowxels

Glow-in-the-dark canvas
C++
1
star