Skip to content

fix(guiding): guide pulses dropped during active pulses + display render delaying pulse end - #313

Merged
ClutchplateDude merged 2 commits into
developfrom
guide-pulse-fixes
Oct 19, 2026
Merged

ClutchplateDude merged 2 commits into
developfrom
guide-pulse-fixes

Conversation

@ClutchplateDude

Copy link
Copy Markdown
Member

Summary

Two fixes for guide-pulse handling, from a user report about guiding clients (not board-specific):

1. Guide pulses arriving during an active pulse were silently dropped

V1.13.14 (#261) added an isSlewingTRK() guard to guidePulse() to refuse pulses when the mount is not tracking (e.g. after the RA tracking limit auto-stop). But slewStatus() reports NOT_SLEWING for the entire duration of any active guide pulse, so the guard also rejected every pulse that arrived while another one was still running — on either axis.

  • Clients that wait for pulse completion before sending the next one (PHD2 via the ASCOM driver polling :GIG#) never overlap pulses, so they are unaffected.
  • Blind senders (INDI/EKOS) fire pulses back-to-back: with typical 500–3000 ms pulses on a 1–2 s cadence, most corrections were dropped and guiding was effectively dead. Both :MG…# replies are empty, so the client cannot detect the drop.

Fix: test the STATUS_TRACKING status flag directly via a new isTracking() accessor. The intended refusal (limit reached, tracking off, parked) is preserved; overlapping pulses get the pre-V1.13.14 last-one-wins semantics again.

2. Info display renders during guide pulses delayed the pulse end

V1.13.7 (#248) added an updateInfoDisplay() call to the else-branch of the guiding block in loop(). A full SSD1306 frame (~1 KB over the default 100 kHz I2C — no Wire.setClock() is configured) blocks loop() for roughly 100 ms, and guiding also bypasses the slew-based 5 Hz refresh throttle (slewStatus() is masked while guiding, so the idle 30 Hz rate applies). The pulse end-time check only runs at the top of each loop() iteration, so every pulse could overshoot its requested duration by up to one render (~100 ms worst case) — real extra guide displacement, since the stepper ISR keeps stepping during the render.

Fix: skip the render while a pulse is running. The display is not left stale — guidePulse() renders once at each pulse start, and the normal end-of-loop() refresh covers the gaps between pulses.

Testing

  • pio run -e ramps green with both changes (-Werror)
  • esp32 fails locally on both pristine develop and this branch — pre-existing local-config issue (Configuration_local_esp32dev.hpp), not from these changes; CI builds clean without local configs
  • Unit tests don't compile Mount.cpp (native env builds core/ports/adapters only); CI covers it

Follow-up idea (not in this PR): Wire.setClock(400000) would cut render time ~4x for all display paths.

🤖 Generated with Claude Code

ClutchplateDude and others added 2 commits October 13, 2026 22:22
V1.13.14 (#261) added an isSlewingTRK() guard to guidePulse() to refuse pulses
when the mount is not tracking (e.g. after the RA tracking limit auto-stop).
However slewStatus() reports NOT_SLEWING for the entire duration of any active
guide pulse, so the guard also silently dropped every pulse that arrived while
another one was still running.

Clients that wait for pulse completion before sending the next one (PHD2 via
the ASCOM driver polling :GIG#) never hit this. Blind senders (INDI/EKOS) do:
with typical 500-3000ms pulses on a 1-2s cadence, most corrections were
dropped and guiding was effectively dead. Both :MG replies are empty, so the
client cannot detect the drop.

Test the STATUS_TRACKING status flag directly via the new isTracking() accessor
instead. This keeps the intended refusal when actually not tracking (limit
reached, tracking off, parked) and restores the pre-V1.13.14 last-one-wins
behavior for overlapping pulses.

Co-Authored-By: Claude Code <noreply@anthropic.com>
V1.13.7 (#248) added an updateInfoDisplay() call to the else-branch of the
guiding block in loop(), refreshing the display mid-pulse. A full SSD1306
frame (~1KB over the default 100kHz I2C, no Wire.setClock is configured)
blocks loop() for roughly 100ms, and guiding also bypasses the slew-based 5Hz
refresh throttle (slewStatus() is masked while guiding, so the idle 30Hz rate
applies). The end-time check only runs at the top of each loop() iteration,
so every pulse could overshoot its requested duration by up to one render.

The display is not left stale: guidePulse() renders once at each pulse start,
and the normal end-of-loop refresh covers the gaps between pulses.

Co-Authored-By: Claude Code <noreply@anthropic.com>
@ClutchplateDude
ClutchplateDude merged commit 3ad0c21 into develop Oct 19, 2026
8 checks passed
@ClutchplateDude
ClutchplateDude deleted the guide-pulse-fixes branch October 19, 2026 00:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants