Skip to content

Derive TCOOLTHRS from Speed, and surface StallGuard arming state - #35

Closed
daniel-frenkel wants to merge 1 commit into
mainfrom
feat/stallguard-tier1
Closed

daniel-frenkel wants to merge 1 commit into
mainfrom
feat/stallguard-tier1

Conversation

@daniel-frenkel

Copy link
Copy Markdown
Member

First step toward making StallGuard usable without hand-tuning registers. This
is the half that needed no guesswork -- it is arithmetic plus a diagnostic.
SGTHRS still depends on installed load and stays manual; that is the calibration
wizard, still to come.

The bug this fixes

StallGuard only reports while TSTEP <= TCOOLTHRS, and TSTEP is inversely
proportional to velocity. Measured on VAL3000 hardware, within 1% from Speed
3000 to 9000 under real curtain load:

TSTEP ~= 374000 / Speed        (microsteps=8, as fixed in valar-core)
Speed TSTEP measured predicted
3000 124 125
6000 62 62.3
9000 41-42 41.6

So the shipped default TCOOLTHRS=100 arms only above Speed ~3740. Below
that StallGuard is off entirely -- no error, no log line, nothing in the UI --
and sensorless homing never completes.

A customer reaches that state just by dragging the Speed slider down for a
quieter curtain. It is also exactly why a bench unit at Speed 1500 looked
broken while the same firmware worked fine at 9000.

Changes

recompute_tcoolthrs derives TCOOLTHRS = 748000 / Speed, on boot and on
every Speed change. 2x cruise TSTEP arms from half of cruise speed upward at any
Speed. That keeps the deliberate low-velocity cutoff -- SG_RESULT is unreliable
when slow, which is the whole point of TCOOLTHRS -- while guaranteeing it
actually engages.

Hooked via !extend on num_speed. Unlike on_stall, appending is what we
want here: core still stores global_speed and pushes the speed to the driver,
then this runs. Verified against the resolved config.

A StallGuard diagnostic text_sensor reporting Armed / Below threshold
/ Ready (stopped) / Never arms at this Speed.

The last state is diagnosed from the configured Speed, not live TSTEP, so a
misconfiguration is visible while the curtain is standing still rather than
being discovered when homing silently fails. Below threshold during
acceleration is normal and expected -- StallGuard is deliberately disarmed at
low velocity.

Verified on the installed curtain unit, over OTA

Speed 9000 TCOOLTHRS auto-derives to 83 (was a hand-set 100)
Speed 1500 moves to 498 -- the configuration that was previously dead
StallGuard sensor reports Ready (stopped) at rest

The auto-derived 83 at Speed 9000 lands right next to the 100 that had been
reached by hand, which is a good sign the rule matches what tuning converges on.

Gates

ENTITY     1 added (StallGuard, diagnostic), 0 removed
BEHAVIOUR  esphome:on_boot::400  number:Speed::set_action (appended, core intact)
           + script:recompute_tcoolthrs, text_sensor:StallGuard

Nothing dropped. esphome compile clean.

Not in this PR

SGTHRS. Measurements show free-running SG_RESULT runs ~270 at Speed 3000 and
~324-450 at 9000, and a hand-grab on the rope takes it to ~130 and ~32
respectively -- so a single fixed threshold cannot serve the range. The rule
that reproduces the current hand-tuned value is
SGTHRS ~= free_SG_at_speed * 0.6 / 2 (97 at Speed 9000 vs the 100 in use),
but it needs a measured free-travel baseline at the actual operating point,
which is the wizard.

Before release

  • Bench: confirm homing still completes at Speed 9000 with auto-derived TCOOLTHRS 83
  • Bench: confirm homing now works at a slow Speed (e.g. 1500) that previously never armed

Aiming for v2.8.0 once those pass.

Generated with Claude Code

…rming

StallGuard only reports while TSTEP <= TCOOLTHRS, and TSTEP is inversely
proportional to velocity. Measured on VAL3000 hardware (microsteps=8), within
1% from Speed 3000 to 9000 under real curtain load:

    TSTEP ~= 374000 / Speed

So the shipped default TCOOLTHRS=100 arms only above Speed ~3740. Below that
StallGuard is switched off entirely -- no error, no log line, nothing in the UI
-- and sensorless homing simply never completes. A customer reaches that state
just by dragging the Speed slider down for a quieter curtain. It is also what
made a bench unit at Speed 1500 look broken while the same firmware worked at
9000.

Two changes:

* recompute_tcoolthrs derives TCOOLTHRS = 748000 / Speed, on boot and whenever
  Speed changes. 2x cruise TSTEP arms from half of cruise speed upward at any
  Speed, preserving the deliberate low-velocity cutoff (SG_RESULT is unreliable
  when slow -- that is what TCOOLTHRS is for) while guaranteeing it engages at
  all. Hooked via !extend on num_speed, which APPENDS, so core still stores
  global_speed and pushes the speed to the driver first; verified against the
  resolved config.

* A "StallGuard" diagnostic text_sensor reporting Armed / Below threshold /
  Ready (stopped) / "Never arms at this Speed". The last is diagnosed from the
  configured Speed rather than live TSTEP, so a misconfiguration is visible
  while the curtain is standing still instead of being discovered when homing
  silently fails. "Below threshold" during acceleration is normal and expected.

Verified on the installed curtain unit over OTA: at Speed 9000 TCOOLTHRS
auto-derives to 83 (was a hand-set 100); setting Speed 1500 moves it to 498,
which is the configuration that was previously dead.

Gates: 1 entity added (StallGuard, diagnostic), 0 removed. Behaviour diff shows
only on_boot 400, num_speed set_action (appended, core actions intact), and the
two new bodies. Compiles clean.

Does not change SGTHRS, which depends on installed load and remains manual --
that is the calibration wizard, still to come.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@daniel-frenkel

Copy link
Copy Markdown
Member Author

Superseded by #36 (v2.8.0), which includes this Tier1 TCOOLTHRS-from-Speed commit plus manual homing, StallGuard opt-in, and the friendly Motion Tuning reorg.

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.

1 participant