NOTE · 09/26

Daylight plan: teaching the mount to keep tracking between panels

The one job left from 19 September. Written down before I start because it involves unbounded motion, and the whole point is to do it somewhere I can watch it rather than at 21:00 on the one clear night.

What I am adding

After each goto, three commands per axis: :G<ax>1<dir> to put the axis in slew mode, :I<ax><period> to set the rate, :J<ax> to go. Today every goto begins with :K, which also stops firmware tracking, and nothing ever turns it back on — which is the whole of [[seventeen-milliseconds-per-pixel]].

The unknown is the period encoding. :I takes a timer-tick period, not a rate. The shape of it should be period = T / steps_per_second, where T is the controller's timer frequency and steps_per_second = deg_per_sec × 2073600 / 360. I am treating that as a hypothesis. The obvious trap is the high-speed multiplier — usually 16× — which would put the first attempt out by a factor of sixteen.

Phase 0 — safety rig (30 min)

Phase 1 — read the constants (15 min)

All read-only, all safe: :e1 firmware, :a1 steps per revolution (expect 2,073,600), :b1 timer frequency, :g1 high-speed ratio. Record what actually comes back. Cross-check against libindi's skywatcherAPI if the source is to hand, but believe the mount over the source.

Phase 2 — calibrate empirically (30 min)

The important one. [[measure-dont-derive]], applied properly this time.

Command a deliberately slow rate — sidereal, 15″/s, 0.0042 deg/s. Let it run 60 seconds. Read :j before and after and compute the actual degrees per second.

At that rate the axis moves a quarter of a degree in a minute. Completely safe indoors, and if the formula is out by 16× I will see it immediately with the mount having gone nowhere. Repeat at 2× and 4× to confirm it is linear.

Output: a verified rate → period function. Everything downstream depends on it, and there is no point writing the feature before this number exists.

Phase 3 — implement (1 hr)

start_tracking(axis, deg_per_sec) — direction from the sign, period from the calibration, then :G :I :J, then read :f back and confirm the tracking-mode bit is actually set rather than assuming the command landed.

Rates come from astropy per panel: d(alt)/dt and d(az)/dt at that moment. The azimuth axis rate is d(az)/dt directly — the cos(alt) factor converts sky distance to axis distance and does not belong in a rate.

Add the bound that a rate command does not carry: refuse anything above about 3× lunar. Cheap, and it is the guard MAX_STEP cannot provide here — see [[bounded-motion-is-the-safety-property]].

Phase 4 — the watchdog (30 min)

A rate command runs until something stops it, so the program has to be that something.

Phase 5 — bench test (30 min)

Run the mosaic with no camera and tiny offsets, indoors. Three things to see: the :f tracking bit set after every goto, the axis counts advancing at the commanded rate between gotos, and the run ending with both axes stopped.

Phase 6 — sky test (first clear night)

2×2 at 30 frames before anything larger. The number that proves it worked is within-panel centroid drift measured from the frames themselves, first frame to last. It is about 117 px today and should go to near nothing. If it does not, the rate is wrong and I will know before committing a full grid to it.


Realistically 3–4 hours to the end of Phase 5. Phase 6 is a separate evening.

Two cheap wins the same day, no mount required