Skip to content

Navigation Menu

Sign in
Sign up

Repository files navigation

VK5DJ Tracker

A Linux-native replacement for the PSTRotator + VK5DJ combo, for Sun/Moon (and manual az/el) dish tracking. Talks to the VK5DJ Beam/EME Rotator Controller over its native serial protocol -- no Windows, no Wine, no VM.

Built from John Drew VK5DJ's own published interface document ("How to interface to the VK5DJ Rotator Controller", 2009年11月02日) and his reference Delphi sample, not from reverse-engineering any third-party program.

What it does

  • Computes Sun and Moon azimuth/elevation for your site using Skyfield and the JPL DE421 ephemeris.
  • Feeds that to the VK5DJ controller over serial (9600 8N1) in its native "Basic Interfacing" format -- the controller does its own tracking arithmetic, same as it does today with PSTRotator.
  • Reads back the controller's actual antenna position.
  • Serves a local dashboard (default http://<host>:8420) with:
    • a live polar sky-view (antenna vs. target, plus the Sun/Moon's path for the next 12h),
    • Sun/Moon rise & set times for the next 24h,
    • mode switching (Sun / Moon / Manual az-el / Off),
    • a world map shaded with the region currently having the Moon above the horizon.

When the current Sun/Moon target sets below limits.el_min, tracking doesn't keep slewing azimuth to chase the body's real (invisible, below- horizon) position -- it holds the beam at the upcoming rise azimuth, parked at el_min, so physical movement actually stops while the antenna stays ready for the moment the body rises again. The dashboard's target marker still shows the true (below-horizon) position while this is happening; only what's actually sent to the controller changes.

Remote/direct beam-steering mode (VK5DJ's "Remote Mode") is deliberately not implemented -- the interface doc itself recommends against it "unless there is a special reason", and Basic Interfacing (send target az/el, let the controller move the beam) is simpler and is what PSTRotator uses too.

Setup

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Copy the template and edit it -- config.yaml is gitignored since it holds your exact site coordinates and hardware-specific serial device path:

cp config.example.yaml config.yaml
location:
 lat: -34.9 # your latitude, decimal degrees
 lon: 138.6 # your longitude, decimal degrees
 elevation_m: 50
serial:
 port: /dev/ttyUSB0 # wherever the VK5DJ controller shows up

Find your serial device with ls /dev/serial/by-id/ (preferred -- stable across reboots) or dmesg | tail after plugging it in.

First run downloads the ~17 MB DE421 ephemeris file (needs internet once):

python run.py

Then open http://<host>:8420 in a browser.

Running as a service

A systemd unit is in systemd/vk5dj-tracker.service. Adjust the paths/user, then:

sudo cp -r . /opt/vk5dj-tracker
sudo useradd -r -G dialout vk5dj # dialout group -> serial port access
sudo cp systemd/vk5dj-tracker.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now vk5dj-tracker

Project layout

vk5dj_tracker/
 protocol.py serial protocol driver (the VK5DJ wire format)
 astro.py Sun/Moon az/el, rise/set, sub-lunar point (Skyfield)
 worldmap.py moon-visibility-by-country geometry
 tracker.py background thread linking controller <-> astronomy, shared state
 web.py FastAPI app (REST API + static dashboard)
 static/ dashboard (vanilla HTML/CSS/JS, no build step, no CDN deps)
 horizon_profile.json your site's surveyed horizon overlay (gitignored, optional)
tools/
 horizon_csv_to_profile.py converts a horizon-survey.csv into horizon_profile.json
run.py entry point
config.yaml your site + serial port + web port

Notes / limitations

  • The moon-visibility world map shades the actual geometric visibility region (per-pixel, against the sub-lunar point), ignoring atmospheric refraction and the Moon's parallax (both on the order of a degree) -- it's for orientation, not a link-budget tool.
  • Country outlines (vk5dj_tracker/static/world.geo.json) are derived from Natural Earth (public domain) via github.com/johan/world.geo.json.
  • The controller's clock is synced once per connection using the optional time-calibration packet from the interface spec; time_synced on the dashboard reflects whether the controller echoed it back correctly.
  • Set limits.el_min to your real local horizon, not just 0 -- it's not only a safety floor, it's also the elevation the "waiting for rise" parking behavior above uses and the below-horizon cutoff for deciding a target has set. If terrain/trees/buildings block your actual sky below a few degrees, set this to match (e.g. 4 degrees).

Horizon obstruction overlay

Beyond the flat limits.el_min floor, the sky-plot can also show your site's actual surveyed horizon (buildings, trees, terrain) at each azimuth, as an amber shaded region -- purely a visual reference on the dashboard, not something the tracker's own driving logic reads or is constrained by. Useful because a single flat elevation limit either wastes visible sky in open directions or risks pointing at obstructions in blocked ones, and because obstruction from foliage genuinely changes with the seasons (a summer survey with full leaf cover isn't the same as what's actually blocked in winter).

1. Survey the horizon with on6zg/horizon-survey -- a phone-based tool (camera + compass/tilt) for walking your site and recording the obstruction elevation at each direction. Export a CSV when done.

2. Convert the CSV to this app's overlay format:

python3 tools/horizon_csv_to_profile.py path/to/horizon_survey_*.csv

This writes vk5dj_tracker/static/horizon_profile.json. No other setup needed -- it's served as a plain static file and picked up on the next dashboard page load, no app restart required. Deploying it to a running instance is just copying that one file into place (e.g. pct push <ctid> vk5dj_tracker/static/horizon_profile.json /opt/vk5dj-tracker/vk5dj_tracker/static/horizon_profile.json if you're running under an LXC container the way this station does).

If you don't have a horizon_profile.json, the overlay and its legend entry simply don't appear -- this is entirely optional. vk5dj_tracker/static/horizon_profile.json is gitignored (same as config.yaml -- it's your own site's exact obstruction survey); vk5dj_tracker/static/horizon_profile.example.json shows the format.

Reading the overlay: segments connecting two closely-spaced survey points (within 15 degrees of azimuth) are drawn as a solid line; wider gaps (nowhere nearby actually measured) are drawn dashed and fainter, so a stretch of "no real data, straight-line guess between two distant points" reads differently from an actually-measured obstruction edge.

Reading az/el limits off the VK5DJ controller's own menu

If you want limits.az_min/az_max in config.yaml to match the controller's own configured mechanical stops (menu items 16/17, "AZ High Stop"/"AZ Low Stop"), don't use the menu numbers directly -- per the VK5DJ manual, azimuth stops are stored as half their degree value (1 unit = 2 degrees; enter 90 to mean 180 degrees). So:

actual_degrees = menu_value * 2

Elevation stops (menu items 18/19) store true (unhalved) degree values, no conversion needed. Hysteresis (menu items 14/15) is in 0.1-degree units (a value of 3 = 0.3 degrees), which is the controller's own "close enough, stop the motor" tolerance -- independent of, and generally larger than, this app's deadband_deg.

About

Linux-native Sun/Moon dish tracker for the VK5DJ Beam/EME Rotator Controller (PSTRotator replacement), horizon-aware tracking

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

AltStyle によって変換されたページ (->オリジナル) /