feat(sat): point the antenna — EasyComm II az/el rotator

EasyComm is what satellite rotator controllers agreed on, so a box that
works with SatPC32, Gpredict or Hamlib works here. Serial or TCP, and its
own settings rather than the HF rotator's: an az/el pair is a different
machine on a different port, and an operator who has both must not have
to choose.

A great many EasyComm controllers — the Arduino trackers above all —
accept commands and never say a word back. That is legal and common, so a
silent controller is not treated as a broken one: it is still driven, and
the last commanded position is reported in its place, marked as commanded
rather than read. A stuck rotator must not be able to hide behind an
order it never carried out, which is why the panel shows the antenna's
position beside the satellite's.

The 450° overlap is the reason a satellite rotator is worth having, so it
is used: a pass crossing north continues past 360 instead of unwinding
three quarters of a turn with the antenna sweeping the ground. Below the
configured elevation the mast is left alone — the numbers are right all
the way round the orbit, but a rotator that chases a satellite through
the far side of the earth spends the night turning, and a mast has a
finite number of turns in it.
This commit is contained in:
2026-09-07 11:34:35 +02:00
parent 465481f8f1
commit 90e363f49e
11 changed files with 953 additions and 11 deletions
+32
View File
@@ -587,6 +587,22 @@ const en: Dict = {
'sat.trackingFull': 'Tracking both ends of the pass. Tune the receiver freely; the transmitter follows.',
'sat.trackingDown': 'Tracking the downlink only — this radio has one receiver.',
'sat.downlinkOnly': 'downlink only', 'sat.nominal': 'nominal',
'sat.antenna': 'Antenna', 'sat.rotCommanded': '(commanded — this controller does not report back)',
'sec.satellite': 'Satellites',
'satset.hint': 'Where the antenna is, and the machine that points it. The satellites you follow and the frequency plan are in the Satellites tab.',
'satset.grid': 'Locator', 'satset.gridPlaceholder': 'your stations',
'satset.gridHint': 'Leave the locator empty to use your stations own. Altitude is the antenna above sea level — it changes the horizon, and so the start and end of a low pass.',
'satset.altM': 'Altitude (m)', 'satset.minEl': 'Lowest pass (°)', 'satset.windowH': 'Predict ahead (hours)',
'satset.autoTle': 'Fetch fresh elements at startup when they are more than three days old',
'satset.rotor': 'Azimuth / elevation rotator',
'satset.rotEnable': 'Point a rotator at the satellite while tracking',
'satset.rotHint': 'EasyComm II — what SatPC32, Gpredict and Hamlib speak, so any controller that works with those works here. This is a separate machine from your HF rotator: having both is normal.',
'satset.rotLink': 'Connection', 'satset.rotSerial': 'Serial (COM)', 'satset.rotTcp': 'Network (TCP)',
'satset.rotHost': 'Address', 'satset.rotPort': 'Port', 'satset.rotCom': 'COM port', 'satset.rotBaud': 'Baud',
'satset.rotRange': 'Rotator range', 'satset.rotMinEl': 'Start above (°)', 'satset.rotStep': 'Move by (°)',
'satset.rotRangeHint': 'A 450° rotator follows a pass straight through north instead of unwinding, so it is used that way when it can be. “Start above” leaves the mast alone until the satellite is worth pointing at; “move by” is the smallest change worth a command — keep it inside your beamwidth.',
'satset.rotPark': 'Park at north, elevation zero, when tracking stops',
'satset.rotTest': 'Test the rotator', 'satset.rotTesting': 'asking the controller…',
};
const fr: Dict = {
@@ -1137,6 +1153,22 @@ const fr: Dict = {
'sat.trackingFull': 'Les deux bouts du passage sont suivis. Accordez le récepteur librement, l’émetteur suit.',
'sat.trackingDown': 'Seule la descente est suivie — cette radio na quun récepteur.',
'sat.downlinkOnly': 'descente seule', 'sat.nominal': 'nominal',
'sat.antenna': 'Antenne', 'sat.rotCommanded': '(commandé — ce contrôleur ne répond pas)',
'sec.satellite': 'Satellites',
'satset.hint': 'Où se trouve lantenne, et la machine qui la pointe. Les satellites suivis et le plan de fréquences sont dans longlet Satellites.',
'satset.grid': 'Locator', 'satset.gridPlaceholder': 'celui de la station',
'satset.gridHint': 'Laissez le locator vide pour utiliser celui de votre station. Laltitude est celle de lantenne au-dessus du niveau de la mer — elle change lhorizon, donc le début et la fin dun passage rasant.',
'satset.altM': 'Altitude (m)', 'satset.minEl': 'Passage minimal (°)', 'satset.windowH': 'Prévoir sur (heures)',
'satset.autoTle': 'Récupérer des éléments frais au démarrage quand ils ont plus de trois jours',
'satset.rotor': 'Rotor azimut / élévation',
'satset.rotEnable': 'Pointer un rotor vers le satellite pendant le suivi',
'satset.rotHint': 'EasyComm II — le langage de SatPC32, Gpredict et Hamlib : tout contrôleur qui fonctionne avec eux fonctionne ici. Cest une machine distincte de votre rotor HF : avoir les deux est normal.',
'satset.rotLink': 'Connexion', 'satset.rotSerial': 'Série (COM)', 'satset.rotTcp': 'Réseau (TCP)',
'satset.rotHost': 'Adresse', 'satset.rotPort': 'Port', 'satset.rotCom': 'Port COM', 'satset.rotBaud': 'Bauds',
'satset.rotRange': 'Course du rotor', 'satset.rotMinEl': 'Démarrer au-dessus de (°)', 'satset.rotStep': 'Déplacer par (°)',
'satset.rotRangeHint': 'Un rotor 450° suit un passage à travers le nord sans se dérouler ; il est donc utilisé ainsi quand il le peut. « Démarrer au-dessus de » laisse le pylône tranquille tant que le satellite ne mérite pas d’être pointé ; « déplacer par » est le plus petit écart qui vaut une commande — gardez-le à lintérieur de votre ouverture de faisceau.',
'satset.rotPark': 'Ranger au nord, élévation zéro, à larrêt du suivi',
'satset.rotTest': 'Tester le rotor', 'satset.rotTesting': 'interrogation du contrôleur…',
};
const dicts: Record<Lang, Dict> = { en, fr };